mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Compare commits
1 Commits
release-1.
...
onionwrapp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9e088b054 |
10
README.md
10
README.md
@@ -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
|
||||
|
||||
[](https://liberapay.com/Briar/donate)
|
||||
[](https://liberapay.com/Briar/donate) [](https://flattr.com/t/592836/)
|
||||
Bitcoin and BCH: 1NZCKkUCtJV2U2Y9hDb9uq8S7ksFCFGR6K
|
||||
|
||||
@@ -12,9 +12,9 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 33
|
||||
versionCode 10506
|
||||
versionName "1.5.6"
|
||||
targetSdkVersion 31
|
||||
versionCode 10501
|
||||
versionName "1.5.1"
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
@@ -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,17 +16,10 @@ 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;
|
||||
|
||||
@@ -65,12 +57,6 @@ 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);
|
||||
}
|
||||
appContext.registerReceiver(batteryReceiver, filter);
|
||||
}
|
||||
|
||||
@@ -90,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,12 +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) {
|
||||
address = Settings.Secure.getString(ctx.getContentResolver(),
|
||||
"bluetooth_address");
|
||||
if (isValidBluetoothAddress(address)) {
|
||||
return new Pair<>(address, "settings");
|
||||
}
|
||||
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);
|
||||
|
||||
@@ -1,67 +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.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.5:onionwrapper-android-0.0.5.aar:d761854dac454616b3e0ca099b2cd17060365ce4316afe495cc7ae86b6c81d15',
|
||||
'org.briarproject:onionwrapper-core:0.0.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
|
||||
'org.briarproject:snowflake-android:2.5.1:snowflake-android-2.5.1.jar:88ec81c17b1b6fa884d06839dec0330e328b45c89f88c970a213ce91ca8eac87',
|
||||
'org.briarproject:tor-android:0.4.7.14:tor-android-0.4.7.14.jar:d39faa3a8abb116136c191c6ebadf8ea0e1f3e4785076d2c66a7b3b0f26988a2',
|
||||
'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',
|
||||
'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',
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -630,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 ||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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));
|
||||
}});
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,13 +8,11 @@ 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;
|
||||
@@ -22,6 +21,8 @@ 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;
|
||||
@@ -118,7 +119,7 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
|
||||
public void testReceiveKeyThrowsExceptionIfAtEndOfStream()
|
||||
throws Exception {
|
||||
setup();
|
||||
expectReadEof();
|
||||
expectReadRecord(null);
|
||||
|
||||
kat.receiveKey();
|
||||
}
|
||||
@@ -147,7 +148,7 @@ public class KeyAgreementTransportTest extends BrambleMockTestCase {
|
||||
public void testReceiveConfirmThrowsExceptionIfAtEndOfStream()
|
||||
throws Exception {
|
||||
setup();
|
||||
expectReadEof();
|
||||
expectReadRecord(null);
|
||||
|
||||
kat.receiveConfirm();
|
||||
}
|
||||
@@ -208,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));
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ dependencyVerification {
|
||||
'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.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
|
||||
'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',
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +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 org.briarproject.onionwrapper.UnixTorWrapper;
|
||||
|
||||
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, true);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,15 @@ dependencyVerification {
|
||||
'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.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.5:onionwrapper-core-0.0.5.jar:9071678323535cb3dfe0f3add96066037db43ea024333eba0117c759bcbd8d63',
|
||||
'org.briarproject:onionwrapper-java:0.0.5:onionwrapper-java-0.0.5.jar:19503ce1dd661f7119eee8ccd2f22b667a28d746c862dc5bb3d2e476db47e27d',
|
||||
'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',
|
||||
|
||||
@@ -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 |
@@ -25,9 +25,9 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 33
|
||||
versionCode 10506
|
||||
versionName "1.5.6"
|
||||
targetSdkVersion 31
|
||||
versionCode 10501
|
||||
versionName "1.5.1"
|
||||
applicationId "org.briarproject.briar.android"
|
||||
buildConfigField "String", "TorVersion", "\"$tor_version\""
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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,10 +30,8 @@
|
||||
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" />
|
||||
@@ -42,6 +39,7 @@
|
||||
<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"
|
||||
@@ -120,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>
|
||||
|
||||
|
||||
@@ -7,26 +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;
|
||||
|
||||
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();
|
||||
@@ -41,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);
|
||||
}
|
||||
appContext.registerReceiver(receiver, filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopService() {
|
||||
public void stopService() throws ServiceException {
|
||||
if (SDK_INT < 23) return;
|
||||
appContext.unregisterReceiver(receiver);
|
||||
}
|
||||
@@ -62,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,7 +18,6 @@ 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.showOnboardingDialog;
|
||||
@@ -116,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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,17 +19,10 @@ 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 android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||
import static androidx.core.content.ContextCompat.checkSelfPermission;
|
||||
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
|
||||
import static org.briarproject.briar.android.util.UiUtils.setError;
|
||||
|
||||
@@ -45,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();
|
||||
}
|
||||
@@ -132,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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.briar.android.account;
|
||||
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.hardware.biometrics.BiometricPrompt;
|
||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
|
||||
@@ -29,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;
|
||||
@@ -193,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,11 +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 org.briarproject.android.dontkillmelib.wakelock.AndroidWakeLockManager;
|
||||
import org.briarproject.bramble.api.system.Wakeful;
|
||||
@@ -36,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;
|
||||
@@ -184,13 +179,7 @@ public abstract class BriarActivity extends BaseActivity {
|
||||
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,
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
import org.briarproject.briar.api.android.ScreenFilterMonitor.AppDetails;
|
||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -33,7 +32,6 @@ import androidx.fragment.app.DialogFragment;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
|
||||
import static android.view.View.GONE;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -70,7 +68,6 @@ public class ScreenFilterDialogFragment extends DialogFragment {
|
||||
((BaseActivity) requireActivity()).getActivityComponent().inject(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
Activity activity = getActivity();
|
||||
@@ -101,7 +98,7 @@ public class ScreenFilterDialogFragment extends DialogFragment {
|
||||
builder.setNeutralButton(R.string.screen_filter_review_apps,
|
||||
(dialog, which) -> {
|
||||
Intent i = new Intent(ACTION_MANAGE_OVERLAY_PERMISSION);
|
||||
tryToStartActivity(requireActivity(), i);
|
||||
startActivity(i);
|
||||
});
|
||||
}
|
||||
builder.setPositiveButton(R.string.continue_button, (dialog, which) -> {
|
||||
|
||||
@@ -1,27 +1,21 @@
|
||||
package org.briarproject.briar.android.hotspot;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.util.Consumer;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
|
||||
import static android.content.Context.WIFI_SERVICE;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
|
||||
/**
|
||||
* Abstract base class for the ConditionManagers that ensure that the conditions
|
||||
* to open a hotspot are fulfilled. There are different extensions of this for
|
||||
* API levels lower than 29, 29+ and 33+.
|
||||
* API levels lower than 29 and 29+.
|
||||
*/
|
||||
abstract class AbstractConditionManager {
|
||||
|
||||
@@ -34,7 +28,6 @@ abstract class AbstractConditionManager {
|
||||
final Consumer<Boolean> permissionUpdateCallback;
|
||||
protected FragmentActivity ctx;
|
||||
WifiManager wifiManager;
|
||||
private ActivityResultLauncher<Intent> wifiRequest;
|
||||
|
||||
AbstractConditionManager(Consumer<Boolean> permissionUpdateCallback) {
|
||||
this.permissionUpdateCallback = permissionUpdateCallback;
|
||||
@@ -45,12 +38,8 @@ abstract class AbstractConditionManager {
|
||||
*/
|
||||
void init(FragmentActivity ctx) {
|
||||
this.ctx = ctx;
|
||||
wifiManager = (WifiManager) ctx.getApplicationContext()
|
||||
this.wifiManager = (WifiManager) ctx.getApplicationContext()
|
||||
.getSystemService(WIFI_SERVICE);
|
||||
wifiRequest = ctx.registerForActivityResult(
|
||||
new ActivityResultContracts.StartActivityForResult(),
|
||||
result -> permissionUpdateCallback
|
||||
.accept(wifiManager.isWifiEnabled()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,8 +57,6 @@ abstract class AbstractConditionManager {
|
||||
*/
|
||||
abstract boolean checkAndRequestConditions();
|
||||
|
||||
abstract String getWifiSettingsAction();
|
||||
|
||||
void showRationale(Context ctx, @StringRes int title,
|
||||
@StringRes int body, Runnable onContinueClicked,
|
||||
Runnable onDismiss) {
|
||||
@@ -82,13 +69,4 @@ abstract class AbstractConditionManager {
|
||||
builder.show();
|
||||
}
|
||||
|
||||
void requestEnableWiFi() {
|
||||
try {
|
||||
wifiRequest.launch(new Intent(getWifiSettingsAction()));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.briarproject.briar.android.hotspot;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import androidx.activity.result.ActivityResultCaller;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
@@ -19,14 +22,20 @@ import static java.util.logging.Logger.getLogger;
|
||||
* As soon as {@link #checkAndRequestConditions()} returns true,
|
||||
* all conditions are fulfilled.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
class ConditionManager extends AbstractConditionManager {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(ConditionManager.class.getName());
|
||||
|
||||
ConditionManager(Consumer<Boolean> permissionUpdateCallback) {
|
||||
super( permissionUpdateCallback);
|
||||
private final ActivityResultLauncher<Intent> wifiRequest;
|
||||
|
||||
ConditionManager(ActivityResultCaller arc,
|
||||
Consumer<Boolean> permissionUpdateCallback) {
|
||||
super(permissionUpdateCallback);
|
||||
wifiRequest = arc.registerForActivityResult(
|
||||
new StartActivityForResult(),
|
||||
result -> permissionUpdateCallback
|
||||
.accept(wifiManager.isWifiEnabled()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,9 +76,8 @@ class ConditionManager extends AbstractConditionManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWifiSettingsAction() {
|
||||
return Settings.ACTION_WIFI_SETTINGS;
|
||||
private void requestEnableWiFi() {
|
||||
wifiRequest.launch(new Intent(Settings.ACTION_WIFI_SETTINGS));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
package org.briarproject.briar.android.hotspot;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.util.Permission;
|
||||
import org.briarproject.briar.android.util.PermissionUtils;
|
||||
import org.briarproject.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import androidx.activity.result.ActivityResultCaller;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.util.Consumer;
|
||||
@@ -27,13 +28,12 @@ import static org.briarproject.briar.android.util.PermissionUtils.showLocationDi
|
||||
|
||||
/**
|
||||
* This class ensures that the conditions to open a hotspot are fulfilled on
|
||||
* API levels >= 29 and < 33.
|
||||
* API levels >= 29.
|
||||
* <p>
|
||||
* As soon as {@link #checkAndRequestConditions()} returns true,
|
||||
* all conditions are fulfilled.
|
||||
*/
|
||||
@RequiresApi(29)
|
||||
@NotNullByDefault
|
||||
class ConditionManager29 extends AbstractConditionManager {
|
||||
|
||||
private static final Logger LOG =
|
||||
@@ -42,6 +42,7 @@ class ConditionManager29 extends AbstractConditionManager {
|
||||
private Permission locationPermission = Permission.UNKNOWN;
|
||||
|
||||
private final ActivityResultLauncher<String> locationRequest;
|
||||
private final ActivityResultLauncher<Intent> wifiRequest;
|
||||
|
||||
ConditionManager29(ActivityResultCaller arc,
|
||||
Consumer<Boolean> permissionUpdateCallback) {
|
||||
@@ -52,6 +53,11 @@ class ConditionManager29 extends AbstractConditionManager {
|
||||
onRequestPermissionResult(granted);
|
||||
permissionUpdateCallback.accept(TRUE.equals(granted));
|
||||
});
|
||||
wifiRequest = arc.registerForActivityResult(
|
||||
new StartActivityForResult(),
|
||||
result -> permissionUpdateCallback
|
||||
.accept(wifiManager.isWifiEnabled())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,11 +131,6 @@ class ConditionManager29 extends AbstractConditionManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWifiSettingsAction() {
|
||||
return Settings.Panel.ACTION_WIFI;
|
||||
}
|
||||
|
||||
private void onRequestPermissionResult(@Nullable Boolean granted) {
|
||||
if (granted != null && granted) {
|
||||
locationPermission = Permission.GRANTED;
|
||||
@@ -145,4 +146,8 @@ class ConditionManager29 extends AbstractConditionManager {
|
||||
locationRequest.launch(ACCESS_FINE_LOCATION);
|
||||
}
|
||||
|
||||
private void requestEnableWiFi() {
|
||||
wifiRequest.launch(new Intent(Settings.Panel.ACTION_WIFI));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
package org.briarproject.briar.android.hotspot;
|
||||
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.util.Permission;
|
||||
import org.briarproject.briar.android.util.PermissionUtils;
|
||||
import org.briarproject.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import androidx.activity.result.ActivityResultCaller;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.core.util.Consumer;
|
||||
|
||||
import static android.Manifest.permission.NEARBY_WIFI_DEVICES;
|
||||
import static androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
|
||||
/**
|
||||
* This class ensures that the conditions to open a hotspot are fulfilled on
|
||||
* API levels >= 33.
|
||||
* <p>
|
||||
* As soon as {@link #checkAndRequestConditions()} returns true,
|
||||
* all conditions are fulfilled.
|
||||
*/
|
||||
@RequiresApi(33)
|
||||
@NotNullByDefault
|
||||
class ConditionManager33 extends AbstractConditionManager {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(ConditionManager33.class.getName());
|
||||
|
||||
private Permission nearbyWifiPermission = Permission.UNKNOWN;
|
||||
|
||||
private final ActivityResultLauncher<String> nearbyWifiRequest;
|
||||
|
||||
ConditionManager33(ActivityResultCaller arc,
|
||||
Consumer<Boolean> permissionUpdateCallback) {
|
||||
super(permissionUpdateCallback);
|
||||
// permissionUpdateCallback receives false if permissions were denied
|
||||
nearbyWifiRequest = arc.registerForActivityResult(
|
||||
new RequestPermission(), granted -> {
|
||||
onRequestPermissionResult(granted);
|
||||
permissionUpdateCallback.accept(TRUE.equals(granted));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
void onStart() {
|
||||
nearbyWifiPermission = Permission.UNKNOWN;
|
||||
}
|
||||
|
||||
private boolean areEssentialPermissionsGranted() {
|
||||
boolean isWifiEnabled = wifiManager.isWifiEnabled();
|
||||
if (LOG.isLoggable(INFO)) {
|
||||
LOG.info(String.format("areEssentialPermissionsGranted(): " +
|
||||
"nearbyWifiPermission? %s, " +
|
||||
"wifiManager.isWifiEnabled()? %b",
|
||||
nearbyWifiPermission, isWifiEnabled));
|
||||
}
|
||||
return nearbyWifiPermission == Permission.GRANTED && isWifiEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean checkAndRequestConditions() {
|
||||
if (areEssentialPermissionsGranted()) return true;
|
||||
|
||||
if (nearbyWifiPermission == Permission.UNKNOWN) {
|
||||
requestPermissions();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the location permission has been permanently denied, ask the
|
||||
// user to change the setting
|
||||
if (nearbyWifiPermission == Permission.PERMANENTLY_DENIED) {
|
||||
PermissionUtils.showDenialDialog(ctx,
|
||||
R.string.permission_nearby_devices_title,
|
||||
R.string.permission_hotspot_nearby_wifi_denied_body,
|
||||
() -> permissionUpdateCallback.accept(false));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should we show the rationale for location permission?
|
||||
if (nearbyWifiPermission == Permission.SHOW_RATIONALE) {
|
||||
showRationale(ctx,
|
||||
R.string.permission_location_title,
|
||||
R.string.permission_hotspot_nearby_wifi_request_body,
|
||||
this::requestPermissions,
|
||||
() -> permissionUpdateCallback.accept(false));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If Wifi is not enabled, we show the rationale for enabling Wifi?
|
||||
if (!wifiManager.isWifiEnabled()) {
|
||||
showRationale(ctx, R.string.wifi_settings_title,
|
||||
R.string.wifi_settings_request_enable_body,
|
||||
this::requestEnableWiFi,
|
||||
() -> permissionUpdateCallback.accept(false));
|
||||
return false;
|
||||
}
|
||||
|
||||
// we shouldn't usually reach this point, but if we do, return false
|
||||
// anyway to force a recheck. Maybe some condition changed in the
|
||||
// meantime.
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getWifiSettingsAction() {
|
||||
return Settings.Panel.ACTION_WIFI;
|
||||
}
|
||||
|
||||
private void onRequestPermissionResult(@Nullable Boolean granted) {
|
||||
if (granted != null && granted) {
|
||||
nearbyWifiPermission = Permission.GRANTED;
|
||||
} else if (shouldShowRequestPermissionRationale(ctx,
|
||||
NEARBY_WIFI_DEVICES)) {
|
||||
nearbyWifiPermission = Permission.SHOW_RATIONALE;
|
||||
} else {
|
||||
nearbyWifiPermission = Permission.PERMANENTLY_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
private void requestPermissions() {
|
||||
nearbyWifiRequest.launch(NEARBY_WIFI_DEVICES);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import static android.view.View.VISIBLE;
|
||||
import static androidx.transition.TransitionManager.beginDelayedTransition;
|
||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||
import static org.briarproject.briar.android.hotspot.HotspotViewModel.getApkFileName;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -103,7 +102,7 @@ public class FallbackFragment extends BaseFragment {
|
||||
i.putExtra(EXTRA_STREAM, uri);
|
||||
i.setType("*/*"); // gives us all sharing options
|
||||
i.addFlags(FLAG_GRANT_READ_URI_PERMISSION);
|
||||
tryToStartActivity(requireActivity(), Intent.createChooser(i, null));
|
||||
startActivity(Intent.createChooser(i, null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,10 +49,8 @@ public class HotspotIntroFragment extends Fragment {
|
||||
private TextView progressTextView;
|
||||
|
||||
private final AbstractConditionManager conditionManager = SDK_INT < 29 ?
|
||||
new ConditionManager(this::onPermissionUpdate) :
|
||||
SDK_INT >= 33 ?
|
||||
new ConditionManager33(this, this::onPermissionUpdate) :
|
||||
new ConditionManager29(this, this::onPermissionUpdate);
|
||||
new ConditionManager(this, this::onPermissionUpdate) :
|
||||
new ConditionManager29(this, this::onPermissionUpdate);
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
@@ -89,6 +87,7 @@ public class HotspotIntroFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void onButtonClick(View view) {
|
||||
startButton.setEnabled(false);
|
||||
startHotspotIfConditionsFulfilled();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,19 +22,13 @@ import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import static android.Manifest.permission.POST_NOTIFICATIONS;
|
||||
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 android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
||||
import static androidx.core.content.ContextCompat.checkSelfPermission;
|
||||
import static org.briarproject.bramble.api.crypto.DecryptionResult.KEY_STRENGTHENER_ERROR;
|
||||
import static org.briarproject.bramble.api.crypto.DecryptionResult.SUCCESS;
|
||||
import static org.briarproject.briar.android.login.LoginUtils.createKeyStrengthenerErrorDialog;
|
||||
@@ -58,10 +52,6 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
|
||||
private TextInputLayout input;
|
||||
private TextInputEditText password;
|
||||
|
||||
private final ActivityResultLauncher<String> requestPermissionLauncher =
|
||||
registerForActivityResult(new RequestPermission(), isGranted ->
|
||||
validatePassword());
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
@@ -119,17 +109,6 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
|
||||
hideSoftKeyboard(password);
|
||||
signInButton.setVisibility(INVISIBLE);
|
||||
progress.setVisibility(VISIBLE);
|
||||
if (SDK_INT >= 33 &&
|
||||
checkSelfPermission(requireContext(), POST_NOTIFICATIONS) !=
|
||||
PERMISSION_GRANTED) {
|
||||
// this calls validatePassword() when it returns
|
||||
requestPermissionLauncher.launch(POST_NOTIFICATIONS);
|
||||
} else {
|
||||
validatePassword();
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePassword() {
|
||||
viewModel.validatePassword(password.getText().toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.briar.android.reporting;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -32,11 +33,13 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
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.briar.android.util.UiUtils.onSingleLinkClick;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -177,7 +180,13 @@ public class ReportFormFragment extends BaseFragment {
|
||||
private void triggerPrivacyPolicy() {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse("https://briarproject.org/privacy-policy/\\"));
|
||||
tryToStartActivity(requireActivity(), i);
|
||||
try {
|
||||
startActivity(i);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
Toast.makeText(requireContext(),
|
||||
R.string.error_start_activity, LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.briar.android.settings;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
@@ -7,6 +8,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.briar.BuildConfig;
|
||||
import org.briarproject.briar.R;
|
||||
@@ -19,9 +21,10 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import static android.content.Intent.ACTION_VIEW;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -82,9 +85,16 @@ public class AboutFragment extends Fragment {
|
||||
}
|
||||
|
||||
private void goToUrl(String url) {
|
||||
Intent i = new Intent(ACTION_VIEW);
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
tryToStartActivity(requireActivity(), i);
|
||||
try {
|
||||
startActivity(i);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
Toast.makeText(requireContext(),
|
||||
R.string.error_start_activity, LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,14 +24,11 @@ import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceGroup;
|
||||
|
||||
import static android.content.Intent.ACTION_SEND;
|
||||
import static android.content.Intent.EXTRA_TEXT;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||
import static org.briarproject.briar.android.util.UiUtils.launchActivityToOpenFile;
|
||||
import static org.briarproject.briar.android.util.UiUtils.triggerFeedback;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -40,14 +37,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||
public static final String SETTINGS_NAMESPACE = "android-ui";
|
||||
|
||||
private static final String PREF_KEY_AVATAR = "pref_key_avatar";
|
||||
private static final String PREF_KEY_SHARE_LINK = "pref_key_share_app_link";
|
||||
private static final String PREF_KEY_FEEDBACK = "pref_key_send_feedback";
|
||||
private static final String PREF_KEY_DEV = "pref_key_dev";
|
||||
private static final String PREF_KEY_EXPLODE = "pref_key_explode";
|
||||
private static final String PREF_KEY_MAILBOX = "pref_key_mailbox";
|
||||
|
||||
private static final String DOWNLOAD_URL = "https://briarproject.org/download/";
|
||||
|
||||
@Inject
|
||||
ViewModelProvider.Factory viewModelFactory;
|
||||
|
||||
@@ -92,17 +86,6 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||
return true;
|
||||
});
|
||||
|
||||
Preference prefShareLink =
|
||||
requireNonNull(findPreference(PREF_KEY_SHARE_LINK));
|
||||
prefShareLink.setOnPreferenceClickListener(preference -> {
|
||||
String text = getString(R.string.share_app_link_text, DOWNLOAD_URL);
|
||||
Intent sendIntent = new Intent(ACTION_SEND);
|
||||
sendIntent.putExtra(EXTRA_TEXT, text);
|
||||
sendIntent.setType("text/plain");
|
||||
tryToStartActivity(requireActivity(),
|
||||
Intent.createChooser(sendIntent, null));
|
||||
return true;
|
||||
});
|
||||
Preference prefFeedback =
|
||||
requireNonNull(findPreference(PREF_KEY_FEEDBACK));
|
||||
prefFeedback.setOnPreferenceClickListener(preference -> {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package org.briarproject.briar.android.util;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.location.LocationManager;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
||||
@@ -27,10 +29,10 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import static android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS;
|
||||
import static android.widget.Toast.LENGTH_LONG;
|
||||
import static androidx.core.content.ContextCompat.checkSelfPermission;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
|
||||
import static org.briarproject.briar.android.util.UiUtils.tryToStartActivity;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -45,7 +47,7 @@ public class PermissionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPermissionGranted(Context ctx, String permission) {
|
||||
public static boolean isPermissionGranted(Context ctx, String permission) {
|
||||
return checkSelfPermission(ctx, permission) ==
|
||||
PERMISSION_GRANTED;
|
||||
}
|
||||
@@ -66,7 +68,7 @@ public class PermissionUtils {
|
||||
gotPermission(ctx, grantedMap, BLUETOOTH_SCAN);
|
||||
}
|
||||
|
||||
private static DialogInterface.OnClickListener getGoToSettingsListener(
|
||||
public static DialogInterface.OnClickListener getGoToSettingsListener(
|
||||
Context context) {
|
||||
return (dialog, which) -> {
|
||||
Intent i = new Intent();
|
||||
@@ -74,7 +76,7 @@ public class PermissionUtils {
|
||||
i.addCategory(CATEGORY_DEFAULT);
|
||||
i.setData(Uri.parse("package:" + APPLICATION_ID));
|
||||
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
tryToStartActivity(context, i);
|
||||
context.startActivity(i);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -121,7 +123,12 @@ public class PermissionUtils {
|
||||
builder.setPositiveButton(R.string.permission_location_setting_button,
|
||||
(dialog, which) -> {
|
||||
Intent i = new Intent(ACTION_LOCATION_SOURCE_SETTINGS);
|
||||
tryToStartActivity(ctx, i);
|
||||
try {
|
||||
ctx.startActivity(i);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(ctx, R.string.error_start_activity,
|
||||
LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
builder.show();
|
||||
}
|
||||
|
||||
@@ -157,15 +157,6 @@ public class UiUtils {
|
||||
ta.commit();
|
||||
}
|
||||
|
||||
public static void tryToStartActivity(Context ctx, Intent intent) {
|
||||
try {
|
||||
ctx.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getContactDisplayName(Author author,
|
||||
@Nullable String alias) {
|
||||
String name = author.getName();
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?android:attr/textColorPrimary"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M21,12L14,5V9C7,10 4,15 3,20C5.5,16.5 9,14.9 14,14.9V19L21,12Z" />
|
||||
</vector>
|
||||
@@ -13,10 +13,10 @@
|
||||
android:layout_margin="@dimen/margin_medium"
|
||||
android:contentDescription="@string/info"
|
||||
android:drawablePadding="@dimen/margin_medium"
|
||||
android:drawableTint="?attr/colorControlNormal"
|
||||
android:gravity="center_vertical"
|
||||
app:drawableLeftCompat="@drawable/ic_info_dark"
|
||||
app:drawableStartCompat="@drawable/ic_info_dark"
|
||||
app:drawableTint="?attr/colorControlNormal"
|
||||
tools:text="Did you know that if you took all the veins out of your body and laid them out end to end, you would die?" />
|
||||
|
||||
</merge>
|
||||
BIN
briar-android/src/main/res/mipmap-xhdpi/tv_banner.png
Normal file
BIN
briar-android/src/main/res/mipmap-xhdpi/tv_banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.0 KiB |
@@ -47,6 +47,10 @@
|
||||
<item quantity="one">Това е тестова версия на Briar. Вашият акаунт ще бъде изтече след %d ден и не може да бъде подновена.</item>
|
||||
<item quantity="other">Това е изпитателно издание на Briar. Валидността на профила ще изтече след %d дена и не може да бъде подновена.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 не се поддържа. Briar ще спре да работи на %s (след %d ден). Инсталирайте Briar на друго устройство и създайте нов профил.</item>
|
||||
<item quantity="other">Android 4 не се поддържа. Briar ще спре да работи на %s (след %d дена). Инсталирайте Briar на друго устройство и създайте нов профил.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Софтуерът е с изтекъл срок.\nБлагодарим за изпитването!</string>
|
||||
<string name="download_briar">За да продължите да използвате Briar изтеглете последното издание.</string>
|
||||
<string name="create_new_account">Ще трябва да създадете нов профил, но ще можете да използвате същия прякор.</string>
|
||||
@@ -589,7 +593,7 @@
|
||||
<!--Mailbox-->
|
||||
<string name="mailbox_settings_title">Пощенска кутия</string>
|
||||
<string name="mailbox_setup_title">Настройка като пощенска кутия</string>
|
||||
<string name="mailbox_setup_intro">Пощенската кутия дава възможност да получавате съобщения от вашите контакти докато сте без достъп до мрежа. Кутията ще получава съобщенията и ще ги пази докато дойдете на линия.\n\nИнсталирайте приложението Birar Mailbox на резервно устройство. Снабдете го със захранване и постоянен достъп до безжична мрежа, така че да е винаги на линия.</string>
|
||||
<string name="mailbox_setup_intro">Пощенската кутия ви дава възможност да получавате съобщения от вашите контакти докато сте извън мрежа. Кутията ще получава съобщенията и ще ги пази докато дойдете на линия.\n\nИнсталирайте приложението Birar Mailbox на резервно устройство. Снабдете го със захранване и постоянен достъп до безжична мрежа, така че да е винаги на линия.</string>
|
||||
<string name="mailbox_setup_download">Първо инсталирайте приложението Mailbox на друго устройство като потърсите „Briar Mailbox“ в Google Play или от където сте инсталирали Briar.\n
|
||||
\nСлед това свържете Mailbox с Briar чрез сканиране на кода за QR от приложението Mailbox.</string>
|
||||
<string name="mailbox_setup_download_link">Споделяне на препратка за изтегляне</string>
|
||||
@@ -631,7 +635,7 @@
|
||||
<string name="mailbox_status_unlink_button">Прекъсване на връзката</string>
|
||||
<string name="mailbox_status_unlink_dialog_title">Желаете ли да прекъснете връзката с пощенската кутия?</string>
|
||||
<string name="mailbox_status_unlink_dialog_question">Сигурни ли сте, че желаете да прекъснете връзката с пощенската кутия?</string>
|
||||
<string name="mailbox_status_unlink_dialog_warning">Ако прекъснете връзката с пощенската кутия, няма да получавате съобщения докато Briar е без достъп до мрежа.</string>
|
||||
<string name="mailbox_status_unlink_dialog_warning">Ако прекъснете връзката с пощенската кутия, няма да получавате съобщения докато Briar е без мрежа.</string>
|
||||
<string name="mailbox_status_unlink_no_wipe_title">Връзката с пощенската кутия е прекъсната</string>
|
||||
<string name="mailbox_status_unlink_no_wipe_message">За да завършите процеса, следващия път, когато имате достъп до устройството с пощенската кутия, отворете приложението на пощенската кутия и докоснете бутона „Прекъсване на връзката“.\n\nДаже и вече нямате достъп до устройството с пощенската кутия - не се притеснявайте. Вашата информация е шифрована, така че ще остане защитена, дори и да не завършите този процес.</string>
|
||||
<string name="mailbox_status_unlink_success">Връзката с пощенската кутия е прекъсната</string>
|
||||
@@ -681,8 +685,6 @@
|
||||
<string name="disappearing_messages_summary">Бъдещите съобщения в разговора изчезват след 7\u00A0дни</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Действия</string>
|
||||
<string name="share_app_link">Споделяне на препратка за изтегляне</string>
|
||||
<string name="share_app_link_text">Изтеглете Брайар от %s</string>
|
||||
<string name="send_feedback">Изпращане на обратна връзка</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Предупреждение за препратка</string>
|
||||
@@ -732,7 +734,6 @@
|
||||
<string name="permission_camera_title">Разрешение за камера</string>
|
||||
<string name="permission_camera_request_body">За да сканира кода за QR, Briar трябва да използва камерата.</string>
|
||||
<string name="permission_location_title">Разрешение за местоположение</string>
|
||||
<string name="permission_nearby_devices_title">Разрешение за устройства наблизо</string>
|
||||
<string name="permission_location_request_body">За да открива устройства чрез Bluetooth, Briar се нуждае от разрешение за достъп до местоположението.\n\nBriar не го пази и не го споделя с никого.</string>
|
||||
<string name="permission_camera_location_title">Камера и местоположение</string>
|
||||
<string name="permission_camera_location_request_body">За да сканира кода за QR, Briar трябва да използва камерата.\n\nЗа да открива устройства чрез Bluetooth, Briar трябва да има достъп до местоположението.\n\nBriar не го пази и не го споделя с никого.</string>
|
||||
@@ -759,21 +760,19 @@
|
||||
<!--Connections Screen-->
|
||||
<string name="transports_help_text">Briar може да се свърже с контактите ви през интернет, Wi-Fi или Bluetooth.\n\nЗа повече поверителност цялата връзка към интернет се пренасочва през мрежата на Tor.\n\nАко даден контакт може да бъде достъпен чрез няколко метода Briar ги използва успоредно.</string>
|
||||
<!--Share app offline-->
|
||||
<string name="hotspot_title">Споделяне на приложението без достъп до мрежа</string>
|
||||
<string name="hotspot_title">Споделяне на приложението извън мрежа</string>
|
||||
<string name="hotspot_intro">Споделете приложението с някого наблизо през Wi-Fi на устройствата, без използване на връзка с интернет.
|
||||
\n\nВашето устройство ще създаде безжична точка за достъп. Хората наблизо могат да се свържат към нея и да изтеглят Briar от вашето устройство.</string>
|
||||
<string name="hotspot_button_start_sharing">Включване на безжична точка</string>
|
||||
<string name="hotspot_button_stop_sharing">Спиране на безжична точка</string>
|
||||
<string name="hotspot_progress_text_start">Настройване на безжична точка…</string>
|
||||
<string name="hotspot_notification_channel_title">Безжична точка за достъп</string>
|
||||
<string name="hotspot_notification_title">Споделяне на Briar без достъп до мрежа</string>
|
||||
<string name="hotspot_notification_title">Споделяне на Briar извън мрежа</string>
|
||||
<string name="hotspot_button_connected">Напред</string>
|
||||
<string name="permission_hotspot_location_request_body">За да създаде безжична точка за достъп, Briar се нуждае от разрешение за достъп до местоположението.\n\nBriar не го пази и не го споделя с никого.</string>
|
||||
<string name="permission_hotspot_location_request_precise_body">За да създаде безжична точка за достъп, Briar се нуждае от разрешение за достъп до точното местоположение.\n\nBriar не го пази и не го споделя с никого.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Отказахте достъп до местоположението, но достъп е необходим за създаване на безжична точка за достъп.\n\nОбмислете дали да не дадете разрешение.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Отказахте достъп до точното местоположение, но достъп е необходим за създаване на безжична точка за достъп.\n\nОбмислете дали да не дадете разрешение.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">За да създаде безжична точка за достъп, Briar се нуждае от права за достъп до околните устройства.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Отказахте достъп до околните устройства, но той е необходим за създаване на безжична точка за достъп.\n\nОбмислете дали да не дадете разрешение.</string>
|
||||
<string name="wifi_settings_title">Настройки на Wi-Fi</string>
|
||||
<string name="wifi_settings_request_enable_body">За да създаде безжична точка за достъп, Briar се нуждае от безжична мрежа. Включете Wi-Fi.</string>
|
||||
<string name="hotspot_tab_manual">Ръчно</string>
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
<item quantity="one">Aquesta és una versió de prova de Briar. El vostre compte expira en %d dia i no es pot renovar.</item>
|
||||
<item quantity="other">Aquesta és una versió de prova de Briar. El vostre compte caducarà en %d dies i no es podrà renovar.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">L\'Android 4 ja no és compatible. El Briar deixarà de funcionar a %s (d\'aquí a %d dia). Instal·leu el Briar en un dispositiu més nou i creeu un compte nou.</item>
|
||||
<item quantity="other">L\'Android 4 ja no és compatible. El Briar deixarà de funcionar a %s (d\'aquí a %d dies). Instal·leu el Briar en un dispositiu més nou i creeu un compte nou.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Aquesta versió de Briar ha caducat.\nGràcies per haver-lo provat!</string>
|
||||
<string name="download_briar">Per continuar utilitzant Briar, baixeu la darrera versió.</string>
|
||||
<string name="create_new_account">Haureu de crear un compte nou, però podeu utilitzar el mateix sobrenom.</string>
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
<item quantity="many">Toto je testovací verze Briar. Váš účet a jeho platnost vyprší po %d dnech a není možné ho obnovit.</item>
|
||||
<item quantity="other">Toto je testovací verze Briar. Váš účet a jeho platnost vyprší po %d dnech a není možné ho obnovit.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Systém Android 4 již není podporován. Briar přestane fungovat %s (za %d den). Nainstalujte si prosím Briar na novější zařízení a vytvořte si nový účet.</item>
|
||||
<item quantity="few">Systém Android 4 již není podporován. Briar přestane fungovat %s (za %d dny). Nainstalujte si prosím Briar na novější zařízení a vytvořte si nový účet.</item>
|
||||
<item quantity="many">Systém Android 4 již není podporován. Briar přestane fungovat %s (za %d dní). Nainstalujte si prosím Briar na novější zařízení a vytvořte si nový účet.</item>
|
||||
<item quantity="other">Systém Android 4 již není podporován. Briar přestane fungovat %s (za %d dní). Nainstalujte si prosím Briar na novější zařízení a vytvořte si nový účet.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Platnost tohoto software vypršela.\nDěkujeme za jeho otestování!</string>
|
||||
<string name="download_briar">Pro pokračování v používání aplikace Briar si prosím stáhněte její nejnovější verzi.</string>
|
||||
<string name="create_new_account">Budete potřebovat vytvořit nový účet, ale můžete použít stejné uživatelské jméno.</string>
|
||||
@@ -715,8 +721,6 @@
|
||||
<string name="disappearing_messages_summary">Nastavte automatické zmizení zpráv této konverzace po 7\u00A0dnech.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Akce</string>
|
||||
<string name="share_app_link">Sdílet odkaz ke stažení</string>
|
||||
<string name="share_app_link_text">Stáhnout Briar z %s</string>
|
||||
<string name="send_feedback">Poslat zpětnou vazbu</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Odkaz varování</string>
|
||||
@@ -766,7 +770,6 @@
|
||||
<string name="permission_camera_title">Oprávnění pro přístup k fotoaparátu</string>
|
||||
<string name="permission_camera_request_body">Pro scan QR kódu, Briar vyžaduje přístup k fotoaparátu.</string>
|
||||
<string name="permission_location_title">Místní povolení</string>
|
||||
<string name="permission_nearby_devices_title">Povolení pro zařízení v okolí</string>
|
||||
<string name="permission_location_request_body">Aby mohl Briar najít zařízení Bluetooth, potřebuje Briar povolení zjistit vaše umístění.\n\nBriar neukládá vaše umístění ani ho s nikým nesdílí.</string>
|
||||
<string name="permission_camera_location_title">Fotoaparát a umístění</string>
|
||||
<string name="permission_camera_location_request_body">Pro oskenování QR kódu potřebuje Briar přístup k fotoaparátu.\n\nPro nalezení zařízení Bluetooth potřebuje Briar povolení zjistit vaše umístění.\n\nBriar neukládá vaše umístění ani ho s nikým nesdílí.</string>
|
||||
@@ -806,8 +809,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Pro vytvoření Wi-Fi hotspotu potřebuje Briar povolení zjistit vaše přesné umístění.\n\nBriar neukládá vaše umístění ani ho s nikým nesdílí.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Zamítli jste přístup k vašemu umístění. Briar přístup potřebuje, aby mohl vytvořit Wi-Fi hotspot.\n\nProsím zvažte povolení přístupu.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Zamítli jste přístup k vašemu přesnému umístění. Briar přístup potřebuje, aby mohl vytvořit Wi-Fi hotspot.\n\nProsím zvažte povolení přístupu.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Pro vytvoření Wi-Fi hotspotu, potřebuje Briar povolení přístupu k zařízením v okolí.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Odmítli jste přístup k zařízením v okolí i když Briar potřebuje povolení, aby mohl vytvořit Wi-Fi hotspot.\n\nProsím zvažte udělení přístupu.</string>
|
||||
<string name="wifi_settings_title">Wi-Fi volba</string>
|
||||
<string name="wifi_settings_request_enable_body">Pro vytvoření Wi-Fi hotspotu potřebuje Briar využít Wi-Fi. Prosím zapněte ji.</string>
|
||||
<string name="hotspot_tab_manual">Manuálně</string>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<string name="dialog_title_lost_password">Passwort vergessen</string>
|
||||
<string name="dialog_message_lost_password">Dein Briar-Konto ist verschlüsselt auf deinem Gerät und nicht in der Cloud gespeichert, deshalb kannst du dein Passwort nicht zurücksetzen. Willst du dein Konto löschen und neu beginnen?\n\nAchtung: Deine bestehenden Identitäten, Kontakte und Nachrichten gehen dann für immer verloren.</string>
|
||||
<string name="startup_failed_activity_title">Fehler beim Starten von Briar</string>
|
||||
<string name="startup_failed_clock_error">Briar konnte nicht gestartet werden, weil die Uhr deines Geräts falsch eingestellt ist.\n\nBitte stelle die Uhr deines Geräts auf die richtige Zeit ein und versuche es erneut.</string>
|
||||
<string name="startup_failed_clock_error">Briar konnte nicht gestartet werden, weil die Uhr deines Geräts falsch eingestellt ist.\n\Bitte stelle die Uhr deines Geräts auf die richtige Zeit ein und versuche es erneut.</string>
|
||||
<string name="startup_failed_db_error">Briar konnte die Datenbank mit deinem Konto, deinen Kontakten und deinen Nachrichten nicht öffnen.\n\nBitte aktualisiere auf die neueste Version der App und versuche es erneut, oder richte ein neues Konto ein, indem du bei der Passwortabfrage \"Ich habe mein Passwort vergessen\" wählst.</string>
|
||||
<string name="startup_failed_data_too_old_error">Dein Konto wurde mit einer alten Version dieser App erstellt und kann mit dieser Version nicht geöffnet werden.\n\nDu musst entweder die alte Version neu installieren oder ein neues Konto einrichten, indem du bei der Passwortabfrage \"Ich habe mein Passwort vergessen\" wählst.</string>
|
||||
<string name="startup_failed_data_too_new_error">Dein Konto wurde mit einer neueren Version dieser App erstellt und kann mit dieser Version nicht geöffnet werden.\n\nBitte aktualisiere auf die neueste Version und versuche es erneut.</string>
|
||||
@@ -49,6 +49,10 @@
|
||||
<item quantity="one">Dies ist eine Testversion von Briar. Dein Konto läuft in %d Tag ab und kann nicht verlängert werden.</item>
|
||||
<item quantity="other">Dies ist eine Testversion von Briar. Dein Konto läuft in %d Tagen ab und kann nicht verlängert werden.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 wird nicht mehr unterstützt. Briar wird nicht mehr auf %s funktionieren (in %d Tag). Bitte installiere es auf einem neueren Gerät und erstelle ein neues Konto.</item>
|
||||
<item quantity="other">Android 4 wird nicht mehr unterstützt. Briar wird nicht mehr auf %s funktionieren (in %dTagen). Bitte installiere es auf einem neueren Gerät und erstelle ein neues Konto.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Diese Software ist abgelaufen.\nDanke, dass du Briar getestet hast!</string>
|
||||
<string name="download_briar">Bitte lade die aktuelle Version von Briar herunter, um es weiter zu benutzen.</string>
|
||||
<string name="create_new_account">Du wirst ein neues Konto erstellen müssen, wobei du jedoch wieder denselben Spitznamen verwenden kannst.</string>
|
||||
@@ -689,8 +693,6 @@
|
||||
<string name="disappearing_messages_summary">Zukünftige Nachrichten in dieser Unterhaltung werden automatisch nach 7\u00A0Tagen gelöscht.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Aktionen</string>
|
||||
<string name="share_app_link">Downloadlink teilen</string>
|
||||
<string name="share_app_link_text">Briar bei %s herunterladen</string>
|
||||
<string name="send_feedback">Feedback senden</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Link-Warnung</string>
|
||||
@@ -740,7 +742,6 @@
|
||||
<string name="permission_camera_title">Berechtigung Kamera</string>
|
||||
<string name="permission_camera_request_body">Um den QR-Code zu scannen, benötigt Briar Zugriff auf die Kamera.</string>
|
||||
<string name="permission_location_title">Berechtigung Standort</string>
|
||||
<string name="permission_nearby_devices_title">Berechtigung für Geräte in der Nähe</string>
|
||||
<string name="permission_location_request_body">Um Bluetooth-Geräte zu finden, braucht Briar Zugriff auf deinen Standort.\n\nBriar speichert weder deinen Standort noch gibt es ihn an andere weiter.</string>
|
||||
<string name="permission_camera_location_title">Kamera und Standort</string>
|
||||
<string name="permission_camera_location_request_body">Um den QR-Code zu scannen, braucht Briar Zugriff auf die Kamera.\n\nUm Bluetooth-Geräte zu finden, braucht Briar Zugriff auf deinen Standort.\n\nBriar speichert weder deinen Standort noch gibt es ihn an andere weiter.</string>
|
||||
@@ -780,8 +781,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Um einen WLAN-Hotspot zu erstellen, benötigt Briar die Berechtigung, auf deinen genauen Standort zuzugreifen.\n\nBriar speichert weder deinen Standort noch gibt es ihn an andere weiter.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Du hast den Zugriff auf deinen Standort verweigert, aber Briar benötigt diese Berechtigung, um einen WLAN-Hotspot zu erstellen.\n\nBitte überlege, ob du Zugriff gewährst.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Du hast den Zugriff auf deinen genauen Standort verweigert, aber Briar benötigt diese Berechtigung, um einen WLAN-Hotspot zu erstellen.\n\nBitte überlege, ob du Zugriff gewährst.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Um einen WLAN-Hotspot zu erstellen, benötigt Briar die Erlaubnis, auf Geräte in der Nähe zuzugreifen.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Du hast den Zugriff auf Geräte in der Nähe verweigert, aber Briar benötigt diese Berechtigung, um einen WLAN-Hotspot zu erstellen.\n\nBitte erwäge, den Zugriff zu gewähren.</string>
|
||||
<string name="wifi_settings_title">WLAN-Einstellungen</string>
|
||||
<string name="wifi_settings_request_enable_body">Um einen WLAN-Hotspot zu erstellen, benötigt Briar das WLAN. Bitte aktiviere es.</string>
|
||||
<string name="hotspot_tab_manual">Manuell</string>
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
<item quantity="many">Esta es una versión de prueba de Briar. Tu cuenta expirará en %d días y no podrá ser renovada.</item>
|
||||
<item quantity="other">Esta es una versión de prueba de Briar. Tu cuenta expirará en %d días y no podrá ser renovada.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 ya no es soportado. Briar dejará de funcionar sobre %s (en %d días). Por favor, instala Briar en un dispositivo más nuevo y crea una cuenta nueva.</item>
|
||||
<item quantity="many">Android 4 ya no es soportado. Briar dejará de funcionar sobre %s (en %d días). Por favor, instala Briar en un dispositivo más nuevo y crea una cuenta nueva.</item>
|
||||
<item quantity="other">Android 4 ya no es soportado. Briar dejará de funcionar sobre %s (en %d días). Por favor, instala Briar en un dispositivo más nuevo y crea una cuenta nueva.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Este programa ha caducado.\n¡Gracias por probarlo!</string>
|
||||
<string name="download_briar">Para continuar usando Briar, por favor descarga la versión mas reciente.</string>
|
||||
<string name="create_new_account">Necesitarás crear una nueva cuenta, pero puedes usar el mismo nombre de usuario.</string>
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
<item quantity="one">این یک نسخه آزمایشی از Briar (برایر) می باشد. حساب کاربری شما در %d روز آینده به پایان می رسد و امکان تمدید آن وجود نخواهد داشت.</item>
|
||||
<item quantity="other">این یک نسخه آزمایشی از Briar (برایر) می باشد. حساب کاربری شما در %d روز آینده به پایان می رسد و امکان تمدید آن وجود نخواهد داشت.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">اندروید 4 دیگر پشتیبانی نمیشود. Briar (در عرض %d روز) کار بر روی %s را متوقف خواهد کرد. لطفا Briar را در دستگاه جدیدتر نصب کنید و یک حساب کاربری جدید ایجاد کنید.</item>
|
||||
<item quantity="other">اندروید 4 دیگر پشتیبانی نمیشود. Briar (در عرض %d روز) کار بر روی %s را متوقف خواهد کرد. لطفا Briar را در دستگاه جدیدتر نصب کنید و یک حساب کاربری جدید ایجاد کنید.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">این نرم افزار منقضی شده است.
|
||||
|
||||
بابت تست از شما سپاسگزاریم.</string>
|
||||
@@ -696,7 +700,7 @@
|
||||
<string name="mailbox_error_wizard_info2">لطفا هنگامی که به دستگاه دسترسی دارید به این صفحه بازگردید.</string>
|
||||
<string name="mailbox_error_wizard_info3">لطفا با استفاده از دکمه زیر، پیوند Mailbox خود را لغو کنید.\n\nپس از لغو پیوند Mailbox قدیمی، میتوانید هر زمان که خواستید یک Mailbox جدید راهاندازی کنید.</string>
|
||||
<!--About-->
|
||||
<string name="about_title">دربارهی Briar</string>
|
||||
<string name="about_title">دربارهی Psiphon</string>
|
||||
<string name="briar_version">نسخه Briar: %s</string>
|
||||
<string name="tor_version">نسخه Tor: %s</string>
|
||||
<string name="links">لینک ها</string>
|
||||
|
||||
@@ -46,6 +46,11 @@
|
||||
<item quantity="many">Ceci est une version d’essai de Briar. Votre compte arrivera à expiration dans %d jours et ne pourra pas être renouvelé.</item>
|
||||
<item quantity="other">Ceci est une version d’essai de Briar. Votre compte arrivera à expiration dans %d jours et ne pourra pas être renouvelé.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 n’est plus pris en charge. Briar cessera de fonctionner le %s (dans %d jour). Veuillez installer Briar sur un appareil plus récent et créer un nouveau compte.</item>
|
||||
<item quantity="many">Android 4 n’est plus pris en charge. Briar cessera de fonctionner le %s (dans %d jours). Veuillez installer Briar sur un appareil plus récent et créer un nouveau compte.</item>
|
||||
<item quantity="other">Android 4 n’est plus pris en charge. Briar cessera de fonctionner le %s (dans %d jours). Veuillez installer Briar sur un appareil plus récent et créer un nouveau compte.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Ce logiciel est arrivé à expiration.\nMerci de l’avoir testé !</string>
|
||||
<string name="download_briar">Pour continuer à utiliser Briar, veuillez télécharger la dernière version.</string>
|
||||
<string name="create_new_account">Vous devrez créer un nouveau compte, mais vous pouvez utiliser le même pseudonyme.</string>
|
||||
|
||||
@@ -1,60 +1,55 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Köszöntünk a Briar-ban</string>
|
||||
<string name="setup_name_explanation">A beceneved fog megjelenni minden tartalom mellett amit megosztottál. Nem tudod megváltoztatni a fiók létrehozása után.</string>
|
||||
<string name="setup_next">Következő</string>
|
||||
<string name="setup_password_intro">Válassz egy jelszót</string>
|
||||
<string name="setup_password_explanation">A Briar fiókod az eszközödön kerül titkosítva tárolásra, nem pedig a felhőben. Ha elfelejted a jelszavad, vagy eltávolítod a Briar-t, nincs lehetőség fiókod visszanyerésére.\n\nVálassz egy hosszú, nehezen kitalálható jelszót, például négy tetszőleges szó vagy tíz tetszőleges betű, szám vagy szimbólum.</string>
|
||||
<string name="dnkm_doze_intro">Az üzenetek fogadásához a Briar-nak szüksége van a háttérben csatlakozásra.</string>
|
||||
<string name="dnkm_doze_explanation">Az üzenetek fogadásához a Briarnak szüksége van háttérben csatlakozásra. Kérjük tiltsa le az akkumulátor optimalizációt, így a Briar kapcsolatban tud maradni.</string>
|
||||
<string name="choose_nickname">Felhasználónév választása</string>
|
||||
<string name="choose_password">Jelszó választása</string>
|
||||
<string name="confirm_password">Jelszó megerősítése</string>
|
||||
<string name="name_too_long">A név túl hosszú</string>
|
||||
<string name="password_too_weak">A jelszó túl gyenge</string>
|
||||
<string name="passwords_do_not_match">A jelszavak nem egyeznek</string>
|
||||
<string name="create_account_button">Fiók létrehozása</string>
|
||||
<string name="more_info">További információ</string>
|
||||
<string name="don_t_ask_again">Ne kérdezze még egyszer</string>
|
||||
<string name="dnkm_huawei_protected_text">Kérjük koppintson a gombra alább és ellenőrizze, hogy a Briar védett, a \"Védett alkalmazások\" képernyőn.</string>
|
||||
<string name="dnkm_huawei_protected_button">A Briar védelme</string>
|
||||
<string name="dnkm_huawei_protected_help">Ha Briar nincs hozzáadva a védett alkalmazások listájához, akkor nem képes futni a háttérben.</string>
|
||||
<string name="dnkm_huawei_app_launch_text">Kérjük koppintson a gombra alább, hogy megnyissa az \"App indítás\" képernyőt és ellenőrizze, hogy a Briar beállított \"Kézi kezelés\"-re.</string>
|
||||
<string name="dnkm_huawei_app_launch_help">Ha a Briar nincs beállítva \"Kézi kezelés\"-re az \"App indítás\" képernyőn, nem fog tudni futni a háttérben.</string>
|
||||
<string name="dnkm_xiaomi_text">Ahhoz, hogy a háttérben fusson, a Briar-t rögzíteni kell a legutóbbi appok listáján.</string>
|
||||
<string name="dnkm_xiaomi_button">A Briar védelme</string>
|
||||
<string name="dnkm_xiaomi_help">Ha Briar nincs rögzítve a legutóbbi appok listájában, akkor nem képes futni a háttérben.</string>
|
||||
<string name="dnkm_xiaomi_dialog_body_old">1. Nyissa meg a legutolsó appok listáját (másnéven az app váltót)\n\n2. Görgessen le a Briar képén, hogy megjelenjen a lakat ikon\n\n3. Ha a lakat nem zárt, koppintson a lezárásához</string>
|
||||
<string name="dnkm_xiaomi_dialog_body_new">1. Nyissa meg a legutóbbi alkalmazások listáját (alkalmazásváltónak is nevezik) 2. Ha Briar neve mellett van egy kis lakat képe, akkor nem kell semmit tennie 3. Ha nincs lakat, nyomja meg és tartsa lenyomva Briar képét, amíg meg nem jelenik a lakat gomb, majd koppintson rá</string>
|
||||
<string name="dnkm_xiaomi_lock_apps_text">Kérjük, érintse meg az alábbi gombot a biztonsági beállítások megnyitásához. Koppintson a „Sebességnövelésre”, majd az „Alkalmazások zárolása” elemre, és győződjön meg arról, hogy a Briar beállítása „Zárolva”.</string>
|
||||
<string name="dnkm_xiaomi_lock_apps_help">Ha a Briar az „Alkalmazások zárolása” képernyőn nincs „Zárolva”, nem tud a háttérben futni.</string>
|
||||
<string name="dnkm_warning_dozed_1">A Briar nem tudott a háttérben futni</string>
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Köszöntjük a Briar-ban</string>
|
||||
<string name="setup_name_explanation">A beceneve fog megjelenni minden tartalom mellett amit Ön osztott meg. Nem tudja megváltoztatni a fiók létrehozása után.</string>
|
||||
<string name="setup_next">Következő</string>
|
||||
<string name="setup_password_intro">Válasszon jelszót</string>
|
||||
<string name="setup_password_explanation">A Briar fiókja az eszközén kerül tárolásra titkosítva, nem a felhőben. Ha elfelejti a jelszavát, vagy eltávolítja a Briar-t, nincs lehetőség fiókja visszanyerésére.\n\nVálasszon egy hosszú, nehezen kitalálható jelszót, például négy tetszőleges szó vagy tíz tetszőleges betű, szám vagy szimbólum.</string>
|
||||
<string name="dnkm_doze_title">Háttérkapcsolatok</string>
|
||||
<string name="dnkm_doze_intro">Az üzenetek fogadásához a Briar-nak szüksége van a háttérben csatlakozásra.</string>
|
||||
<string name="dnkm_doze_explanation">Az üzenetek fogadásához a Briarnak szüksége van háttérben csatlakozásra. Kérjük tiltsa le az akkumulátor optimalizációt, így a Briar kapcsolatban tud maradni.</string>
|
||||
<string name="dnkm_doze_button">Kapcsolatok engedélyezése</string>
|
||||
<string name="choose_nickname">Felhasználónév választása</string>
|
||||
<string name="choose_password">Jelszó választása</string>
|
||||
<string name="confirm_password">Jelszó megerősítése</string>
|
||||
<string name="name_too_long">A név túl hosszú</string>
|
||||
<string name="password_too_weak">A jelszó túl gyenge</string>
|
||||
<string name="passwords_do_not_match">A jelszavak nem egyeznek</string>
|
||||
<string name="create_account_button">Fiók létrehozása</string>
|
||||
<string name="more_info">További információ</string>
|
||||
<string name="don_t_ask_again">Ne kérdezze még egyszer</string>
|
||||
<string name="dnkm_huawei_protected_text">Kérjük koppintson a gombra alább és ellenőrizze, hogy a Briar védett, a \"Védett alkalmazások\" képernyőn.</string>
|
||||
<string name="dnkm_huawei_protected_button">A Briar védelme</string>
|
||||
<string name="dnkm_huawei_protected_help">Ha Briar nincs hozzáadva a védett alkalmazások listájához, akkor nem képes futni a háttérben.</string>
|
||||
<string name="dnkm_huawei_app_launch_text">Kérjük koppintson a gombra alább, hogy megnyissa az \"App indítás\" képernyőt és ellenőrizze, hogy a Briar beállított \"Kézi kezelés\"-re.</string>
|
||||
<string name="dnkm_huawei_app_launch_button">Az akkumulátor beállítások megnyitása</string>
|
||||
<string name="dnkm_huawei_app_launch_help">Ha a Briar nincs beállítva \"Kézi kezelés\"-re az \"App indítás\" képernyőn, nem fog tudni futni a háttérben.</string>
|
||||
<string name="dnkm_xiaomi_text">Ahhoz, hogy a háttérben fusson, a Briar-t rögzíteni kell a legutóbbi appok listáján.</string>
|
||||
<string name="dnkm_xiaomi_button">A Briar védelme</string>
|
||||
<string name="dnkm_xiaomi_help">Ha Briar nincs rögzítve a legutóbbi appok listájában, akkor nem képes futni a háttérben.</string>
|
||||
<string name="dnkm_xiaomi_dialog_body_old">1. Nyissa meg a legutolsó appok listáját (másnéven az app váltót)\n\n2. Görgessen le a Briar képén, hogy megjelenjen a lakat ikon\n\n3. Ha a lakat nem zárt, koppintson a lezárásához</string>
|
||||
<string name="dnkm_xiaomi_dialog_body_new">1. Nyissa meg a legutolsó appok listáját (másnéven az app váltót)\n\n2. Nyomja meg és tartsa nyomva a Briar képét, hogy megjelenjen a lakat ikon\n\n3. Ha a lakat nem zárt, koppintson a lezárásához</string>
|
||||
<string name="dnkm_warning_dozed">%s nem tud futni a háttérben</string>
|
||||
<!--Login-->
|
||||
<string name="enter_password">Jelszó</string>
|
||||
<string name="try_again">Hibás jelszó, próbáld újra</string>
|
||||
<string name="dialog_title_cannot_check_password">A jelszót nem sikerült ellenőrizni</string>
|
||||
<string name="dialog_message_cannot_check_password">A Briar nem tudta ellenőrizni jelszavad. Kérjük indítsd újra az eszközöd a probléma megoldásához.</string>
|
||||
<string name="dialog_message_cannot_check_password">A Briar nem tudta ellenőrizni jelszavát. Kérjük indítja újra az eszközét a probléma megoldásához.</string>
|
||||
<string name="sign_in_button">Bejelentkezés</string>
|
||||
<string name="forgotten_password">Elfelejtettem a jelszavam</string>
|
||||
<string name="dialog_title_lost_password">Elveszett jelszó</string>
|
||||
<string name="dialog_message_lost_password">A Briar fiókod az eszközödön kerül titkosítva tárolásra, nem a felhőben. Ha elfelejted a jelszavad, vagy eltávolítod a Briar-t, nincs lehetőség fiókod visszanyerésére.\n\nVálassz egy hosszú, nehezen kitalálható jelszót, például négy tetszőleges szó vagy tíz tetszőleges betű, szám vagy szimbólum.</string>
|
||||
<string name="dialog_message_lost_password">A Briar fiókja az eszközén kerül tárolásra titkosítva, nem a felhőben. Ha elfelejti a jelszavát, vagy eltávolítja a Briar-t, nincs lehetőség fiókja visszanyerésére.\n\nVálasszon egy hosszú, nehezen kitalálható jelszót, például négy tetszőleges szó vagy tíz tetszőleges betű, szám vagy szimbólum.</string>
|
||||
<string name="startup_failed_activity_title">Briar indítási hiba</string>
|
||||
<string name="startup_failed_clock_error">A Briar nem tud elindulni, mert az eszköz órája nem megfelelően jár.\n\nKérjük állítsd be az eszköz óráját a megfelelő időre és próbálja újra.</string>
|
||||
<string name="startup_failed_db_error">Briar nem tudta megnyitni az Ön fiókját, névjegyeit és üzeneteit tartalmazó adatbázist. Kérjük, frissítsen az alkalmazás legújabb verziójára, és próbálja újra, vagy hozzon létre új fiókot az „Elfelejtettem a jelszavam” lehetőség kiválasztásával a jelszó kérése.</string>
|
||||
<string name="startup_failed_data_too_old_error">Fiókja ennek az alkalmazásnak egy régi verziójával jött létre, és ezzel a verzióval nem nyitható meg. Újra kell telepítenie a régi verziót, vagy be kell állítania egy új fiókot az „Elfelejtettem a jelszavam” lehetőség kiválasztásával a jelszókérőnél.</string>
|
||||
<string name="startup_failed_data_too_new_error">Fiókja az alkalmazás újabb verziójával jött létre, és ezzel a verzióval nem nyitható meg. Kérjük, frissítsen a legújabb verzióra, és próbálja újra.</string>
|
||||
<string name="startup_failed_service_error">Briar nem tudott elindítani egy szükséges összetevőt. Kérjük, frissítsen az alkalmazás legújabb verziójára, és próbálja újra.</string>
|
||||
<string name="startup_failed_clock_error">A Briar nem tud elindulni, mert az eszköz órája nem megfelelően jár.\n\nKérjük állítsa be az eszköz óráját a megfelelő időre és próbálja újra.</string>
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="one">Ez a teszt verziója a Briar-nak. A fiókja le fog járni %d napon belül és nem megújítható.</item>
|
||||
<item quantity="other">Ez a teszt verziója a Briar-nak. A fiókod le fog járni %d napon belül és nem megújítható.</item>
|
||||
<item quantity="other">Ez a teszt verziója a Briar-nak. A fiókja le fog járni %d napon belül és nem megújítható.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Ez a szoftver lejárt.\nKöszönjük a tesztelését!</string>
|
||||
<string name="download_briar">A Briar használatának folytatásához kérjük töltsd le a legújabb verziót.</string>
|
||||
<string name="create_new_account">Új fiókot kell létrehoznod, de használhatod ugyanazt a becenevet.</string>
|
||||
<string name="download_briar">A Briar használatának folytatásához kérjük töltse le a legújabb verziót.</string>
|
||||
<string name="create_new_account">Új fiókot kell létrehoznia, de használhatja ugyanazt a becenevet.</string>
|
||||
<string name="download_briar_button">Legújabb verzió letöltése</string>
|
||||
<string name="old_android_expiry_date_reached">A Briar már nem fut Android 4 rendszeren. Kérjük, telepítse a Briart egy újabb eszközre.</string>
|
||||
<string name="old_android_delete_account">Az alábbi gombra koppintva törölheti fiókját erről az eszközről.</string>
|
||||
<string name="delete_account_button">Fiók törlése</string>
|
||||
<string name="startup_open_database">Adatbázis dekódolása...</string>
|
||||
<string name="startup_migrate_database">Adatbázis frissítése</string>
|
||||
@@ -86,27 +81,27 @@
|
||||
<!--Transports: Wi-Fi-->
|
||||
<string name="transport_lan">Wi-Fi</string>
|
||||
<string name="transport_lan_long">Azonos Wi-Fi hálózat</string>
|
||||
<string name="lan_device_status_on">A telefonod Wi-Fi-hez csatlakoztatott.</string>
|
||||
<string name="lan_device_status_off">A telefonod Wi-Fi-hez nem csatlakoztatott.</string>
|
||||
<string name="lan_device_status_on">A telefonja Wi-Fi-hez csatlakoztatott.</string>
|
||||
<string name="lan_device_status_off">A telefonja Wi-Fi-hez nem csatlakoztatott.</string>
|
||||
<string name="lan_plugin_status_enabling">A Briar csatlakozik a Wi-Fi hálózathoz</string>
|
||||
<string name="lan_plugin_status_active">A Briar csatlakoztatva a Wi-Fi hálózathoz</string>
|
||||
<string name="lan_plugin_status_inactive">A Briar nem tud csatlakozni a Wi-Fi hálózathoz</string>
|
||||
<string name="lan_plugin_status_disabled">A Briar Wi-Fi nélküli használatra van beállítva</string>
|
||||
<!--Transports: Bluetooth-->
|
||||
<string name="transport_bt">Bluetooth</string>
|
||||
<string name="bt_device_status_on">A telefonod Bluetooth-ja bekapcsolva</string>
|
||||
<string name="bt_device_status_off">A telefonod Bluetooth-ja kikapcsolva</string>
|
||||
<string name="bt_device_status_on">A telefonja Bluetooth-ja bekapcsolva</string>
|
||||
<string name="bt_device_status_off">A telefonja Bluetooth-ja kikapcsolva</string>
|
||||
<string name="bt_plugin_status_enabling">A Briar csatlakozik a Bluetooth-hoz</string>
|
||||
<string name="bt_plugin_status_active">A Briar csatlakoztatva a Bluetooth-hoz</string>
|
||||
<string name="bt_plugin_status_inactive">A Briar nem tud csatlakozni a Bluetooth-hoz</string>
|
||||
<string name="bt_plugin_status_disabled">A Briar Bluetooth nélküli használatra van beállítva</string>
|
||||
<!--Notifications-->
|
||||
<string name="reminder_notification_title">Kilépve a Briar-ból</string>
|
||||
<string name="reminder_notification_text">Koppints az újra belépéshez.</string>
|
||||
<string name="reminder_notification_text">Koppintson az újra belépéshez.</string>
|
||||
<string name="reminder_notification_channel_title">Briar Belépési emlékeztető</string>
|
||||
<string name="reminder_notification_dismiss">Kihagy</string>
|
||||
<string name="ongoing_notification_title">Belépve a Briar-ba</string>
|
||||
<string name="ongoing_notification_text">Érintsd meg a Briar megnyitásához.</string>
|
||||
<string name="ongoing_notification_text">Érintse meg a Briar megnyitásához.</string>
|
||||
<plurals name="private_message_notification_text">
|
||||
<item quantity="one">Új privát üzenet.</item>
|
||||
<item quantity="other">%d új privát üzenet.</item>
|
||||
@@ -148,13 +143,12 @@
|
||||
<string name="fix">Javítás</string>
|
||||
<string name="help">Súgó</string>
|
||||
<string name="sorry">Sajnáljuk</string>
|
||||
<string name="error_start_activity">Nem elérhető a rendszereden</string>
|
||||
<string name="error_start_activity">Nem elérhető az ön rendszerén</string>
|
||||
<string name="status_heading">Állapot</string>
|
||||
<string name="error">Hiba</string>
|
||||
<string name="info">Információk</string>
|
||||
<!--Contacts and Private Conversations-->
|
||||
<string name="no_contacts">Nincs megjeleníthető kapcsolat</string>
|
||||
<string name="no_contacts_action">Koppints a + gombra a kapcsolatok hozzáadásához</string>
|
||||
<string name="no_contacts_action">Koppintson a + gombra a kapcsolatok hozzáadásához</string>
|
||||
<string name="date_no_private_messages">Nincs üzenet.</string>
|
||||
<string name="no_private_messages">Nincs megjeleníthető üzenet</string>
|
||||
<string name="message_hint">Új üzenet</string>
|
||||
@@ -169,11 +163,11 @@
|
||||
<string name="set_contact_alias_hint">Kapcsolat neve</string>
|
||||
<string name="menu_item_disappearing_messages">Eltűnő üzenetek</string>
|
||||
<!--The first placeholder will show a duration like "7 days". The second placeholder at the end will add "Tap to learn more."-->
|
||||
<string name="auto_delete_msg_you_enabled">Az üzeneteid eltűnnek %1$s. %2$s múlva</string>
|
||||
<string name="auto_delete_msg_you_enabled">Az üzenetei eltűnnek %1$s. %2$s múlva</string>
|
||||
<!--The placeholder at the end will add "Tap to learn more."-->
|
||||
<string name="auto_delete_msg_you_disabled">Az üzeneteid nem fognak eltűnni. %1$s</string>
|
||||
<string name="auto_delete_msg_you_disabled">Az üzenetei nem fognak eltűnni. %1$s</string>
|
||||
<!--The first placeholder will show a contact's name. The second placeholder will show a duration like "7 days". The third placeholder at the end will add "Tap to learn more."-->
|
||||
<string name="auto_delete_msg_contact_enabled">%1$s üzeneteid eltűnnek %2$s. %3$s múlva</string>
|
||||
<string name="auto_delete_msg_contact_enabled">%1$s üzenetei eltűnnek %2$s. %3$s múlva</string>
|
||||
<plurals name="duration_minutes">
|
||||
<item quantity="one">%d perc</item>
|
||||
<item quantity="other">%d perc</item>
|
||||
@@ -187,11 +181,11 @@
|
||||
<item quantity="other">%d nap</item>
|
||||
</plurals>
|
||||
<!--The first placeholder will show a contact's name. The second placeholder at the end will add "Tap to learn more."-->
|
||||
<string name="auto_delete_msg_contact_disabled">%1$s üzeneteid nem fognak eltűnni. %2$s</string>
|
||||
<string name="tap_to_learn_more">Koppints a további információkért.</string>
|
||||
<string name="auto_delete_msg_contact_disabled">%1$s üzenetei nem fognak eltűnni. %2$s</string>
|
||||
<string name="tap_to_learn_more">Koppintson a további információkért.</string>
|
||||
<string name="auto_delete_changed_warning_title">Eltűnő üzenetek megváltoztak</string>
|
||||
<string name="auto_delete_changed_warning_message_enabled">Azóta, hogy elkezdted írni az üzeneted, az eltűnő üzenetek engedélyezésre kerültek.</string>
|
||||
<string name="auto_delete_changed_warning_message_disabled">Azóta, hogy elkezdted írni az üzeneted, az eltűnő üzenetek letiltottak.</string>
|
||||
<string name="auto_delete_changed_warning_message_enabled">Azóta, hogy elkezdte írni az üzenetét, az eltűnő üzenetek engedélyezésre kerültek.</string>
|
||||
<string name="auto_delete_changed_warning_message_disabled">Azóta, hogy elkezdte írni az üzenetét, az eltűnő üzenetek tiltásra kerültek.</string>
|
||||
<string name="auto_delete_changed_warning_send">Küldés mindenféleképpen</string>
|
||||
<string name="delete_all_messages">Minden üzenet törlése</string>
|
||||
<string name="dialog_title_delete_all_messages">Üzenet törlés megerősítése</string>
|
||||
@@ -205,7 +199,7 @@
|
||||
<string name="dialog_message_not_deleted_not_all_selected_invitations">Egy meghívás törléséhez ki kell jelölnie a kérelmet és a választ.</string>
|
||||
<string name="delete_contact">Kapcsolat törlése</string>
|
||||
<string name="dialog_title_delete_contact">Kapcsolat törlésének megerősítése</string>
|
||||
<string name="dialog_message_delete_contact">Biztosan eltávolítod ezt a kapcsolatot és minden vele történt üzenetváltásod?</string>
|
||||
<string name="dialog_message_delete_contact">Biztosan eltávolítja ezt a kapcsolatot és minden vele történt üzenetváltását?</string>
|
||||
<string name="contact_deleted_toast">Kapcsolat törölve</string>
|
||||
<!--This is shown in the action bar when opening an image in fullscreen that the user sent-->
|
||||
<string name="you">Ön</string>
|
||||
@@ -224,7 +218,6 @@ Biztosan szeretné menteni?</string>
|
||||
<string name="menu_contact">Kapcsolat</string>
|
||||
<!--Adding Contacts-->
|
||||
<string name="add_contact_title">Közeli kapcsolat hozzáadása</string>
|
||||
<string name="add_contact_error_two_way">Mindketten beolvastátok egymás QR-kódjait?</string>
|
||||
<string name="face_to_face">Találkoznia kell a személlyel akit, hozzá szeretne adni a kapcsolatokhoz.\n\nEz megelőzi azt, hogy valaki megszemélyesítse Önt, vagy elolvassa későbbi üzeneteit.</string>
|
||||
<string name="continue_button">Folytatás</string>
|
||||
<string name="try_again_button">Újrapróbálkozás</string>
|
||||
@@ -232,16 +225,14 @@ Biztosan szeretné menteni?</string>
|
||||
<string name="exchanging_contact_details">Kapcsolat részletek cseréje\u2026</string>
|
||||
<string name="contact_added_toast">Kapcsolat hozzáadva: %s</string>
|
||||
<string name="contact_already_exists">%s kapcsolat már létezik</string>
|
||||
<string name="contact_already_exists_general">A kapcsolat már létezik</string>
|
||||
<string name="qr_code_invalid">A QR kód érvénytelen</string>
|
||||
<string name="qr_code_too_old_1">A beolvasott QR-kód a Briar egy régebbi verziójából származik. Kérje meg kapcsolattartóját, hogy frissítsen a legújabb verzióra, majd próbálja újra.</string>
|
||||
<string name="qr_code_too_new_1">A beolvasott QR-kód a Briar egy régebbi verziójából származik. Kérje meg kapcsolattartóját, hogy frissítsen a legújabb verziót, majd próbálja újra.</string>
|
||||
<string name="qr_code_too_old">A QR kód amit leolvasott egy korábbi %s verzióhoz tartozik.\n\nKérje meg kapcsolatát, hogy frissítsen a legutolsó verzióra, majd próbálják újra.</string>
|
||||
<string name="qr_code_too_new">A QR kód amit leolvasott egy újabb %s verzióhoz tartozik.\n\nKérjük, frissítsen a legutolsó verzióra, majd próbálják újra.</string>
|
||||
<string name="camera_error">Kamera hiba</string>
|
||||
<string name="connecting_to_device">Csatlakozás az eszközhöz\u2026</string>
|
||||
<string name="authenticating_with_device">Azonosítás az eszközzel\u2026</string>
|
||||
<string name="connection_error_title">Nem sikerült csatlakozni a kapcsolatához</string>
|
||||
<string name="connection_error_feedback">Ha ez a probléma tartósan fennáll, kérjük <a href="feedback">küldjön visszajelzést</a> nekünk, hogy segítsen fejleszteni az appot.</string>
|
||||
<string name="info_both_must_scan">Mindketten be kell szkennelniük egymás QR-kódjait</string>
|
||||
<!--Adding Contacts Remotely-->
|
||||
<string name="add_contact_remotely_title_case">Távoli kapcsolat hozzá adása</string>
|
||||
<string name="add_contact_nearby_title">Közeli kapcsolat hozzáadása</string>
|
||||
@@ -255,7 +246,7 @@ Biztosan szeretné menteni?</string>
|
||||
<string name="send_link_title">Linkek cseréje</string>
|
||||
<string name="add_contact_choose_nickname">Becenév választása</string>
|
||||
<string name="add_contact_choose_a_nickname">Becenév megadása</string>
|
||||
<string name="nickname_intro">Add meg a kapcsolatod becenevét. Csak te látod.</string>
|
||||
<string name="nickname_intro">Adja meg a kontakt becenevét. Csak ön láthatja.</string>
|
||||
<string name="your_link">Adja oda ezt a linket annak a kapcsolatának, akit hozzá szeretne adni</string>
|
||||
<string name="link_clip_label">Briar link</string>
|
||||
<string name="link_copied_toast">Link másolva</string>
|
||||
@@ -300,15 +291,9 @@ Kérjük frissítsen a legutolsó verzióra és próbálja újra.</string>
|
||||
<string name="different_person_button">Másik személy</string>
|
||||
<string name="duplicate_link_dialog_text_3">%1$s és %2$s ugyanazt a linket küldte.\n\nEgyikük lehet, hogy megpróbálja kikutatni, hogy kik a kapcsolatai.\n\nNe árulja el nekik, hogy ugyanazt a linket már megkapta mástól.</string>
|
||||
<string name="pending_contact_updated_toast">Várakozó kapcsolat frissítve</string>
|
||||
<string name="info_both_must_enter_links">Mindkettőnek hozzá kell adnia egymás linkjét</string>
|
||||
<!--Peer trust levels-->
|
||||
<string name="peer_trust_level_unverified">Ellenőrizetlen kapcsolat</string>
|
||||
<string name="peer_trust_level_verified">Ellenőrzött kapcsolat</string>
|
||||
<string name="peer_trust_level_ourselves">Én</string>
|
||||
<string name="peer_trust_level_stranger">Idegen</string>
|
||||
<!--Introductions-->
|
||||
<string name="introduction_onboarding_title">Kapcsolatai bemutatása</string>
|
||||
<string name="introduction_onboarding_text">Mutassa be ismerőseit egymásnak, hogy csatlakozhassanak a Briarhez.</string>
|
||||
<string name="introduction_onboarding_text">Bemutathatja kapcsolatait egymásnak, így nem szükséges, hogy találkozzanak személyesen, hogy kapcsolódhassanak a Briar-on.</string>
|
||||
<string name="introduction_menu_item">Bemutatkozás készítése</string>
|
||||
<string name="introduction_activity_title">Kapcsolat kiválasztása</string>
|
||||
<string name="introduction_not_possible">Jelenleg folyamatban van egy bemutatkozása ezekkel a kapcsolatokkal. Kérjük tegye lehetővé előbb ezek befejeződését. Ha a kapcsolatai ritkán vannak online, ez több időt is igénybe vehet.</string>
|
||||
@@ -331,14 +316,10 @@ Kérjük frissítsen a legutolsó verzióra és próbálja újra.</string>
|
||||
<!--Connect via Bluetooth-->
|
||||
<string name="menu_item_connect_via_bluetooth">Csatlakozás bluetooth-on keresztül</string>
|
||||
<string name="connect_via_bluetooth_title">Csatlakozás bluetooth-on keresztül</string>
|
||||
<string name="connect_via_bluetooth_intro">Ha a Bluetooth-kapcsolatok nem működnek automatikusan, ezt a képernyőt használhatja a manuális csatlakozáshoz. A kapcsolathoz a közelben kell lennie. Önnek és ismerősének egyszerre kell megnyomnia a „Start” gombot.</string>
|
||||
<string name="connect_via_bluetooth_already_discovering">Már próbál csatlakozni Bluetooth-on keresztül. Kérjük, próbálja újra rövidesen.</string>
|
||||
<string name="connect_via_bluetooth_no_location_permission">Nem folytatható hely engedélyek nélkül</string>
|
||||
<string name="connect_via_bluetooth_no_bluetooth_permission">Nem folytatható a közeli eszközök engedélye nélkül</string>
|
||||
<string name="connect_via_bluetooth_start">Csatlakozás Bluetooth-on...</string>
|
||||
<string name="connect_via_bluetooth_success">Sikeres csatlakozás Bluetooth-on.</string>
|
||||
<string name="connect_via_bluetooth_error">Nem sikerült csatlakozni Bluetooth-on.</string>
|
||||
<string name="connect_via_bluetooth_error_not_supported">Az eszköz nem támogatja a Bluetooth-t.</string>
|
||||
<!--Private Groups-->
|
||||
<string name="groups_list_empty">Nincs megjeleníthető csoport</string>
|
||||
<string name="groups_list_empty_action">Koppintson a + ikonra csoport létrehozásához, vagy kérje meg kapcsolatait, hogy osszanak meg csoportokat Önnel</string>
|
||||
@@ -431,10 +412,6 @@ Kérjük frissítsen a legutolsó verzióra és próbálja újra.</string>
|
||||
<string name="forum_declined_toast">Meghívás elutasítva</string>
|
||||
<string name="shared_by_format">Megosztva %s által</string>
|
||||
<string name="forum_invitation_already_sharing">Megosztás alatt</string>
|
||||
<string name="forum_invitation_already_invited">A meghívó már elküldve</string>
|
||||
<string name="forum_invitation_invite_received">A meghívó már megérkezett</string>
|
||||
<string name="forum_invitation_not_supported">Nem támogatott ezen kapcsolat által</string>
|
||||
<string name="forum_invitation_error">Hiba. Ez egy programhiba, nem a te hibád</string>
|
||||
<string name="forum_invitation_response_accepted_sent">Elfogadta a %s fórum meghívását.</string>
|
||||
<string name="forum_invitation_response_declined_sent">Elutasította %s a fórum meghívását.</string>
|
||||
<string name="forum_invitation_response_declined_auto"> %s fórum meghívása automatikusan elutasításra került.</string>
|
||||
@@ -460,11 +437,11 @@ Kérjük frissítsen a legutolsó verzióra és próbálja újra.</string>
|
||||
<string name="blogs_feed_empty_state">Nincs megjelenítendő bejegyzés</string>
|
||||
<string name="blogs_feed_empty_state_action">A bejegyzések a kapcsolataitól és a blogoktól, amikre feliratkozott, itt jelennek meg.\n\nÉrintse meg a toll ikont egy blog bejegyzés írásához</string>
|
||||
<string name="blogs_remove_blog">Blog eltávolítása</string>
|
||||
<string name="blogs_remove_blog_dialog_message">Biztosan eltávolítod ezt a blogot?
|
||||
<string name="blogs_remove_blog_dialog_message">Biztosan eltávolítja ezt a blogot?
|
||||
|
||||
A bejegyzések törlődni fognak az eszközödről, de a többi ember eszközéről nem .
|
||||
A bejegyzések törlődni fognak az Ön eszközéről, de nem a többi ember eszközéről.
|
||||
|
||||
Kapcsolataid, akivel megosztottad ezt a blogot, lehet nem kapnak többé frissítést.</string>
|
||||
Kapcsolatai, akivel megosztotta ezt a blogot, lehet nem kapnak többé frissítést.</string>
|
||||
<string name="blogs_remove_blog_ok">Eltávolít</string>
|
||||
<string name="blogs_blog_removed">Blog eltávolítva</string>
|
||||
<string name="blogs_reblog_comment_hint">Megjegyzés hozzáadása (opcionális)</string>
|
||||
@@ -489,9 +466,8 @@ Kapcsolataid, akivel megosztottad ezt a blogot, lehet nem kapnak többé frissí
|
||||
<string name="blogs_rss_feeds_import">RSS feed importálása</string>
|
||||
<string name="blogs_rss_feeds_import_button">Importálás</string>
|
||||
<string name="blogs_rss_feeds_import_hint">Adja meg az RSS feed URL címét</string>
|
||||
<string name="blogs_rss_feeds_import_progress">RSS feed importálása...</string>
|
||||
<string name="blogs_rss_feeds_import_error">Elnézését kérjük! Probléma akadt a feed-je importálásával.</string>
|
||||
<string name="blogs_rss_feeds_import_title">Hírcsatorna importálása fájlból</string>
|
||||
<string name="blogs_rss_feeds_import_exists">Ez a feed már importálva van.</string>
|
||||
<string name="blogs_rss_feeds">RSS Feed-ek</string>
|
||||
<string name="blogs_rss_feeds_manage_imported">Importálva:</string>
|
||||
<string name="blogs_rss_feeds_manage_author">Szerző:</string>
|
||||
@@ -596,79 +572,12 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="choose_ringtone_title">Csengőhang választása</string>
|
||||
<string name="cannot_load_ringtone">Sikertelen a csengőhang betöltése</string>
|
||||
<!--Mailbox-->
|
||||
<string name="mailbox_settings_title">Postafiók</string>
|
||||
<string name="mailbox_setup_title">Postafiók beàllítàsa</string>
|
||||
<string name="mailbox_setup_intro">A postafiók lehetővé teszi a kapcsolatai számára, hogy üzeneteket küldjenek Önnek, miközben Ön offline állapotban van. A postafiók fogadja az üzeneteket, és tárolja őket, amíg az internethez nem kapcsolódik. Telepítheti a Briar postafiók alkalmazást egy tartalék eszközre. Tartsa csatlakoztatva az áramforráshoz és a Wi-Fi-hálózathoz, hogy mindig online legyen.</string>
|
||||
<string name="mailbox_setup_download_link">Letöltési link megosztása</string>
|
||||
<string name="mailbox_setup_button_scan">Olvassa be a postafiók QR-kódját</string>
|
||||
<string name="permission_camera_qr_denied_body">Megtagadta a hozzáférést a kamerához, de a QR-kód beolvasásához a kamera használata szükséges. Kérjük, fontolja meg a hozzáférés megadását.</string>
|
||||
<string name="mailbox_setup_connecting">Kapcsolódàs a postafiókhoz...</string>
|
||||
<!--This string is shown when connecting to a Mailbox for the first time. The placeholder will be replaced with a duration, e.g. "2 minutes".-->
|
||||
<string name="mailbox_setup_connecting_info">Ez akár%1s-ot is igénybe vehet</string>
|
||||
<string name="mailbox_qr_code_too_old">A beolvasott QR-kód a Briar postafiók egy régebbi verziójából származik. Kérjük, frissítse a Briar postafiók a legújabb verzióra, majd próbálja újra.</string>
|
||||
<string name="mailbox_qr_code_too_new">A beolvasott QR-kód a Briar postafiók újabb verziójából származik. Kérjük, frissítse a Briart a legújabb verzióra, majd próbálja újra.</string>
|
||||
<string name="contact_qr_code_for_mailbox">A beolvasott QR-kód egy Briar-névjegy hozzáadására szolgál. Ha névjegyet szeretne hozzáadni, lépjen a névjegyzékbe, és koppintson a + ikonra.</string>
|
||||
<string name="mailbox_setup_qr_code_wrong_description">A beolvasott QR-kód nem a Briar postafiókból származik.Kérjük, nyissa meg a Briar postafiók alkalmazást a postafiók eszközén, és olvassa be az abban megjelenő QR-kódot.</string>
|
||||
<string name="mailbox_setup_already_paired_title">A Mailbox már linkelt</string>
|
||||
<string name="mailbox_setup_already_paired_description">Válaszd le a Mailbox-ot a másik eszközödön és próbáld újra.</string>
|
||||
<string name="mailbox_setup_io_error_title">Sikertelen a kapcsolódás</string>
|
||||
<string name="mailbox_setup_io_error_description">Ellenőrizd, hogy mindkét eszköz csatlakoztatva van-e az internethez és próbáld újra.</string>
|
||||
<string name="mailbox_setup_assertion_error_title">Postafiók hiba</string>
|
||||
<string name="mailbox_setup_assertion_error_description">Kérjük, küldjön visszajelzést (anonim adatokkal) a Briar alkalmazáson keresztül, ha a probléma továbbra is fennáll.</string>
|
||||
<string name="mailbox_setup_camera_error_description">Nem sikerült elérni a kamerát. Próbálja újra, talán az eszköz újraindítása után.</string>
|
||||
<string name="mailbox_setup_connecting">Csatlakozás...</string>
|
||||
<string name="mailbox_setup_paired_title">Csatlakozva</string>
|
||||
<string name="tor_offline_title">Offline</string>
|
||||
<string name="tor_offline_button_check">Ellenőrizze a kapcsolat beállításait</string>
|
||||
<string name="mailbox_status_title">Postafiók állapota</string>
|
||||
<string name="mailbox_status_connected_title">A Mailbox fut</string>
|
||||
<string name="mailbox_status_problem_title">A Briar-nak problémái vannak a Mailbox-hoz csatlakozással</string>
|
||||
<string name="mailbox_status_failure_title">A Mailbox nem elérhető</string>
|
||||
<string name="mailbox_status_app_too_old_title">Briar túl régi</string>
|
||||
<string name="mailbox_status_app_too_old_message">Frissísd a Briar-t a legutolsó app verzióra és próbáld újra.</string>
|
||||
<string name="mailbox_status_mailbox_too_old_title">A Mailbox túl régi</string>
|
||||
<string name="mailbox_status_mailbox_too_old_message">Frissítsd a Mailbox-ot a legutolsó app verzióra és próbáld újra.</string>
|
||||
<string name="mailbox_status_check_button">Kapcsolat ellenőrzése</string>
|
||||
<!--Example for string substitution: Last connection: 3min ago-->
|
||||
<string name="mailbox_status_connected_info">Utolsó csatlakozás: %s</string>
|
||||
<!--Indicates that there never was a connection to the mailbox. Last connection: Never-->
|
||||
<string name="mailbox_status_connected_never">Soha</string>
|
||||
<string name="mailbox_status_unlink_button">Leválasztás</string>
|
||||
<string name="mailbox_status_unlink_dialog_title">Leválassza a postafiókot?</string>
|
||||
<string name="mailbox_status_unlink_dialog_question">Biztosan szeretnéd lecsatlakoztatni a Mailbox-od?</string>
|
||||
<string name="mailbox_status_unlink_dialog_warning">Ha leválasztod a Mailbox-od, nem fogsz tudni üzeneteket kapni amíg a Briar offline.</string>
|
||||
<string name="mailbox_status_unlink_no_wipe_title">A Mailbox-od lecsatlakoztatásra került</string>
|
||||
<string name="mailbox_status_unlink_no_wipe_message">Ha legközelebb hozzáfér postafiókjához, nyissa meg a postafiók alkalmazást, és érintse meg a „Leválasztás” gombot a folyamat befejezéséhez. Ha már nem fér hozzá postafiókjához, ne aggódjon. Adatai titkosítva vannak, így akkor is biztonságban maradnak, ha nem fejezi be a folyamatot.</string>
|
||||
<string name="mailbox_status_unlink_success">A Mailbox-od lecsatlakoztatásra került</string>
|
||||
<string name="mailbox_error_notification_channel_title">Briar Mailbox probléma</string>
|
||||
<string name="mailbox_error_notification_title">A Briar Mailbox nem elérhető</string>
|
||||
<string name="mailbox_error_notification_text">Érintsd meg a hibajavításhoz.</string>
|
||||
<string name="mailbox_error_wizard_button">Probléma javítása</string>
|
||||
<string name="mailbox_error_wizard_title">Mailbox hibaelhárító varázsló</string>
|
||||
<string name="mailbox_error_wizard_question1">Van hozzáférésed a Mailbox eszközödhöz?</string>
|
||||
<string name="mailbox_error_wizard_answer1">Igen, most azonnal van hozzáférésem.</string>
|
||||
<string name="mailbox_error_wizard_answer2">Épp most nem, de később hozzáférek.</string>
|
||||
<string name="mailbox_error_wizard_answer3">Nem, nincs már hozzáférésem.</string>
|
||||
<string name="mailbox_error_wizard_info1_1">Ellenőrizd, hogy a Mailbox eszközöd be van-e kapcsolva és csatlakoztatva van-e az internethez.</string>
|
||||
<string name="mailbox_error_wizard_question1_1">Nyisd meg a Mailbox appot. Mit látsz?</string>
|
||||
<string name="mailbox_error_wizard_answer1_1">A Mailbox beállításának lépéseit látom</string>
|
||||
<string name="mailbox_error_wizard_answer1_2">Látok egy QR kódot</string>
|
||||
<string name="mailbox_error_wizard_answer1_3">Azt látom \"Mailbox is running\"</string>
|
||||
<string name="mailbox_error_wizard_answer1_4">Azt látom, hogy \"Device offline\"</string>
|
||||
<string name="mailbox_error_wizard_info1_1_1">Kérjük válaszd le a Mailbox-ot a gombbal alább, aztán kövesd a lépéseket a Mailbox eszközön az újra csatlakoztatáshoz.</string>
|
||||
<string name="mailbox_error_wizard_info_1_1_2">Kérjük válaszd le a Mailbox-ot a gombbal alább, aztán olvasd be a QR kódot az újra csatlakoztatáshoz.</string>
|
||||
<string name="mailbox_error_wizard_info1_1_4">Ellenőrizze, hogy a postafiók megfelelően csatlakozik-e az internethez. Ellenőrizze, hogy a postafiók órája a megfelelő időt, dátumot és időzónát mutatja-e. Ellenőrizze, hogy a postafiók és a Briar alkalmazások frissültek-e a legújabb verzióra. Indítsa újra a postafiók és a Briar eszközöket, és próbálja újra.</string>
|
||||
<string name="mailbox_error_wizard_info2">Kérjük gyere vissza erre képernyőre, ha van hozzáférésed az eszközhöz.</string>
|
||||
<!--About-->
|
||||
<string name="about_title">Névjegy</string>
|
||||
<string name="briar_version">Briar verzió: %s</string>
|
||||
<string name="tor_version">Tor verzió: %s</string>
|
||||
<string name="links">Linkek</string>
|
||||
<string name="briar_website">\u2022 <a href="">Weboldal</a></string>
|
||||
<string name="briar_source_code">\u2022 <a href="">Forráskód</a> </string>
|
||||
<string name="briar_changelog">\u2022 <a href="">Változásnapló</a></string>
|
||||
<string name="briar_privacy_policy">\u2022 <a href="">Adatvédelmi irányelvek</a></string>
|
||||
<!--Here translators can add their names or Transifex usernames(eg "Thanks to all the contributors at the Localization Lab, especially Tom, Matthew and Jerry")-->
|
||||
<string name="translator_thanks">Köszönet minden közreműködőnek a Lokalizációs Laborban</string>
|
||||
<!--Conversation Settings-->
|
||||
<string name="disappearing_messages_title">Eltűnő üzenetek</string>
|
||||
<string name="disappearing_messages_explanation_long">Bekapcsolva ezt beállítást az új
|
||||
@@ -684,7 +593,6 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="disappearing_messages_summary">Make future messages in this conversation automatically disappear after 7\u00A0days.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Események</string>
|
||||
<string name="share_app_link">Letöltési link megosztása</string>
|
||||
<string name="send_feedback">Visszajelzés küldése</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Link figyelmeztetés</string>
|
||||
@@ -693,7 +601,6 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="link_warning_open_link">Link megnyitása</string>
|
||||
<!--Crash Reporter-->
|
||||
<string name="crash_report_title">Briar összeomlási jelentés</string>
|
||||
<string name="briar_crashed">Sajnáljuk, a Briar összeomlott</string>
|
||||
<string name="not_your_fault">Ez nem az Ön hibája.</string>
|
||||
<string name="please_send_report">Kérjük segítsen nekünk a Briar-t jobbá tenni, a hibajelentés elküldésével.</string>
|
||||
<string name="report_is_encrypted">Biztosítjuk, hogy a hibajelentés titkosított és biztonságos.</string>
|
||||
@@ -701,7 +608,6 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="describe_crash">Írja le mi történt (opcionális)</string>
|
||||
<string name="enter_feedback">Gépelje be visszajelzését</string>
|
||||
<string name="optional_contact_email">Email címe (opcionális)</string>
|
||||
<string name="privacy_policy">Az adatok elküldésével Ön elfogadja a mi <a href="">Adatvédelmi irányelvünket</a></string>
|
||||
<string name="include_debug_report_crash">Névtelen adat beágyazása az összeomlásról</string>
|
||||
<string name="include_debug_report_feedback">Névtelen adat beágyazása az eszközről</string>
|
||||
<string name="dev_report_user_info">Felhasználó információ</string>
|
||||
@@ -712,7 +618,6 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="dev_report_memory">Memória</string>
|
||||
<string name="dev_report_storage">Tárhely</string>
|
||||
<string name="dev_report_connectivity">Csatlakozódás</string>
|
||||
<string name="dev_report_network_usage">Hálózathasználat</string>
|
||||
<string name="dev_report_build_config">Build konfiguráció</string>
|
||||
<string name="dev_report_logcat">App log</string>
|
||||
<string name="dev_report_device_features">Eszköz szolgáltatások</string>
|
||||
@@ -734,21 +639,14 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<string name="permission_camera_title">Kamera jogosultságok</string>
|
||||
<string name="permission_camera_request_body">A QR kód olvasáshoz a Briar-nak szüksége van kamera hozzáférésre.</string>
|
||||
<string name="permission_location_title">Hely engedélyek</string>
|
||||
<string name="permission_nearby_devices_title">Közeli eszközök engedélye</string>
|
||||
<string name="permission_location_request_body">A Bluetooth eszközök észleléséhez a Briar-nak szükségve van a lokációhoz hozzáférésre.\n\nA Briar nem tárolja lokációját vagy ossza meg bárkivel.</string>
|
||||
<string name="permission_camera_location_title">Kamera és lokáció</string>
|
||||
<string name="permission_camera_location_request_body">A QR kód beszkenneléséhez a Briar-nak szüksége van a Kamerához hozzáférésre.\n\nA Bluetooth eszközök észleléséhez a Briar-nak szükségve van a lokációhoz hozzáférésre.\n\nA Briar nem tárolja lokációját vagy ossza meg bárkivel.</string>
|
||||
<string name="permission_camera_bluetooth_title">Kamera és közeli eszközök</string>
|
||||
<string name="permission_camera_bluetooth_request_body">A QR-kód beolvasásához Briarnak hozzá kell férnie a kamerához. A Bluetooth-eszközök felfedezéséhez Briarnak engedélyre van szüksége a közeli eszközök megkereséséhez és azokhoz való csatlakozáshoz.</string>
|
||||
<string name="permission_camera_denied_body">Megtiltotta hozzáférést a kamerához, de a kapcsolatok hozzáadásához szükséges a kamera.\n\nKérjük gondolja meg a jog megadását.</string>
|
||||
<string name="permission_location_denied_body">Megtiltotta hozzáférést a helyhez, azonban a Briar-nak szüksége van erre, hogy detektálja a Bluetooth eszközöket.\n\nKérjük gondolja meg a jog megadását.</string>
|
||||
<string name="permission_location_setting_title">Hely beállítás</string>
|
||||
<string name="permission_location_setting_body">Az eszköze hely beállításai be kell kapcsolva legyenek, hogy megtaláljon más eszközöket Bluetooth-on. Kérjük engedélyezze a folytatáshoz. Utána újra letilthatja.</string>
|
||||
<string name="permission_location_setting_hotspot_body">Wi-Fi hotspot létrehozásához az eszköz helybeállítását be kell kapcsolni. A folytatáshoz engedélyezze a helymeghatározást. Utána újra kikapcsolhatja.</string>
|
||||
<string name="permission_location_setting_button">Hely engedélyezése</string>
|
||||
<string name="permission_bluetooth_title">Közeli eszközök engedélye</string>
|
||||
<string name="permission_bluetooth_body">A Bluetooth-kommunikáció használatához Briarnak engedélyre van szüksége a közeli eszközök megtalálásához és azokhoz való csatlakozáshoz.</string>
|
||||
<string name="permission_bluetooth_denied_body">Megtagadta a hozzáférést a közeli eszközökhöz, de Briarnak szüksége van erre az engedélyre a Bluetooth használatához. Kérjük, fontolja meg a hozzáférés megadását.</string>
|
||||
<string name="qr_code">QR kód</string>
|
||||
<string name="show_qr_code_fullscreen">A QR kód teljes képernyősen</string>
|
||||
<!--App Locking-->
|
||||
@@ -761,28 +659,12 @@ Vigyázat: Ez végleg törli az identitásait, kapcsolatait és üzeneteit</stri
|
||||
<!--Connections Screen-->
|
||||
<string name="transports_help_text">A Briar Interneten, Wi-Fi-n vagy Bluetooth-on keresztül csatlakozhat kapcsolataihoz.\n\nAz összes internetkapcsolat a Tor hálózaton megy keresztül megy az adatvédelem érdekében.\n\nHa egy kapcsolatot több módszerrel is el lehet érni, Briar párhuzamosan használja azokat.</string>
|
||||
<!--Share app offline-->
|
||||
<string name="hotspot_title">Ossza meg ezt az alkalmazást offline</string>
|
||||
<string name="hotspot_button_start_sharing">Hotspot indítása</string>
|
||||
<string name="hotspot_button_stop_sharing">Hotspot leállítása</string>
|
||||
<string name="hotspot_progress_text_start">Hotspot beállítása…</string>
|
||||
<string name="hotspot_notification_channel_title">Wifi hotspot</string>
|
||||
<string name="hotspot_notification_title">Briar megosztása offline állapotban</string>
|
||||
<string name="hotspot_button_connected">Következő</string>
|
||||
<string name="permission_hotspot_location_request_body">Wi-Fi hotspot létrehozásához a Briarnak engedélyre van szüksége ahhoz, hogy hozzáférjen az Ön tartózkodási helyéhez. A Briar nem tárolja az Ön tartózkodási helyét, és nem osztja meg senkivel.</string>
|
||||
<string name="permission_hotspot_location_request_precise_body">Wi-Fi hotspot létrehozásához a Briarnak engedélyre van szüksége, hogy hozzáférjen az Ön pontos helyéhez. A Briar nem tárolja az Ön tartózkodási helyét, és nem osztja meg senkivel.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Megtagadta a hozzáférést a tartózkodási helyéhez, de Briarnak szüksége van erre az engedélyre Wi-Fi hotspot létrehozásához. Kérjük, fontolja meg a hozzáférés megadását.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Megtagadta a hozzáférést a pontos tartózkodási helyéhez, de Briarnak szüksége van erre az engedélyre Wi-Fi hotspot létrehozásához. Kérjük, fontolja meg a hozzáférés megadását.</string>
|
||||
<string name="wifi_settings_title">Wi-Fi beállítás</string>
|
||||
<string name="wifi_settings_request_enable_body">Wi-Fi hotspot létrehozásához Briarnak Wi-Fi-t kell használnia. Kérjük, engedélyezze.</string>
|
||||
<string name="hotspot_tab_manual">Kézi</string>
|
||||
<!--The placeholder to be inserted into the string 'hotspot_manual_wifi': People can connect by %s-->
|
||||
<string name="hotspot_scanning_a_qr_code">QR-kód beolvasása</string>
|
||||
<!--Wi-Fi setup-->
|
||||
<!--The %s placeholder will be replaced with the translation of 'hotspot_scanning_a_qr_code'-->
|
||||
<string name="hotspot_manual_wifi">Telefonja Wi-Fi hotspotot biztosít. Azok az emberek, akik szeretnék letölteni a Briart, csatlakozhatnak a hotspothoz úgy, hogy hozzáadják azt eszközük Wi-Fi beállításaihoz az alábbi adatokkal vagy %s-al. Amikor csatlakoztak a hotspothoz, nyomja meg a „Tovább” gombot.</string>
|
||||
<string name="hotspot_manual_wifi_ssid">Hálózat neve</string>
|
||||
<string name="hotspot_qr_wifi">Telefonja Wi-Fi hotspotot biztosít. Azok, akik szeretnék letölteni a Briart, ennek a QR-kódnak a beolvasásával csatlakozhatnak a hotspothoz. Amikor csatlakoztak a hotspothoz, nyomja meg a „Tovább” gombot.</string>
|
||||
<string name="hotspot_no_peers_connected">Nincsenek csatlakoztatva eszközök</string>
|
||||
<!--Download link-->
|
||||
<!--The %s placeholder will be replaced with the translation of 'hotspot_scanning_a_qr_code'-->
|
||||
<!--e.g. Download Briar 1.2.20-->
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
<item quantity="one">Þetta er prufuútgáfa af Briar. Notandaaðgangurinn þinn mun renna út eftir %d dag og er ekki hægt að endurnýja hann.</item>
|
||||
<item quantity="other">Þetta er prufuútgáfa af Briar. Notandaaðgangurinn þinn mun renna út eftir %d daga og er ekki hægt að endurnýja hann.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 er ekki lengur stutt. Briar mun hætta að virka á %s (eftir %d dag). Settu Briar upp á nýrra tæki og útbúðu nýjan aðgang.</item>
|
||||
<item quantity="other">Android 4 er ekki lengur stutt. Briar mun hætta að virka á %s (eftir %d daga). Settu Briar upp á nýrra tæki og útbúðu nýjan aðgang.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Þessi hugbúnaður er úreltur.\nTakk fyrir að hafa tekið þátt í prófunum!</string>
|
||||
<string name="download_briar">Til að halda áfram að nota Briar, ættirðu að sækja nýjustu útgáfuna.</string>
|
||||
<string name="create_new_account">Þú þarft að búa til nýjan notandaaðgang, en þú getur notað áfram sama stuttnefni.</string>
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
<item quantity="many">Questa è una versione di prova di Briar. Il tuo account scadrà fra %d giorni e non può essere rinnovato.</item>
|
||||
<item quantity="other">Questa è una versione di prova di Briar. Il tuo account scadrà fra %d giorni e non può essere rinnovato.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 non è più supportato. Briar smetterà di funzionare il %s (tra %d giorno). Installa Briar in un dispositivo più recente e crea un nuovo account.</item>
|
||||
<item quantity="many">Android 4 non è più supportato. Briar smetterà di funzionare il %s (tra %d giorni). Installa Briar in un dispositivo più recente e crea un nuovo account.</item>
|
||||
<item quantity="other">Android 4 non è più supportato. Briar smetterà di funzionare il %s (tra %d giorni). Installa Briar in un dispositivo più recente e crea un nuovo account.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Questo software è scaduto.\nGrazie per il test!</string>
|
||||
<string name="download_briar">Per continuare a utilizzare Briar, scarica l\'ultima versione.</string>
|
||||
<string name="create_new_account">Avrai bisogno di creare un nuovo account, ma puoi usare lo stesso nickname.</string>
|
||||
@@ -702,8 +707,6 @@
|
||||
<string name="disappearing_messages_summary">Fai sparire automaticamente i messaggi futuri di questa conversazione dopo 7\u00A0giorni.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Azioni</string>
|
||||
<string name="share_app_link">Condividi link di download</string>
|
||||
<string name="share_app_link_text">Scarica Briar su %s</string>
|
||||
<string name="send_feedback">Invia feedback</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Attenzione Link</string>
|
||||
@@ -753,7 +756,6 @@
|
||||
<string name="permission_camera_title">Autorizzazione fotocamera</string>
|
||||
<string name="permission_camera_request_body">Per scansionare il codice QR, Briar deve accedere alla fotocamera.</string>
|
||||
<string name="permission_location_title">Autorizzazione geolocalizzazione</string>
|
||||
<string name="permission_nearby_devices_title">Autorizzazione dispositivi vicini</string>
|
||||
<string name="permission_location_request_body">Per trovare dispositivi Bluetooth, Briar ha bisogno di accedere alla tua posizione.\n\nBriar non memorizza la tua posizione, nè la condivide con terzi.</string>
|
||||
<string name="permission_camera_location_title">Fotocamera e geolocalizzazione</string>
|
||||
<string name="permission_camera_location_request_body">Per scansionare il codice QR, Briar ha bisogno di accedere alla fotocamera.\n\nPer trovare dispositivi Bluetooth, Briar ha bisogno di accedere alla tua posizione.\n\nBriar non memorizza la tua posizione, nè la condivide con terzi.</string>
|
||||
@@ -793,8 +795,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Per creare un hotspot Wi-Fi, Briar ha bisogno dell\'autorizzazione per accedere alla tua posizione precisa.\n\nBriar non memorizza la tua posizione e non la condivide con nessuno.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Hai negato l\'accesso alla tua posizione, ma Briar ha bisogno di questa autorizzazione per creare un hotspot Wi-Fi.\n\nPrendi in considerazione di consentirla.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Hai negato l\'accesso alla tua posizione, ma Briar ha bisogno di questa autorizzazione per creare un hotspot Wi-Fi.\n\nConsidera la possibilità di concedere l\'accesso.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Per creare un hotspot Wi-Fi, Briar deve avere l\'autorizzazione per i dispositivi vicini.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Hai negato l\'accesso ai dispositivi vicini, ma Briar ha bisogno di questa autorizzazione per creare un hotspot Wi-Fi.\n\nPrendi in considerazione di consentirla.</string>
|
||||
<string name="wifi_settings_title">Impostazione Wi-Fi</string>
|
||||
<string name="wifi_settings_request_enable_body">Per creare un hotspot Wi-Fi, Briar deve usare il Wi-Fi. Prima attivalo.</string>
|
||||
<string name="hotspot_tab_manual">Manuale</string>
|
||||
|
||||
@@ -46,6 +46,9 @@
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="other">これは、Briarの試験バージョンです。 アカウントはあと%d日で期限切れになり、更新できません。</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="other">Android 4はサポートされなくなりました。Briarは(%d日後に)%s上での動作を停止します。新しい端末に Briarをインストールして、新規アカウントを作成してください。</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">このソフトウェアの有効期限が切れました。試験に参加してくださりありがとうございます!</string>
|
||||
<string name="download_briar">Briarを使用し続けるには、最新のリリースをダウンロードしてください。</string>
|
||||
<string name="create_new_account">新規アカウントを作成する必要があります。同じニックネームも使用できます。</string>
|
||||
@@ -211,7 +214,7 @@
|
||||
<string name="messaging_too_many_attachments_toast">最初の%d個の画像のみが送信されます。</string>
|
||||
<string name="menu_contact">連絡先</string>
|
||||
<!--Adding Contacts-->
|
||||
<string name="add_contact_title">近くにいる人を連絡先に追加</string>
|
||||
<string name="add_contact_title">近くの人を連絡先に追加する</string>
|
||||
<string name="add_contact_error_two_way">お互いのQRコードを読み取りましたか?</string>
|
||||
<string name="face_to_face">連絡先として追加したい人と会う必要があります。\n\nこれにより、だれかがあなたになりすましたり、メッセージを読んだりするのを防ぐことができます。</string>
|
||||
<string name="continue_button">続行</string>
|
||||
@@ -251,7 +254,7 @@
|
||||
<string name="link_copied_toast">リンクをコピーしました</string>
|
||||
<string name="adding_contact_error">連絡先を追加中にエラーが発生しました。</string>
|
||||
<string name="pending_contact_requests_snackbar">保留中の連絡先への追加要求があります</string>
|
||||
<string name="pending_contact_requests">保留中の連絡先への追加要求</string>
|
||||
<string name="pending_contact_requests">連絡先追加要求</string>
|
||||
<string name="no_pending_contacts">保留中の連絡先追加要求はありません</string>
|
||||
<string name="waiting_for_contact_to_come_online">連絡先がオンラインになるのを待っています…</string>
|
||||
<string name="connecting">接続中…</string>
|
||||
@@ -674,8 +677,6 @@
|
||||
<string name="disappearing_messages_summary">この会話の今後のメッセージは、自動的に7\u00A0日後に消えます。</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">操作</string>
|
||||
<string name="share_app_link">ダウンロードリンクを共有</string>
|
||||
<string name="share_app_link_text">%s でBriarをダウンロード</string>
|
||||
<string name="send_feedback">フィードバックを送信</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">リンクの警告</string>
|
||||
@@ -725,7 +726,6 @@
|
||||
<string name="permission_camera_title">カメラの権限</string>
|
||||
<string name="permission_camera_request_body">QRコードを読み取るには、Briarはカメラにアクセスする必要があります。</string>
|
||||
<string name="permission_location_title">位置情報の権限</string>
|
||||
<string name="permission_nearby_devices_title">付近の端末の権限</string>
|
||||
<string name="permission_location_request_body">Bluetooth端末を検出するには、Briarがあなたの位置情報へアクセスする権限を必要とします。\n\nBriarはあなたの場所を保存したり、誰とも共有したりしません。</string>
|
||||
<string name="permission_camera_location_title">カメラと位置情報</string>
|
||||
<string name="permission_camera_location_request_body">QRコードを読み取るには、Briarはカメラにアクセスする権限を必要とします。\n\nBluetooth端末を検出するには、Briarは現在地情報にアクセスする許可が必要です。\n\nBriarは現在地を保存したり、誰とも共有したりしません。</string>
|
||||
@@ -765,10 +765,8 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Wi-Fiホットスポットを作るには、Briarはあなたの正確な位置情報にアクセスする権限が必要です。\n\nBriarはあなたの位置情報を保存せず、誰かに共有することもありません。</string>
|
||||
<string name="permission_hotspot_location_denied_body">あなたは位置情報にアクセスすることを拒否しましたが、BriarはWi-Fiホットスポットを作るのに、この権限が必要です。\n\nアクセス権を付与することを考慮願います。</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">あなたは正確な位置情報にアクセスすることを拒否しましたが、BriarはWi-Fiホットスポットを作るのに、この権限が必要です。\n\nアクセス権を付与することを考慮願います。</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Wi-Fiホットスポットを作るには、Briarは付近の端末にアクセスする権限が必要です。</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">あなたは付近の端末にアクセスすることを拒否しましたが、BriarはWi-Fiホットスポットを作るのに、この権限が必要です。\n\nアクセス権を付与することを考慮願います。</string>
|
||||
<string name="wifi_settings_title">Wi-Fi設定</string>
|
||||
<string name="wifi_settings_request_enable_body">Wi-Fiホットスポットを作るには、BriarはWi-Fiの使用が必要です。有効にしてください。</string>
|
||||
<string name="wifi_settings_request_enable_body">Wi-Fiホットスポットを作るには、BriarWi-Fiの使用が必要です。有効にしてください。</string>
|
||||
<string name="hotspot_tab_manual">手動</string>
|
||||
<!--The placeholder to be inserted into the string 'hotspot_manual_wifi': People can connect by %s-->
|
||||
<string name="hotspot_scanning_a_qr_code">QRコードを読み取る</string>
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
<item quantity="one">ესაა საცდელი ვერსიის Briar. თქვენს ანგარიშს %d დღეში გაუვა ვადა და ვეღარ გახანგრძლივდება.</item>
|
||||
<item quantity="other">ეს არის Briar-ის საცდელი ვერსია, რომლის ვადა %d დღეში ამოიწურება და მისი განახლება შეუძლებელია.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 აღარაა მხარდაჭერილი. Briar-ის გაუქმების ვადაა %s (%d დღეში). გთხოვთ, Briar გამოიყენოთ უფრო ახალ მოწყობილობაზე და ახალი ანგარიში შექმნათ.</item>
|
||||
<item quantity="other">Android 4 აღარაა მხარდაჭერილი. Briar შეწყვეტს მუშაობას %s (%d დღეში). გთხოვთ, დააინსტალიროთ Briar უფრო ახალ მოწყობილობაზე და ახალი ანგარიში შექმნათ.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">პროგრამული უზრუნველყოფის ვადა ამოიწურა.\nგმადლობთ ტესტირებისთვის!</string>
|
||||
<string name="download_briar">თუ გსურთ, კვლავ გამოიყენოთ Briar, ჩამოტვირთეთ ბოლო გამოშვება.</string>
|
||||
<string name="create_new_account">დაგჭირდებათ ახალი ანგარიშის შექმნა, თუმცა იმავე მეტსახელის გამოყენება შეგეძლებათ.</string>
|
||||
|
||||
@@ -47,6 +47,12 @@
|
||||
<item quantity="many">Tai yra bandomoji Briar versija. Jūsų paskyros galiojimas pasibaigs po %d dienų ir negalės būti pratęstas.</item>
|
||||
<item quantity="other">Tai yra bandomoji Briar versija. Jūsų paskyros galiojimas pasibaigs po %d dienos ir negalės būti pratęstas.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">„Android“ 4 yra daugiau nebepalaikoma. Briar nustos veikti ties %s (po %d dienos). Įsidiekite Briar naujesniame įrenginyje ir susikurkite naują paskyrą.</item>
|
||||
<item quantity="few">„Android“ 4 yra daugiau nebepalaikoma. Briar nustos veikti ties %s (po %d dienų). Įsidiekite Briar naujesniame įrenginyje ir susikurkite naują paskyrą.</item>
|
||||
<item quantity="many">„Android“ 4 yra daugiau nebepalaikoma. Briar nustos veikti ties %s (po %d dienų). Įsidiekite Briar naujesniame įrenginyje ir susikurkite naują paskyrą.</item>
|
||||
<item quantity="other">„Android“ 4 yra daugiau nebepalaikoma. Briar nustos veikti ties %s (po %d dienos). Įsidiekite Briar naujesniame įrenginyje ir susikurkite naują paskyrą.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Programinės įrangos galiojimas pasibaigė.\nDėkojame, kad išbandėte!</string>
|
||||
<string name="download_briar">Norėdami ir toliau naudotis Briar, atsisiųskite naujausią programos laidą.</string>
|
||||
<string name="create_new_account">Jūs turėsite susikurti paskyrą, tačiau galėsite naudoti tą patį slapyvardį.</string>
|
||||
@@ -774,7 +780,6 @@
|
||||
<string name="hotspot_qr_site">Jūsų telefonas teikia belaidį (Wi-Fi) prieigos tašką. Žmonės, prisijungę prie prieigos taško, gali atsisiųsti Briar, skenuodami šį QR kodą.</string>
|
||||
<!--e.g. Download Briar 1.2.20-->
|
||||
<string name="website_download_title_1">Atsisiųsti Briar %s</string>
|
||||
<string name="website_download_intro_1">Kažkas iš šalia esančių pradėjo bendrinti su jumis Briar.</string>
|
||||
<string name="website_download_button">Atsisiųsti Briar</string>
|
||||
<string name="website_download_outro">Kai atsisiuntimas pasibaigs, atverkite atsisiųstą failą ir jį įdiekite.</string>
|
||||
<string name="website_troubleshooting_title">Nesklandumų šalinimas</string>
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="other">ဤအရာသည် Briar ၏ စမ်းသပ်ဆဲဗားရှင်းဖြစ်ပါသည်။ သင့်အကောင့်သည် %d ရက်ကြာလျှင် သက်တမ်းကုန်ဆုံးမည်ဖြစ်ပြီး သက်တမ်းတိုး၍မရနိုင်ပါ။</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="other">အန်းဒရိုက် ၄ ကို မပံ့ပိုးတော့ပါ။ Briar သည် %s(ရက်%dတွင်) အလုပ် မလုပ်တော့ပါ။ ကျေးဇူးပြု၍ Briar ကို စက်ပစ္စည်းအသစ်တွင် ထည့်သွင်းပြီး အကောင့်အသစ်တစ်ခု ဖန်တီးပါ။</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">ဤဆော့ဖ်ဝဲသည် သက်တမ်းကုန်သွားပါပြီ။ \nစမ်းသပ်အသုံးပြုခြင်းအတွက် ကျေးဇူးတင်ပါသည်။</string>
|
||||
<string name="download_briar">Briar ကို ဆက်လက်အသုံးပြုရန် နောက်ဆုံးထွက်ထားသည်ကို ဒေါင်းလုဒ်လုပ်ပါ။</string>
|
||||
<string name="create_new_account">အကောင့်အသစ်ဖွင့်ရန် လိုအပ်သော်လည်း သုံးလက်စနာမည်ပြောင်ကို ဆက်သုံးနိုင်ပါသည်။</string>
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
<item quantity="one">Dette er en test-versjon av Briar. Din konto vil utløpe om %d dag, og kan ikke fornyes.</item>
|
||||
<item quantity="other">Dette er en test-versjon av Briar. Din konto vil utløpe om %d dager og kan ikke fornyes.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 er ikke lenger støttet. Briar vil slutte å virke den %s (om %d dag). Vennligst installer Briar på en nyere enhet og lage en ny konto.</item>
|
||||
<item quantity="other">Android 4 er ikke lenger støttet. Briar vil slutte å virke den %s (om %d dager). Vennligst installer Briar på en nyere enhet og lage en ny konto.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Denne programvaren har utløpt.\nTakk for at du testet den.</string>
|
||||
<string name="download_briar">For å fortsette å bruke Briar, vennligst laste ned nyeste utgave.</string>
|
||||
<string name="create_new_account">Du trenger å lage en ny konto, men du kan benytte samme kallenavn.</string>
|
||||
|
||||
@@ -47,6 +47,11 @@
|
||||
<item quantity="many">Esta é uma versão de teste do Briar. Sua conta irá expirar em %d dias e não poderá ser renovada.</item>
|
||||
<item quantity="other">Esta é uma versão de teste do Briar. Sua conta irá expirar em %d dias e não poderá ser renovada.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">A versão 4 do Android já não é mais compatível. Briar deixará de funcionar em %s (dentro de %d dias). Por favor, instale Briar em um novo aparelho e crie uma nova conta.</item>
|
||||
<item quantity="many">A versão 4 do Android já não é mais compatível. Briar deixará de funcionar em %s (dentro de %d dias). Por favor, instale Briar em um novo dispositivo e crie uma nova conta.</item>
|
||||
<item quantity="other">A versão 4 do Android já não é mais compatível. Briar deixará de funcionar em %s (dentro de %d dias). Por favor, instale Briar em um novo dispositivo e crie uma nova conta.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Este software expirou.\nObrigado por testar!</string>
|
||||
<string name="download_briar">Para continuar usando o Briar, por favor baixe a versão mais recente.</string>
|
||||
<string name="create_new_account">Você precisará criar uma nova conta, mas poderá usar o mesmo apelido.</string>
|
||||
|
||||
@@ -50,6 +50,11 @@
|
||||
<item quantity="few">Aceasta este o versiune de test Briar. Contul dvs. va expira în %d zile și nu poate fi reînnoit.</item>
|
||||
<item quantity="other">Aceasta este o versiune de test Briar. Contul dvs. va expira în %d zile și nu poate fi reînnoit.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Versiunea Android 4 nu mai este acceptată. Briar nu va mai funcționa pe %s (în decurs de %d zi). Instalați Briar pe un dispozitiv mai nou și creați un cont nou.</item>
|
||||
<item quantity="few">Versiunea Android 4 nu mai este acceptată. Briar nu va mai funcționa pe %s (în %d zile). Instalați Briar pe un dispozitiv mai nou și creați un cont nou.</item>
|
||||
<item quantity="other">Versiunea Android 4 nu mai este acceptată. Briar nu va mai funcționa pe %s (în %d zile). Instalați Briar pe un dispozitiv mai nou și creați un cont nou.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Acest program software a expirat.\nVă mulțumim că l-ați testat!</string>
|
||||
<string name="download_briar">Pentru a putea să utilizați Briar în continuare, descărcați cea mai recentă versiune.</string>
|
||||
<string name="create_new_account">Va trebui să creați un cont nou, dar puteți să folosiți același pseudonim.</string>
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
<item quantity="many">Это бета-версия Briar. Срок действия вашего аккаунта закончится через %d дней и не может быть возобновлен.</item>
|
||||
<item quantity="other">Это бета-версия Briar. Срок действия вашего аккаунта закончится через %d дней и не может быть возобновлен.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 больше не поддерживается. Briar перестанет работать на %s (через %d день). Пожалуйста, установите Briar на более современное устройство и создайте новую учетную запись.</item>
|
||||
<item quantity="few">Android 4 больше не поддерживается. Briar перестанет работать на %s (через %d дня). Пожалуйста, установите Briar на более современное устройство и создайте новую учетную запись.</item>
|
||||
<item quantity="many">Android 4 больше не поддерживается. Briar перестанет работать на %s (через %d дней). Пожалуйста, установите Briar на более современное устройство и создайте новую учетную запись.</item>
|
||||
<item quantity="other">Android 4 больше не поддерживается. Briar перестанет работать на %s (через %d дней). Пожалуйста, установите Briar на более современное устройство и создайте новый аккаунт.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Срок действия этого программного обеспечения истек.\nСпасибо за тестирование!</string>
|
||||
<string name="download_briar">Для продолжения использования Briar, пожалуйста, скачайте последнюю версию.</string>
|
||||
<string name="create_new_account">Вам необходимо создать новый аккаунт, но вы можете использовать тот же псевдоним.</string>
|
||||
@@ -163,10 +169,10 @@
|
||||
<string name="error">Ошибка</string>
|
||||
<string name="info">Информация</string>
|
||||
<!--Contacts and Private Conversations-->
|
||||
<string name="no_contacts">Нет контактов</string>
|
||||
<string name="no_contacts">Нет контактов для отображения</string>
|
||||
<string name="no_contacts_action">Для добавления контакта нажмите значок +</string>
|
||||
<string name="date_no_private_messages">Нет сообщений.</string>
|
||||
<string name="no_private_messages">Нет сообщений</string>
|
||||
<string name="no_private_messages">Нет сообщений для отображения</string>
|
||||
<string name="message_hint">Новое сообщение</string>
|
||||
<string name="message_hint_auto_delete">Новое исчезающее сообщение</string>
|
||||
<string name="message_error">Ошибка отправки сообщения</string>
|
||||
@@ -237,7 +243,7 @@
|
||||
<string name="messaging_too_many_attachments_toast">Будут отправлены только %d первых изображений</string>
|
||||
<string name="menu_contact">Контакт</string>
|
||||
<!--Adding Contacts-->
|
||||
<string name="add_contact_title">Добавить контакт поблизости</string>
|
||||
<string name="add_contact_title">Добавление контакта поблизости</string>
|
||||
<string name="add_contact_error_two_way">Просканировали ли вы QR-коды друг друга?</string>
|
||||
<string name="face_to_face">Вы должны встретиться с человеком, которого хотите добавить в контакты.\n\nЭто не позволит кому-либо выдать себя за вас или читать ваши сообщения.</string>
|
||||
<string name="continue_button">Продолжить</string>
|
||||
@@ -259,9 +265,9 @@
|
||||
<string name="connection_error_feedback">Если эта проблема сохраняется, пожалуйста <a href="feedback">отправьте отзыв</a>, чтобы помочь нам улучшить приложение.</string>
|
||||
<string name="info_both_must_scan">Вы должны Просканировать QR-коды друг друга.</string>
|
||||
<!--Adding Contacts Remotely-->
|
||||
<string name="add_contact_remotely_title_case">Добавить контакт удаленно</string>
|
||||
<string name="add_contact_remotely_title_case">Добавление контакта удаленно</string>
|
||||
<string name="add_contact_nearby_title">Добавить контакт поблизости</string>
|
||||
<string name="add_contact_remotely_title"> Добавить контакт удаленно</string>
|
||||
<string name="add_contact_remotely_title"> Добавление контакта удаленно</string>
|
||||
<string name="contact_link_intro">Введите ссылку от вашего контакта здесь</string>
|
||||
<string name="contact_link_hint">Ссылка контакта</string>
|
||||
<string name="paste_button">Вставить</string>
|
||||
@@ -357,8 +363,8 @@
|
||||
<string name="connect_via_bluetooth_error">Не удалось подключиться через Bluetooth.</string>
|
||||
<string name="connect_via_bluetooth_error_not_supported">Bluetooth не поддерживается устройством.</string>
|
||||
<!--Private Groups-->
|
||||
<string name="groups_list_empty">Нет групп</string>
|
||||
<string name="groups_list_empty_action">Для создания группы нажмите значок + или попросите у контактов поделиться с вами группами</string>
|
||||
<string name="groups_list_empty">Нет групп для отображения</string>
|
||||
<string name="groups_list_empty_action">Для создания группы нажмите значок + или попросите ваши контакты поделиться с вами группами</string>
|
||||
<string name="groups_created_by">Создано %s</string>
|
||||
<plurals name="messages">
|
||||
<item quantity="one">%d сообщение</item>
|
||||
@@ -415,13 +421,13 @@
|
||||
<string name="groups_reveal_visible_revealed_by_contact">Связь между контактами видна группе (открыта %s)</string>
|
||||
<string name="groups_reveal_invisible">Связь между контактами не видна группе</string>
|
||||
<!--Forums-->
|
||||
<string name="no_forums">Нет форумов</string>
|
||||
<string name="no_forums_action">Для создания форума нажмите значок + или попросите у контактов поделиться с вами форумами</string>
|
||||
<string name="no_forums">Нет форумов для отображения</string>
|
||||
<string name="no_forums_action">Для создания форума нажмите значок + или попросите ваши контакты поделиться с вами форумами</string>
|
||||
<string name="create_forum_title">Создать форум</string>
|
||||
<string name="choose_forum_hint">Придумайте название вашего форума</string>
|
||||
<string name="create_forum_button">Создать форум</string>
|
||||
<string name="forum_created_toast">Форум создан</string>
|
||||
<string name="no_forum_posts">Нет постов</string>
|
||||
<string name="no_forum_posts">Нет постов для отображения</string>
|
||||
<string name="no_posts">Нет постов</string>
|
||||
<plurals name="posts">
|
||||
<item quantity="one">%d пост</item>
|
||||
@@ -441,7 +447,7 @@
|
||||
<string name="forum_share_button">Поделиться форумом</string>
|
||||
<string name="contacts_selected">Выбранные контакты</string>
|
||||
<string name="activity_share_toolbar_header">Выберите контакты</string>
|
||||
<string name="no_contacts_selector">Нет контактов</string>
|
||||
<string name="no_contacts_selector">Нет контактов для отображения</string>
|
||||
<string name="no_contacts_selector_action">Пожалуйста, вернитесь сюда после добавления контакта</string>
|
||||
<string name="forum_shared_snackbar">Поделиться форумом совместно с выбранными контактами</string>
|
||||
<string name="forum_share_message">Добавить сообщение (необязательно)</string>
|
||||
@@ -474,7 +480,7 @@
|
||||
</plurals>
|
||||
<string name="nobody">Никого</string>
|
||||
<!--Blogs-->
|
||||
<string name="blogs_other_blog_empty_state">Нет постов</string>
|
||||
<string name="blogs_other_blog_empty_state">Нет постов для отображения</string>
|
||||
<string name="read_more">подробнее</string>
|
||||
<string name="blogs_write_blog_post">Написать в блоге</string>
|
||||
<string name="blogs_write_blog_post_body_hint">Напишите свой пост в блоге</string>
|
||||
@@ -482,7 +488,7 @@
|
||||
<string name="blogs_blog_post_created">Пост создан</string>
|
||||
<string name="blogs_blog_post_received">Появился новый пост в блоге</string>
|
||||
<string name="blogs_blog_post_scroll_to">Перейти</string>
|
||||
<string name="blogs_feed_empty_state">Нет постов</string>
|
||||
<string name="blogs_feed_empty_state">Нет постов для отображения</string>
|
||||
<string name="blogs_feed_empty_state_action">Посты ваших контактов и блогов, на которые вы подписаны, появятся здесь\n\nНажмите значок пера, чтобы написать пост</string>
|
||||
<string name="blogs_remove_blog">Удалить блог</string>
|
||||
<string name="blogs_remove_blog_dialog_message">Вы уверены, что хотите удалить этот блог?\n\nПосты будут удалены только с вашего устройства.\n\nВсе контакты, с которыми вы поделились этим блогом, могут перестать получать обновления.</string>
|
||||
@@ -520,7 +526,7 @@
|
||||
<string name="blogs_rss_remove_feed">Удалить RSS-ленту</string>
|
||||
<string name="blogs_rss_remove_feed_dialog_message">Вы уверены, что хотите удалить эту ленту?\n\nПосты будут удалены только с вашего устройства.\n\nВсе контакты, с которыми вы поделились этой лентой, могут перестать получать обновления.</string>
|
||||
<string name="blogs_rss_remove_feed_ok">Удалить</string>
|
||||
<string name="blogs_rss_feeds_manage_empty_state">Нет RSS-лент\n\nКоснитесь значка + для импорта ленты</string>
|
||||
<string name="blogs_rss_feeds_manage_empty_state">Нет RSS-лент для отображения\n\nКоснитесь значка + для импорта ленты</string>
|
||||
<string name="blogs_rss_feeds_manage_error">Ошибка при загрузке вашей ленты. Повторите попытку позже.</string>
|
||||
<!--Settings Profile Picture-->
|
||||
<string name="change_profile_picture">Нажмите, чтобы изменить изображение вашего профиля </string>
|
||||
@@ -552,7 +558,7 @@
|
||||
<string name="tor_network_setting_summary">Автоматически: %1$s (%2$s)</string>
|
||||
<string name="tor_mobile_data_title">Использовать мобильные данные</string>
|
||||
<string name="tor_only_when_charging_title">Подключаться к интернету только во время зарядки</string>
|
||||
<string name="tor_only_when_charging_summary">Подключение к интернету будет отключено при работе устройства от батареи</string>
|
||||
<string name="tor_only_when_charging_summary">Отключение интернет-соединения, при работе устройства от батареи</string>
|
||||
<!--Settings Security and Panic-->
|
||||
<string name="security_settings_title">Безопасность</string>
|
||||
<string name="pref_lock_title">Блокировка приложения</string>
|
||||
@@ -594,8 +600,8 @@
|
||||
<string name="purge_setting_summary">Удалить ваш аккаунт Briar при нажатии тревожной кнопки. Внимание: это необратимо удалит ваши идентификаторы, контакты и сообщения</string>
|
||||
<!--Settings Notifications-->
|
||||
<string name="notification_settings_title">Уведомления</string>
|
||||
<string name="notify_sign_in_title">Напоминать мне войти</string>
|
||||
<string name="notify_sign_in_summary">Показывать напоминание при запуске телефона или после обновления приложения.</string>
|
||||
<string name="notify_sign_in_title">Напомнить мне войти</string>
|
||||
<string name="notify_sign_in_summary">Показывать напоминание при запуске телефона или обновлении приложения.</string>
|
||||
<string name="notify_private_messages_setting_title">Личные сообщения</string>
|
||||
<string name="notify_private_messages_setting_summary">Показывать оповещения для личных сообщений</string>
|
||||
<string name="notify_private_messages_setting_summary_26">Настройка оповещений для личных сообщений</string>
|
||||
@@ -617,10 +623,10 @@
|
||||
<!--Mailbox-->
|
||||
<string name="mailbox_settings_title">Mailbox</string>
|
||||
<string name="mailbox_setup_title">Настройка Mailbox</string>
|
||||
<string name="mailbox_setup_intro">Mailbox дает возможность вашим контактам отправлять вам сообщения, пока вы находитесь в оффлайн. Mailbox будет получать ваши сообщения и хранить их до тех пор, пока вы не подключитесь к сети.\n
|
||||
Вы можете установить приложение Briar Mailbox на запасное устройство. Держите его подключенным к питанию и Wi-Fi, чтобы оно всегда было в сети.</string>
|
||||
<string name="mailbox_setup_intro">Mailbox позволяет вашим контактам отправлять вам сообщения, пока вы находитесь в автономном режиме. Mailbox будет получать ваши сообщения и хранить их до тех пор, пока вы не подключитесь к сети.\n
|
||||
\nВы можете установить приложение Briar Mailbox на запасное устройство. Чтобы устройство всегда находилось в сети, подключите его к питанию и Wi-Fi.</string>
|
||||
<string name="mailbox_setup_download">Во-первых, установите приложение Mailbox на другое устройство, выполнив поиск \"Briar Mailbox\" в Google Play или там, откуда вы загрузили Briar.\n
|
||||
\nЗатем свяжите Mailbox с Briar, сосканировав QR-код, показанный приложением Mailbox.</string>
|
||||
\nЗатем свяжите ваш Mailbox с Briar, просканировав QR-код, показанный приложением Mailbox.</string>
|
||||
<string name="mailbox_setup_download_link">Поделиться ссылкой на загрузку</string>
|
||||
<string name="mailbox_setup_button_scan">Сканирование QR-кода Mailbox</string>
|
||||
<string name="permission_camera_qr_denied_body">Вы запретили доступ к камере, однако сканирование QR-кода требует использования камеры.\n\nПожалуйста, рассмотрите возможность предоставления доступа.</string>
|
||||
@@ -715,8 +721,6 @@
|
||||
<string name="disappearing_messages_summary">Сделайте так, чтобы будущие сообщения в этом разговоре автоматически исчезали спустя 7\u00A0дней.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Действия</string>
|
||||
<string name="share_app_link">Поделиться ссылкой на загрузку</string>
|
||||
<string name="share_app_link_text">Загрузить Briar на %s</string>
|
||||
<string name="send_feedback">Отправить отзыв</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Предупреждение о ссылке</string>
|
||||
@@ -766,7 +770,6 @@
|
||||
<string name="permission_camera_title">Доступ к камере</string>
|
||||
<string name="permission_camera_request_body">Для сканирования QR-кода Briar необходим доступ к камере.</string>
|
||||
<string name="permission_location_title">Доступ к местоположению</string>
|
||||
<string name="permission_nearby_devices_title">Разрешение ближайших устройств</string>
|
||||
<string name="permission_location_request_body">Для обнаружения Bluetooth-устройств, Briar требуется разрешение на доступ к вашему местоположению.\n\nBriar не хранит ваше местоположение и не делится им кем-либо еще.</string>
|
||||
<string name="permission_camera_location_title">Камера и местоположение</string>
|
||||
<string name="permission_camera_location_request_body">Для сканирования QR-кода Briar необходим доступ к камере.\n\nДля обнаружения Bluetooth-устройств, Briar требуется разрешение на доступ к вашему местоположению.\n\nBriar не хранит ваше местоположение и не делится им кем-либо еще.</string>
|
||||
@@ -806,8 +809,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Для создания точки доступа Wi-Fi Briar необходимо разрешение на доступ к вашему точному местоположению.\n\nBriar не хранит ваше местоположение и не передает его кому-либо.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Доступ к местоположению запрещен, но Briar необходимо это разрешение для создания точки доступа Wi-Fi.\n\nРассмотрите возможность предоставления доступа.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Доступ к точному местоположению запрещен, но Briar необходимо это разрешение для создания точки доступа Wi-Fi.\n\nРассмотрите возможность предоставления доступа.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Чтобы создать точку доступа Wi-Fi, Briar необходимо получить разрешение на доступ к ближайшим устройствам.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Вы запретили доступ ближайшим устройствам, однако Briar необходимо это разрешение для создания точки доступа Wi-Fi.\n\nПожалуйста, рассмотрите возможность предоставления доступа.</string>
|
||||
<string name="wifi_settings_title">Настройка Wi-Fi</string>
|
||||
<string name="wifi_settings_request_enable_body">Чтобы создать точку доступа Wi-Fi, Briar должен использовать Wi-Fi. Пожалуйста, включите его.</string>
|
||||
<string name="hotspot_tab_manual">Вручную</string>
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
<item quantity="many">Toto je testovacia verzia aplikácie Briar. Platnosť vášho účtu vyprší o %d dní a nie je možné ho obnoviť.</item>
|
||||
<item quantity="other">Toto je testovacia verzia aplikácie Briar. Platnosť vášho účtu vyprší o %d dní a nie je možné ho obnoviť.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Systém Android 4 už nie je podporovaný. Briar prestane fungovať na %s (za %d deň). Nainštalujte si Briar na novšie zariadenie a vytvorte si nový účet.</item>
|
||||
<item quantity="few">Systém Android 4 už nie je podporovaný. Briar prestane fungovať na %s (za %d dni). Nainštalujte si Briar na novšie zariadenie a vytvorte si nový účet.</item>
|
||||
<item quantity="many">Systém Android 4 už nie je podporovaný. Briar prestane fungovať na %s (za %d dní). Nainštalujte si Briar na novšie zariadenie a vytvorte si nový účet.</item>
|
||||
<item quantity="other">Systém Android 4 už nie je podporovaný. Briar prestane fungovať na %s (za %d dní). Nainštalujte si Briar na novšie zariadenie a vytvorte si nový účet.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Platnosť tohto softvéru vypršala.\nĎakujeme za testovanie!</string>
|
||||
<string name="download_briar">Ak chcete pokračovať v používaní aplikácie Briar, stiahnite si najnovšiu verziu.</string>
|
||||
<string name="create_new_account">Budete si musieť vytvoriť nový účet, ale môžete použiť rovnakú prezývku.</string>
|
||||
@@ -716,8 +722,6 @@
|
||||
<string name="disappearing_messages_summary">Nastaviť, aby budúce správy v tejto konverzácii automaticky zmizli po 7\u00A0dňoch.</string>
|
||||
<!--Settings Actions-->
|
||||
<string name="pref_category_actions">Akcie</string>
|
||||
<string name="share_app_link">Zdieľať odkaz na stiahnutie</string>
|
||||
<string name="share_app_link_text">Stiahnuť Briar na %s</string>
|
||||
<string name="send_feedback">Odoslať spätnú väzbu</string>
|
||||
<!--Link Warning-->
|
||||
<string name="link_warning_title">Varovanie o odkaze</string>
|
||||
@@ -767,7 +771,6 @@
|
||||
<string name="permission_camera_title">Povolenie na používanie kamery</string>
|
||||
<string name="permission_camera_request_body">Na naskenovanie QR kódu potrebuje Briar prístup ku kamere.</string>
|
||||
<string name="permission_location_title">Povolenie na určenie polohy</string>
|
||||
<string name="permission_nearby_devices_title">Povolenie pre blízke zariadenia</string>
|
||||
<string name="permission_location_request_body">Na zistenie zariadení Bluetooth potrebuje Briar povolenie na prístup k vašej polohe.\n\nBriar neukladá vašu polohu ani ju s nikým nezdieľa.</string>
|
||||
<string name="permission_camera_location_title">Kamera a poloha</string>
|
||||
<string name="permission_camera_location_request_body">Na skenovanie QR kódu potrebuje Briar prístup ku kamere.\n\nNa zistenie zariadení Bluetooth potrebuje Briar povolenie na prístup k vašej polohe.\n\nBriar neukladá vašu polohu ani ju s nikým nezdieľa.</string>
|
||||
@@ -807,8 +810,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">Na vytvorenie prístupového bodu Wi-Fi potrebuje Briar povolenie na prístup k vašej presnej polohe.\n\nBriar neukladá vašu polohu ani ju s nikým nezdieľa.</string>
|
||||
<string name="permission_hotspot_location_denied_body">Odmietli ste prístup k svojej polohe, ale Briar potrebuje toto povolenie na vytvorenie prístupového bodu Wi-Fi.\n\nProsím, zvážte udelenie prístupu.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">Odmietli ste prístup k presnej polohe, ale Briar potrebuje toto povolenie na vytvorenie prístupového bodu Wi-Fi.\n\nProsím, zvážte udelenie prístupu.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">Na vytvorenie Wi-Fi prístupového bodu potrebuje aplikácia Briar povolenie na prístup k okolitým zariadeniam.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">Odmietli ste prístup k okolitým zariadeniam, ale Briar potrebuje toto povolenie na vytvorenie prístupového bodu Wi-Fi.\n\nProsíme, zvážte udelenie prístupu.</string>
|
||||
<string name="wifi_settings_title">Nastavenie Wi-Fi</string>
|
||||
<string name="wifi_settings_request_enable_body">Ak chcete vytvoriť prístupový bod Wi-Fi, zariadenie Briar musí používať Wi-Fi. Povoľte ho.</string>
|
||||
<string name="hotspot_tab_manual">Manuálne</string>
|
||||
|
||||
@@ -50,6 +50,10 @@ dhe s’mund të hapet me këtë version.\n\nJu lutemi, përmirësojeni me versi
|
||||
<item quantity="one">Ky është një version beta i Briar-it. Llogaria juaj do të skadojë për %d ditë dhe s\’mund të rinovohet.</item>
|
||||
<item quantity="other">Ky është një version beta i Briar-it. Llogaria juaj do të skadojë për %d ditë dhe s\’mund të rinovohet.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 nuk mbulohet më. Briar-i do të reshtë së funksionuari më %s (për %d ditë). Ju lutemi, instalojeni Briar-in në një pajisje më të re dhe krijoni një llogari të re.</item>
|
||||
<item quantity="other">Android 4 nuk mbulohet më. Briar-i do të reshtë së funksionuari më %s (për %d ditë). Ju lutemi, instalojeni Briar-in në një pajisje më të re dhe krijoni një llogari të re.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Ky software ka skaduar.\nFaleminderit që e provuat!</string>
|
||||
<string name="download_briar">Që të vazhdoni të përdorni Briar-in, ju lutemi shkarkoni versionin më të ri.</string>
|
||||
<string name="create_new_account">Do t’ju duhet të krijoni një llogari të re, por mund të përdorni të njëjtën nofkë.</string>
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
<item quantity="one">Det här är en test-version av Briar. Ditt konto kommer att upphöra om %d dagar och kan ej förnyas.</item>
|
||||
<item quantity="other">Det här är en test-version av Briar. Ditt konto kommer att upphöra om %d dag och kan ej förnyas.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 stöds ej längre. Briar kommer att sluta fungera den %s (om %d dag). Vänligen installera Briar på en ny enhet och skapa ett nytt konto.</item>
|
||||
<item quantity="other">Android 4 stöds ej längre. Briar kommer att sluta fungera den %s (om %d dagar). Vänligen installera Briar på en nyare enhet och skapa ett nytt konto.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">Mjukvaran har gått ut.\nTack för att du bidragit till att testa!</string>
|
||||
<string name="download_briar">För att fortsätta använda Briar, hämta den senaste utgåvan.</string>
|
||||
<string name="create_new_account">Du måste skapa ett nytt konto, men du kan använda samma användarnamn.</string>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,12 @@
|
||||
<item quantity="many">Це тестова версія Briar. Термін дії вашого профілю спливає через %d днів. Його не можна продовжити.</item>
|
||||
<item quantity="other">Це тестова версія Briar. Термін дії вашого профілю спливає через %d дня. Його не можна продовжити.</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="one">Android 4 більше не підтримується. Briar припинить роботу %s (за %d день). Будь ласка, встановіть Briar на новіший пристрій і створіть новий обліковий запис.</item>
|
||||
<item quantity="few">Android 4 більше не підтримується. Briar припинить роботу %s (за %d дні). Будь ласка, встановіть Briar на новіший пристрій і створіть новий обліковий запис.</item>
|
||||
<item quantity="many">Android 4 більше не підтримується. Briar припинить роботу %s (за %d днів). Будь ласка, встановіть Briar на новіший пристрій і створіть новий обліковий запис.</item>
|
||||
<item quantity="other">Android 4 більше не підтримується. Briar припинить роботу %s (за %d днів). Будь ласка, встановіть Briar на новіший пристрій і створіть новий обліковий запис.</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">У цієї програми закінчився термін дії\nДякуємо, що тестували її!</string>
|
||||
<string name="download_briar">Щоб далі користуватися Briar, будь ласка, завантажте найновіший випуск.</string>
|
||||
<string name="create_new_account">Вам знадобиться створити новий обліковий запис, але ви можете використовувати те саме ім\'я користувача.</string>
|
||||
@@ -234,7 +240,6 @@
|
||||
<string name="menu_contact">Контакти</string>
|
||||
<!--Adding Contacts-->
|
||||
<string name="add_contact_title">Додати контакт поблизу</string>
|
||||
<string name="add_contact_error_two_way">Чи Ви відсканували QR коди один одного?</string>
|
||||
<string name="face_to_face">Ви маєте зустрітися з особою, яку ви бажаєте додати до списку контактів.\n\nЦе виключить можливість у майбутньому будь-кому видавати себе за вас або читати ваші повідомлення.</string>
|
||||
<string name="continue_button">Продовжити</string>
|
||||
<string name="try_again_button">Спробувати ще раз</string>
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="other">这是 Briar 的一个测试版本。您的帐户将在 %d 天后到期,且无法延期。</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="other">本应用不再支持 Android 4。Briar 将于 %s 停止工作(%d天内)。请在更高版本系统上安装 Briar 并创建一个新帐户</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">本软件已过期。\n感谢您的测试!</string>
|
||||
<string name="download_briar">请下载最新版本以继续使用 Briar</string>
|
||||
<string name="create_new_account">您将需要创建一个新帐户,但可以使用相同的昵称。</string>
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
<plurals name="expiry_warning">
|
||||
<item quantity="other">這是 Briar 的測試版本。您的帳戶將在 %d 天後到期,且無法延期。</item>
|
||||
</plurals>
|
||||
<plurals name="old_android_expiry_warning">
|
||||
<item quantity="other">Briar 已不再支援 Android 4,它將在%s停止運作(%d天時間),請在較新的設備上安裝Briar 並建立新帳號。</item>
|
||||
</plurals>
|
||||
<string name="expiry_date_reached">本軟件已過期。\n感謝您的測試!</string>
|
||||
<string name="download_briar">爲了繼續使用 Briar,請下載最新版。</string>
|
||||
<string name="create_new_account">您要創建一個新帳戶,但可以續用現時的暱稱。</string>
|
||||
|
||||
@@ -733,8 +733,6 @@
|
||||
|
||||
<!-- Settings Actions -->
|
||||
<string name="pref_category_actions">Actions</string>
|
||||
<string name="share_app_link">Share download link</string>
|
||||
<string name="share_app_link_text">Download Briar at %s</string>
|
||||
<string name="send_feedback">Send feedback</string>
|
||||
|
||||
<!-- Link Warning -->
|
||||
@@ -789,7 +787,6 @@
|
||||
<string name="permission_camera_title">Camera permission</string>
|
||||
<string name="permission_camera_request_body">To scan the QR code, Briar needs access to the camera.</string>
|
||||
<string name="permission_location_title">Location permission</string>
|
||||
<string name="permission_nearby_devices_title">Nearby devices permission</string>
|
||||
<string name="permission_location_request_body">To discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
|
||||
<string name="permission_camera_location_title">Camera and location</string>
|
||||
<string name="permission_camera_location_request_body">To scan the QR code, Briar needs access to the camera.\n\nTo discover Bluetooth devices, Briar needs permission to access your location.\n\nBriar does not store your location or share it with anyone.</string>
|
||||
@@ -834,8 +831,6 @@
|
||||
<string name="permission_hotspot_location_request_precise_body">To create a Wi-Fi hotspot, Briar needs permission to access your precise location.\n\nBriar does not store your location or share it with anyone.</string>
|
||||
<string name="permission_hotspot_location_denied_body">You have denied access to your location, but Briar needs this permission to create a Wi-Fi hotspot.\n\nPlease consider granting access.</string>
|
||||
<string name="permission_hotspot_location_denied_precise_body">You have denied access to your precise location, but Briar needs this permission to create a Wi-Fi hotspot.\n\nPlease consider granting access.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_request_body">To create a Wi-Fi hotspot, Briar needs permission to access nearby devices.</string>
|
||||
<string name="permission_hotspot_nearby_wifi_denied_body">You have denied access to nearby devices, but Briar needs this permission to create a Wi-Fi hotspot.\n\nPlease consider granting access.</string>
|
||||
<string name="wifi_settings_title">Wi-Fi setting</string>
|
||||
<string name="wifi_settings_request_enable_body">To create a Wi-Fi hotspot, Briar needs to use Wi-Fi. Please enable it.</string>
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
android:title="@string/mailbox_settings_title"
|
||||
app:icon="@drawable/ic_mailbox" />
|
||||
|
||||
<Preference
|
||||
android:title="@string/about_title"
|
||||
app:fragment="org.briarproject.briar.android.settings.AboutFragment"
|
||||
app:icon="@drawable/ic_info_dark" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="pref_key_actions"
|
||||
android:layout="@layout/preferences_category"
|
||||
@@ -42,11 +47,6 @@
|
||||
android:targetClass="org.briarproject.briar.android.hotspot.HotspotActivity"
|
||||
android:targetPackage="@string/app_package" />
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="pref_key_share_app_link"
|
||||
android:title="@string/share_app_link"
|
||||
app:icon="@drawable/ic_settings_share_link">
|
||||
</Preference>
|
||||
<Preference
|
||||
android:key="pref_key_send_feedback"
|
||||
android:title="@string/send_feedback"
|
||||
@@ -74,10 +74,4 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<Preference
|
||||
android:title="@string/about_title"
|
||||
app:allowDividerAbove="true"
|
||||
app:fragment="org.briarproject.briar.android.settings.AboutFragment"
|
||||
app:icon="@drawable/ic_info_dark" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -74,13 +74,6 @@ public interface BlogManager {
|
||||
@Nullable String comment, BlogPostHeader parentHeader)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Adds a comment to an existing blog post or reblogs it.
|
||||
*/
|
||||
void addLocalComment(Transaction txn, LocalAuthor author,
|
||||
GroupId groupId, @Nullable String comment,
|
||||
BlogPostHeader parentHeader) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the blog with the given ID.
|
||||
*/
|
||||
@@ -106,11 +99,6 @@ public interface BlogManager {
|
||||
*/
|
||||
Collection<Blog> getBlogs() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all blogs to which the user subscribes.
|
||||
*/
|
||||
Collection<Blog> getBlogs(Transaction txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group IDs of all blogs to which the user subscribes.
|
||||
*/
|
||||
@@ -148,11 +136,6 @@ public interface BlogManager {
|
||||
*/
|
||||
void setReadFlag(MessageId m, boolean read) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks a blog post as read or unread.
|
||||
*/
|
||||
void setReadFlag(Transaction txn, MessageId m, boolean read) throws DbException;
|
||||
|
||||
/**
|
||||
* Registers a hook to be called whenever a blog is removed.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user