Compare commits

..

1 Commits

Author SHA1 Message Date
akwizgran
934997ed91 Check for partial setup of clients due to feature flags reverting. 2023-01-31 11:23:19 +00:00
116 changed files with 999 additions and 1975 deletions

View File

@@ -83,8 +83,7 @@ android test:
test_reproducible:
stage: check_reproducibility
script:
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[APP]='briar' -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
- "curl -X POST -F token=${RELEASE_JAR_CHECK_TOKEN} -F ref=main -F variables[APP]='briar-headless' -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/307/trigger/pipeline"
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
only:
- tags

View File

@@ -13,8 +13,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 31
versionCode 10423
versionName "1.4.23"
versionCode 10420
versionName "1.4.20"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -71,7 +71,7 @@ def torLibsDir = 'src/main/jniLibs'
task cleanTorBinaries {
outputs.dir torLibsDir
doLast {
delete fileTree(torLibsDir)
delete fileTree(torLibsDir) { include '**/*.so' }
}
}
@@ -80,9 +80,34 @@ clean.dependsOn cleanTorBinaries
task unpackTorBinaries {
outputs.dir torLibsDir
doLast {
copy {
from configurations.tor.collect { zipTree(it) }
into torLibsDir
configurations.tor.each { outer ->
zipTree(outer).each { inner ->
if (inner.name.endsWith('_arm_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'armeabi-v7a/lib$1.so'
}
} else if (inner.name.endsWith('_arm64_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'arm64-v8a/lib$1.so'
}
} else if (inner.name.endsWith('_x86_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'x86/lib$1.so'
}
} else if (inner.name.endsWith('_x86_64_pie.zip')) {
copy {
from zipTree(inner)
into torLibsDir
rename '(.*)', 'x86_64/lib$1.so'
}
}
}
}
}
dependsOn cleanTorBinaries

View File

@@ -33,10 +33,8 @@ class AndroidBluetoothTransportConnection
super(plugin);
this.connectionLimiter = connectionLimiter;
this.socket = socket;
InputStream socketIn = socket.getInputStream();
if (socketIn == null) throw new IOException();
in = timeoutMonitor.createTimeoutInputStream(socketIn,
plugin.getMaxIdleTime() * 2L);
in = timeoutMonitor.createTimeoutInputStream(
socket.getInputStream(), plugin.getMaxIdleTime() * 2);
wakeLock = wakeLockManager.createWakeLock("BluetoothConnection");
wakeLock.acquire();
String address = socket.getRemoteDevice().getAddress();
@@ -50,9 +48,7 @@ class AndroidBluetoothTransportConnection
@Override
protected OutputStream getOutputStream() throws IOException {
OutputStream socketOut = socket.getOutputStream();
if (socketOut == null) throw new IOException();
return socketOut;
return socket.getOutputStream();
}
@Override

View File

@@ -24,9 +24,9 @@ dependencyVerification {
'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:obfs4proxy-android:0.0.14-tor2:obfs4proxy-android-0.0.14-tor2.jar:a0a93770d6760ce57d9dbd31cc7177687374e00c3361dac22ab75e3b6e0f289e',
'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.briarproject:obfs4proxy-android:0.0.14-tor1:obfs4proxy-android-0.0.14-tor1.jar:8b08068778b133484b17956d8f7a7710739c33f671a26a68156f4d34e6f28c30',
'org.briarproject:snowflake-android:2.3.1:snowflake-android-2.3.1.jar:1f83c9a070f87b7074af13627709a8b5aced5460104be7166af736b1bb73c293',
'org.briarproject:tor-android:0.4.7.13:tor-android-0.4.7.13.jar:7852aab7d2298b80878c7719f34ce665725b494d673ecf2e6f9e697564638cc6',
'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',

View File

@@ -16,7 +16,6 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@Immutable
@@ -24,24 +23,17 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
public abstract class BdfMessageValidator implements MessageValidator {
protected static final Logger LOG =
getLogger(BdfMessageValidator.class.getName());
Logger.getLogger(BdfMessageValidator.class.getName());
protected final ClientHelper clientHelper;
protected final MetadataEncoder metadataEncoder;
protected final Clock clock;
protected final boolean canonical;
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock, boolean canonical) {
this.clientHelper = clientHelper;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
this.canonical = canonical;
}
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
this(clientHelper, metadataEncoder, clock, true);
this.clientHelper = clientHelper;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
}
protected abstract BdfMessageContext validateMessage(Message m, Group g,
@@ -57,7 +49,7 @@ public abstract class BdfMessageValidator implements MessageValidator {
"Timestamp is too far in the future");
}
try {
BdfList bodyList = clientHelper.toList(m, canonical);
BdfList bodyList = clientHelper.toList(m.getBody());
BdfMessageContext result = validateMessage(m, g, bodyList);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());

View File

@@ -49,9 +49,6 @@ public interface ClientHelper {
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
FormatException;
BdfList getMessageAsList(Transaction txn, MessageId m, boolean canonical)
throws DbException, FormatException;
BdfDictionary getGroupMetadataAsDictionary(GroupId g) throws DbException,
FormatException;
@@ -109,8 +106,6 @@ public interface ClientHelper {
BdfList toList(Message m) throws FormatException;
BdfList toList(Message m, boolean canonical) throws FormatException;
BdfList toList(Author a);
byte[] sign(String label, BdfList toSign, PrivateKey privateKey)

View File

@@ -11,7 +11,7 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
public final class BdfDictionary extends TreeMap<String, Object> {
public class BdfDictionary extends TreeMap<String, Object> {
public static final Object NULL_VALUE = new Object();
@@ -39,9 +39,9 @@ public final class BdfDictionary extends TreeMap<String, Object> {
}
public Boolean getBoolean(String key) throws FormatException {
Boolean value = getOptionalBoolean(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
throw new FormatException();
}
@Nullable
@@ -52,16 +52,19 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Boolean getBoolean(String key, Boolean defaultValue)
throws FormatException {
Boolean value = getOptionalBoolean(key);
return value == null ? defaultValue : value;
public Boolean getBoolean(String key, Boolean defaultValue) {
Object o = get(key);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getLong(String key) throws FormatException {
Long value = getOptionalLong(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
throw new FormatException();
}
@Nullable
@@ -75,37 +78,20 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Long getLong(String key, Long defaultValue) throws FormatException {
Long value = getOptionalLong(key);
return value == null ? defaultValue : value;
}
public Integer getInt(String key) throws FormatException {
Integer value = getOptionalInt(key);
if (value == null) throw new FormatException();
return value;
}
@Nullable
public Integer getOptionalInt(String key) throws FormatException {
Long value = getOptionalLong(key);
if (value == null) return null;
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
throw new FormatException();
}
return value.intValue();
}
public Integer getInt(String key, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(key);
return value == null ? defaultValue : value;
public Long getLong(String key, Long defaultValue) {
Object o = get(key);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
return defaultValue;
}
public Double getDouble(String key) throws FormatException {
Double value = getOptionalDouble(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
throw new FormatException();
}
@Nullable
@@ -117,16 +103,17 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public Double getDouble(String key, Double defaultValue)
throws FormatException {
Double value = getOptionalDouble(key);
return value == null ? defaultValue : value;
public Double getDouble(String key, Double defaultValue) {
Object o = get(key);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
return defaultValue;
}
public String getString(String key) throws FormatException {
String value = getOptionalString(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof String) return (String) o;
throw new FormatException();
}
@Nullable
@@ -137,16 +124,17 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public String getString(String key, String defaultValue)
throws FormatException {
String value = getOptionalString(key);
return value == null ? defaultValue : value;
public String getString(String key, String defaultValue) {
Object o = get(key);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(String key) throws FormatException {
byte[] value = getOptionalRaw(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
throw new FormatException();
}
@Nullable
@@ -158,16 +146,17 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public byte[] getRaw(String key, byte[] defaultValue)
throws FormatException {
byte[] value = getOptionalRaw(key);
return value == null ? defaultValue : value;
public byte[] getRaw(String key, byte[] defaultValue) {
Object o = get(key);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
return defaultValue;
}
public BdfList getList(String key) throws FormatException {
BdfList value = getOptionalList(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
throw new FormatException();
}
@Nullable
@@ -178,16 +167,16 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public BdfList getList(String key, BdfList defaultValue)
throws FormatException {
BdfList value = getOptionalList(key);
return value == null ? defaultValue : value;
public BdfList getList(String key, BdfList defaultValue) {
Object o = get(key);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(String key) throws FormatException {
BdfDictionary value = getOptionalDictionary(key);
if (value == null) throw new FormatException();
return value;
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
throw new FormatException();
}
@Nullable
@@ -199,9 +188,9 @@ public final class BdfDictionary extends TreeMap<String, Object> {
throw new FormatException();
}
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue)
throws FormatException {
BdfDictionary value = getOptionalDictionary(key);
return value == null ? defaultValue : value;
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) {
Object o = get(key);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -13,7 +13,7 @@ import javax.annotation.concurrent.NotThreadSafe;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
@NotThreadSafe
public final class BdfList extends ArrayList<Object> {
public class BdfList extends ArrayList<Object> {
/**
* Factory method for constructing lists inline.
@@ -33,15 +33,15 @@ public final class BdfList extends ArrayList<Object> {
super(items);
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isInRange(int index) {
return index >= 0 && index < size();
}
public Boolean getBoolean(int index) throws FormatException {
Boolean value = getOptionalBoolean(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
throw new FormatException();
}
@Nullable
@@ -53,16 +53,21 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Boolean getBoolean(int index, Boolean defaultValue)
throws FormatException {
Boolean value = getOptionalBoolean(index);
return value == null ? defaultValue : value;
public Boolean getBoolean(int index, Boolean defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Boolean) return (Boolean) o;
return defaultValue;
}
public Long getLong(int index) throws FormatException {
Long value = getOptionalLong(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
throw new FormatException();
}
@Nullable
@@ -77,37 +82,22 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Long getLong(int index, Long defaultValue) throws FormatException {
Long value = getOptionalLong(index);
return value == null ? defaultValue : value;
}
public Integer getInt(int index) throws FormatException {
Integer value = getOptionalInt(index);
if (value == null) throw new FormatException();
return value;
}
@Nullable
public Integer getOptionalInt(int index) throws FormatException {
Long value = getOptionalLong(index);
if (value == null) return null;
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
throw new FormatException();
}
return value.intValue();
}
public Integer getInt(int index, Integer defaultValue)
throws FormatException {
Integer value = getOptionalInt(index);
return value == null ? defaultValue : value;
public Long getLong(int index, Long defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Long) return (Long) o;
if (o instanceof Integer) return ((Integer) o).longValue();
if (o instanceof Short) return ((Short) o).longValue();
if (o instanceof Byte) return ((Byte) o).longValue();
return defaultValue;
}
public Double getDouble(int index) throws FormatException {
Double value = getOptionalDouble(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
throw new FormatException();
}
@Nullable
@@ -120,16 +110,19 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public Double getDouble(int index, Double defaultValue)
throws FormatException {
Double value = getOptionalDouble(index);
return value == null ? defaultValue : value;
public Double getDouble(int index, Double defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof Double) return (Double) o;
if (o instanceof Float) return ((Float) o).doubleValue();
return defaultValue;
}
public String getString(int index) throws FormatException {
String value = getOptionalString(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof String) return (String) o;
throw new FormatException();
}
@Nullable
@@ -141,16 +134,19 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public String getString(int index, String defaultValue)
throws FormatException {
String value = getOptionalString(index);
return value == null ? defaultValue : value;
public String getString(int index, String defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof String) return (String) o;
return defaultValue;
}
public byte[] getRaw(int index) throws FormatException {
byte[] value = getOptionalRaw(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
throw new FormatException();
}
@Nullable
@@ -163,16 +159,19 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public byte[] getRaw(int index, byte[] defaultValue)
throws FormatException {
byte[] value = getOptionalRaw(index);
return value == null ? defaultValue : value;
public byte[] getRaw(int index, byte[] defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof byte[]) return (byte[]) o;
if (o instanceof Bytes) return ((Bytes) o).getBytes();
return defaultValue;
}
public BdfList getList(int index) throws FormatException {
BdfList value = getOptionalList(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
throw new FormatException();
}
@Nullable
@@ -184,16 +183,18 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public BdfList getList(int index, BdfList defaultValue)
throws FormatException {
BdfList value = getOptionalList(index);
return value == null ? defaultValue : value;
public BdfList getList(int index, BdfList defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfList) return (BdfList) o;
return defaultValue;
}
public BdfDictionary getDictionary(int index) throws FormatException {
BdfDictionary value = getOptionalDictionary(index);
if (value == null) throw new FormatException();
return value;
if (!isInRange(index)) throw new FormatException();
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
throw new FormatException();
}
@Nullable
@@ -206,9 +207,10 @@ public final class BdfList extends ArrayList<Object> {
throw new FormatException();
}
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue)
throws FormatException {
BdfDictionary value = getOptionalDictionary(index);
return value == null ? defaultValue : value;
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
if (!isInRange(index)) return defaultValue;
Object o = get(index);
if (o instanceof BdfDictionary) return (BdfDictionary) o;
return defaultValue;
}
}

View File

@@ -32,12 +32,6 @@ public interface BdfReader {
void skipLong() throws IOException;
boolean hasInt() throws IOException;
int readInt() throws IOException;
void skipInt() throws IOException;
boolean hasDouble() throws IOException;
double readDouble() throws IOException;
@@ -60,11 +54,23 @@ public interface BdfReader {
BdfList readList() throws IOException;
void readListStart() throws IOException;
boolean hasListEnd() throws IOException;
void readListEnd() throws IOException;
void skipList() throws IOException;
boolean hasDictionary() throws IOException;
BdfDictionary readDictionary() throws IOException;
void readDictionaryStart() throws IOException;
boolean hasDictionaryEnd() throws IOException;
void readDictionaryEnd() throws IOException;
void skipDictionary() throws IOException;
}

View File

@@ -9,8 +9,6 @@ public interface BdfReaderFactory {
BdfReader createReader(InputStream in);
BdfReader createReader(InputStream in, boolean canonical);
BdfReader createReader(InputStream in, int nestedLimit,
int maxBufferSize, boolean canonical);
int maxBufferSize);
}

View File

@@ -24,5 +24,13 @@ public interface BdfWriter {
void writeList(Collection<?> c) throws IOException;
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
void writeDictionary(Map<?, ?> m) throws IOException;
void writeDictionaryStart() throws IOException;
void writeDictionaryEnd() throws IOException;
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
@@ -35,16 +34,6 @@ public interface MailboxManager {
*/
MailboxPairingTask startPairingTask(String qrCodePayload);
/**
* Takes a textual QR code representation in
* {@link org.briarproject.bramble.util.Base32} format and converts it
* into a qrCodePayload as expected by {@link #startPairingTask(String)}.
*
* @throws FormatException when the provided payload did not include a
* proper briar-mailbox:// link.
*/
String convertBase32Payload(String base32Payload) throws FormatException;
/**
* Can be used by the UI to test the mailbox connection.
*

View File

@@ -14,7 +14,6 @@ import java.util.regex.Pattern;
import javax.annotation.Nullable;
import static java.nio.charset.CodingErrorAction.IGNORE;
import static java.nio.charset.CodingErrorAction.REPORT;
import static java.util.regex.Pattern.CASE_INSENSITIVE;
@SuppressWarnings("CharsetObjectCanBeUsed")
@@ -53,38 +52,26 @@ public class StringUtils {
return s.getBytes(UTF_8);
}
public static String fromUtf8(byte[] bytes) throws FormatException {
return fromUtf8(bytes, 0, bytes.length, true);
public static String fromUtf8(byte[] bytes) {
return fromUtf8(bytes, 0, bytes.length);
}
public static String fromUtf8(byte[] bytes, int off, int len)
throws FormatException {
return fromUtf8(bytes, off, len, true);
}
private static String fromUtf8(byte[] bytes, int off, int len,
boolean strict) throws FormatException {
public static String fromUtf8(byte[] bytes, int off, int len) {
CharsetDecoder decoder = UTF_8.newDecoder();
decoder.onMalformedInput(strict ? REPORT : IGNORE);
decoder.onUnmappableCharacter(strict ? REPORT : IGNORE);
decoder.onMalformedInput(IGNORE);
decoder.onUnmappableCharacter(IGNORE);
ByteBuffer buffer = ByteBuffer.wrap(bytes, off, len);
try {
return decoder.decode(buffer).toString();
} catch (CharacterCodingException e) {
throw new FormatException();
throw new AssertionError(e);
}
}
public static String truncateUtf8(String s, int maxUtf8Length) {
byte[] utf8 = toUtf8(s);
if (utf8.length <= maxUtf8Length) return s;
// Don't be strict when converting back, so that if we truncate a
// multi-byte character the whole character gets dropped
try {
return fromUtf8(utf8, 0, maxUtf8Length, false);
} catch (FormatException e) {
throw new AssertionError(e);
}
return fromUtf8(utf8, 0, maxUtf8Length);
}
/**

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
@@ -9,12 +8,9 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
import static java.lang.Boolean.TRUE;
import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class BdfDictionaryTest extends BrambleTestCase {
@@ -23,20 +19,20 @@ public class BdfDictionaryTest extends BrambleTestCase {
public void testConstructors() {
assertEquals(Collections.<String, Object>emptyMap(),
new BdfDictionary());
assertEquals(singletonMap("foo", NULL_VALUE),
new BdfDictionary(singletonMap("foo", NULL_VALUE)));
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE)));
}
@Test
public void testFactoryMethod() {
assertEquals(Collections.<String, Object>emptyMap(),
BdfDictionary.of());
assertEquals(singletonMap("foo", NULL_VALUE),
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
}
@Test
public void testLongPromotion() throws Exception {
public void testIntegerPromotion() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("foo", (byte) 1);
d.put("bar", (short) 2);
@@ -48,33 +44,6 @@ public class BdfDictionaryTest extends BrambleTestCase {
assertEquals(Long.valueOf(4), d.getLong("bam"));
}
@Test
public void testIntPromotionAndDemotion() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("foo", (byte) 1);
d.put("bar", (short) 2);
d.put("baz", 3);
d.put("bam", 4L);
assertEquals(Integer.valueOf(1), d.getInt("foo"));
assertEquals(Integer.valueOf(2), d.getInt("bar"));
assertEquals(Integer.valueOf(3), d.getInt("baz"));
assertEquals(Integer.valueOf(4), d.getInt("bam"));
}
@Test(expected = FormatException.class)
public void testIntUnderflow() throws Exception {
BdfDictionary d =
BdfDictionary.of(new BdfEntry("foo", Integer.MIN_VALUE - 1L));
d.getInt("foo");
}
@Test(expected = FormatException.class)
public void testIntOverflow() throws Exception {
BdfDictionary d =
BdfDictionary.of(new BdfEntry("foo", Integer.MAX_VALUE + 1L));
d.getInt("foo");
}
@Test
public void testFloatPromotion() throws Exception {
BdfDictionary d = new BdfDictionary();
@@ -98,7 +67,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testKeySetIteratorIsOrderedByKeys() {
public void testKeySetIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);
@@ -117,7 +86,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testValuesIteratorIsOrderedByKeys() {
public void testValuesIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);
@@ -136,7 +105,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testEntrySetIteratorIsOrderedByKeys() {
public void testEntrySetIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);
@@ -161,284 +130,4 @@ public class BdfDictionaryTest extends BrambleTestCase {
assertEquals("d", e.getKey());
assertEquals(4, e.getValue());
}
@Test(expected = FormatException.class)
public void testMissingValueForBooleanThrowsFormatException()
throws Exception {
new BdfDictionary().getBoolean("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForLongThrowsFormatException()
throws Exception {
new BdfDictionary().getLong("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForIntThrowsFormatException() throws Exception {
new BdfDictionary().getInt("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForDoubleThrowsFormatException()
throws Exception {
new BdfDictionary().getDouble("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForStringThrowsFormatException()
throws Exception {
new BdfDictionary().getString("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForRawThrowsFormatException() throws Exception {
new BdfDictionary().getRaw("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForListThrowsFormatException()
throws Exception {
new BdfDictionary().getList("foo");
}
@Test(expected = FormatException.class)
public void testMissingValueForDictionaryThrowsFormatException()
throws Exception {
new BdfDictionary().getDictionary("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForBooleanThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getBoolean("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForLongThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getLong("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForIntThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getInt("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForDoubleThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getDouble("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForStringThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getString("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForRawThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getRaw("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForListThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getList("foo");
}
@Test(expected = FormatException.class)
public void testNullValueForDictionaryThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)).getDictionary("foo");
}
@Test
public void testOptionalMethodsReturnNullForMissingValue()
throws Exception {
testOptionalMethodsReturnNull(new BdfDictionary());
}
@Test
public void testOptionalMethodsReturnNullForNullValue() throws Exception {
BdfDictionary d = BdfDictionary.of(new BdfEntry("foo", NULL_VALUE));
testOptionalMethodsReturnNull(d);
}
private void testOptionalMethodsReturnNull(BdfDictionary d)
throws Exception {
assertNull(d.getOptionalBoolean("foo"));
assertNull(d.getOptionalLong("foo"));
assertNull(d.getOptionalInt("foo"));
assertNull(d.getOptionalDouble("foo"));
assertNull(d.getOptionalString("foo"));
assertNull(d.getOptionalRaw("foo"));
assertNull(d.getOptionalList("foo"));
assertNull(d.getOptionalDictionary("foo"));
}
@Test
public void testDefaultMethodsReturnDefaultForMissingValue()
throws Exception {
testDefaultMethodsReturnDefault(new BdfDictionary());
}
@Test
public void testDefaultMethodsReturnDefaultForNullValue() throws Exception {
BdfDictionary d = BdfDictionary.of(new BdfEntry("foo", NULL_VALUE));
testDefaultMethodsReturnDefault(d);
}
private void testDefaultMethodsReturnDefault(BdfDictionary d)
throws Exception {
assertEquals(TRUE, d.getBoolean("foo", TRUE));
assertEquals(Long.valueOf(123L), d.getLong("foo", 123L));
assertEquals(Integer.valueOf(123), d.getInt("foo", 123));
assertEquals(Double.valueOf(123D), d.getDouble("foo", 123D));
assertEquals("123", d.getString("foo", "123"));
byte[] defaultRaw = {1, 2, 3};
assertArrayEquals(defaultRaw, d.getRaw("foo", defaultRaw));
BdfList defaultList = BdfList.of(1, 2, 3);
assertEquals(defaultList, d.getList("foo", defaultList));
BdfDictionary defaultDict = BdfDictionary.of(new BdfEntry("123", 123));
assertEquals(defaultDict, d.getDictionary("foo", defaultDict));
}
@Test(expected = FormatException.class)
public void testWrongTypeForBooleanThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getBoolean("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalBooleanThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalBoolean("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultBooleanThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getBoolean("foo", true);
}
@Test(expected = FormatException.class)
public void testWrongTypeForLongThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getLong("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalLongThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getOptionalLong("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultLongThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getLong("foo", 1L);
}
@Test(expected = FormatException.class)
public void testWrongTypeForIntThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getInt("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalIntThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getOptionalInt("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultIntThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 1.23)).getInt("foo", 1);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDoubleThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getDouble("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalDoubleThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalDouble("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultDoubleThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getDouble("foo", 1D);
}
@Test(expected = FormatException.class)
public void testWrongTypeForStringThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getString("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalStringThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalString("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultStringThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getString("foo", "");
}
@Test(expected = FormatException.class)
public void testWrongTypeForRawThrowsFormatException() throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getRaw("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalRawThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalRaw("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultRawThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getRaw("foo", new byte[0]);
}
@Test(expected = FormatException.class)
public void testWrongTypeForListThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getList("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalListThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalList("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultListThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getList("foo",
new BdfList());
}
@Test(expected = FormatException.class)
public void testWrongTypeForDictionaryThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getDictionary("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalDictionaryThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getOptionalDictionary("foo");
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultDictionaryThrowsFormatException()
throws Exception {
BdfDictionary.of(new BdfEntry("foo", 123)).getDictionary("foo",
new BdfDictionary());
}
}

View File

@@ -5,31 +5,31 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import static java.lang.Boolean.TRUE;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import java.util.Arrays;
import java.util.Collections;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class BdfListTest extends BrambleTestCase {
@Test
public void testConstructors() {
assertEquals(emptyList(), new BdfList());
assertEquals(asList(1, 2, NULL_VALUE),
new BdfList(asList(1, 2, NULL_VALUE)));
assertEquals(Collections.emptyList(), new BdfList());
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
new BdfList(Arrays.asList(1, 2, NULL_VALUE)));
}
@Test
public void testFactoryMethod() {
assertEquals(emptyList(), BdfList.of());
assertEquals(asList(1, 2, NULL_VALUE), BdfList.of(1, 2, NULL_VALUE));
assertEquals(Collections.emptyList(), BdfList.of());
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
BdfList.of(1, 2, NULL_VALUE));
}
@Test
public void testLongPromotion() throws Exception {
public void testIntegerPromotion() throws Exception {
BdfList list = new BdfList();
list.add((byte) 1);
list.add((short) 2);
@@ -41,31 +41,6 @@ public class BdfListTest extends BrambleTestCase {
assertEquals(Long.valueOf(4), list.getLong(3));
}
@Test
public void testIntPromotionAndDemotion() throws Exception {
BdfList list = new BdfList();
list.add((byte) 1);
list.add((short) 2);
list.add(3);
list.add(4L);
assertEquals(Integer.valueOf(1), list.getInt(0));
assertEquals(Integer.valueOf(2), list.getInt(1));
assertEquals(Integer.valueOf(3), list.getInt(2));
assertEquals(Integer.valueOf(4), list.getInt(3));
}
@Test(expected = FormatException.class)
public void testIntUnderflow() throws Exception {
BdfList list = BdfList.of(Integer.MIN_VALUE - 1L);
list.getInt(0);
}
@Test(expected = FormatException.class)
public void testIntOverflow() throws Exception {
BdfList list = BdfList.of(Integer.MAX_VALUE + 1L);
list.getInt(0);
}
@Test
public void testFloatPromotion() throws Exception {
BdfList list = new BdfList();
@@ -88,6 +63,61 @@ public class BdfListTest extends BrambleTestCase {
assertArrayEquals(new byte[123], second);
}
@Test
@SuppressWarnings("ConstantConditions")
public void testIndexOutOfBoundsReturnsDefaultValue() throws Exception {
BdfList list = BdfList.of(1, 2, 3);
boolean defaultBoolean = true;
assertEquals(defaultBoolean, list.getBoolean(-1, defaultBoolean));
assertEquals(defaultBoolean, list.getBoolean(3, defaultBoolean));
Long defaultLong = 123L;
assertEquals(defaultLong, list.getLong(-1, defaultLong));
assertEquals(defaultLong, list.getLong(3, defaultLong));
Double defaultDouble = 1.23;
assertEquals(defaultDouble, list.getDouble(-1, defaultDouble));
assertEquals(defaultDouble, list.getDouble(3, defaultDouble));
String defaultString = "123";
assertEquals(defaultString, list.getString(-1, defaultString));
assertEquals(defaultString, list.getString(3, defaultString));
byte[] defaultBytes = new byte[] {1, 2, 3};
assertArrayEquals(defaultBytes, list.getRaw(-1, defaultBytes));
assertArrayEquals(defaultBytes, list.getRaw(3, defaultBytes));
BdfList defaultList = BdfList.of(1, 2, 3);
assertEquals(defaultList, list.getList(-1, defaultList));
assertEquals(defaultList, list.getList(3, defaultList));
BdfDictionary defaultDict = BdfDictionary.of(
new BdfEntry("1", 1),
new BdfEntry("2", 2),
new BdfEntry("3", 3)
);
assertEquals(defaultDict, list.getDictionary(-1, defaultDict));
assertEquals(defaultDict, list.getDictionary(3, defaultDict));
}
@Test
@SuppressWarnings("ConstantConditions")
public void testWrongTypeReturnsDefaultValue() throws Exception {
BdfList list = BdfList.of(1, 2, 3, true);
boolean defaultBoolean = true;
assertEquals(defaultBoolean, list.getBoolean(0, defaultBoolean));
Long defaultLong = 123L;
assertEquals(defaultLong, list.getLong(3, defaultLong));
Double defaultDouble = 1.23;
assertEquals(defaultDouble, list.getDouble(0, defaultDouble));
String defaultString = "123";
assertEquals(defaultString, list.getString(0, defaultString));
byte[] defaultBytes = new byte[] {1, 2, 3};
assertArrayEquals(defaultBytes, list.getRaw(0, defaultBytes));
BdfList defaultList = BdfList.of(1, 2, 3);
assertEquals(defaultList, list.getList(0, defaultList));
BdfDictionary defaultDict = BdfDictionary.of(
new BdfEntry("1", 1),
new BdfEntry("2", 2),
new BdfEntry("3", 3)
);
assertEquals(defaultDict, list.getDictionary(0, defaultDict));
}
@Test(expected = FormatException.class)
public void testNegativeIndexForBooleanThrowsFormatException()
throws Exception {
@@ -100,12 +130,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalBoolean(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultBooleanThrowsFormatException()
throws Exception {
new BdfList().getBoolean(-1, true);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForLongThrowsFormatException()
throws Exception {
@@ -118,30 +142,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalLong(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultLongThrowsFormatException()
throws Exception {
new BdfList().getLong(-1, 1L);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForIntThrowsFormatException()
throws Exception {
new BdfList().getInt(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForOptionalIntThrowsFormatException()
throws Exception {
new BdfList().getOptionalInt(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultIntThrowsFormatException()
throws Exception {
new BdfList().getInt(-1, 1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDoubleThrowsFormatException()
throws Exception {
@@ -154,12 +154,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalDouble(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultDoubleThrowsFormatException()
throws Exception {
new BdfList().getDouble(-1, 1D);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForStringThrowsFormatException()
throws Exception {
@@ -172,12 +166,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalString(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultStringThrowsFormatException()
throws Exception {
new BdfList().getString(-1, "");
}
@Test(expected = FormatException.class)
public void testNegativeIndexForRawThrowsFormatException()
throws Exception {
@@ -190,12 +178,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalRaw(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultRawThrowsFormatException()
throws Exception {
new BdfList().getRaw(-1, new byte[0]);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForListThrowsFormatException()
throws Exception {
@@ -208,11 +190,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalList(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultListThrowsFormatException()
throws Exception {
new BdfList().getList(-1, new BdfList());
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDictionaryThrowsFormatException()
@@ -226,12 +203,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalDictionary(-1);
}
@Test(expected = FormatException.class)
public void testNegativeIndexForDefaultDictionaryThrowsFormatException()
throws Exception {
new BdfList().getDictionary(-1, new BdfDictionary());
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForBooleanThrowsFormatException()
throws Exception {
@@ -244,12 +215,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalBoolean(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultBooleanThrowsFormatException()
throws Exception {
new BdfList().getBoolean(0, true);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForLongThrowsFormatException()
throws Exception {
@@ -262,30 +227,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalLong(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultLongThrowsFormatException()
throws Exception {
new BdfList().getLong(0, 1L);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForIntThrowsFormatException()
throws Exception {
new BdfList().getInt(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForOptionalIntThrowsFormatException()
throws Exception {
new BdfList().getOptionalInt(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultIntThrowsFormatException()
throws Exception {
new BdfList().getInt(0, 1);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDoubleThrowsFormatException()
throws Exception {
@@ -298,12 +239,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalDouble(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultDoubleThrowsFormatException()
throws Exception {
new BdfList().getDouble(0, 1D);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForStringThrowsFormatException()
throws Exception {
@@ -316,12 +251,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalString(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultStringThrowsFormatException()
throws Exception {
new BdfList().getString(0, "");
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForRawThrowsFormatException()
throws Exception {
@@ -334,12 +263,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalRaw(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultRawThrowsFormatException()
throws Exception {
new BdfList().getRaw(0, new byte[0]);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForListThrowsFormatException()
throws Exception {
@@ -352,11 +275,6 @@ public class BdfListTest extends BrambleTestCase {
new BdfList().getOptionalList(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultListThrowsFormatException()
throws Exception {
new BdfList().getList(0, new BdfList());
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDictionaryThrowsFormatException()
@@ -369,13 +287,6 @@ public class BdfListTest extends BrambleTestCase {
throws Exception {
new BdfList().getOptionalDictionary(0);
}
@Test(expected = FormatException.class)
public void testTooLargeIndexForDefaultDictionaryThrowsFormatException()
throws Exception {
new BdfList().getDictionary(0, new BdfDictionary());
}
@Test(expected = FormatException.class)
public void testWrongTypeForBooleanThrowsFormatException()
throws Exception {
@@ -388,12 +299,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(123).getOptionalBoolean(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultBooleanThrowsFormatException()
throws Exception {
BdfList.of(123).getBoolean(0, true);
}
@Test(expected = FormatException.class)
public void testWrongTypeForLongThrowsFormatException() throws Exception {
BdfList.of(1.23).getLong(0);
@@ -405,29 +310,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(1.23).getOptionalLong(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultLongThrowsFormatException()
throws Exception {
BdfList.of(1.23).getLong(0, 1L);
}
@Test(expected = FormatException.class)
public void testWrongTypeForIntThrowsFormatException() throws Exception {
BdfList.of(1.23).getInt(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForOptionalIntThrowsFormatException()
throws Exception {
BdfList.of(1.23).getOptionalInt(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultIntThrowsFormatException()
throws Exception {
BdfList.of(1.23).getInt(0, 1);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDoubleThrowsFormatException() throws Exception {
BdfList.of(123).getDouble(0);
@@ -439,12 +321,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(123).getOptionalDouble(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultDoubleThrowsFormatException()
throws Exception {
BdfList.of(123).getDouble(0, 1D);
}
@Test(expected = FormatException.class)
public void testWrongTypeForStringThrowsFormatException() throws Exception {
BdfList.of(123).getString(0);
@@ -456,12 +332,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(123).getOptionalString(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultStringThrowsFormatException()
throws Exception {
BdfList.of(123).getString(0, "");
}
@Test(expected = FormatException.class)
public void testWrongTypeForRawThrowsFormatException() throws Exception {
BdfList.of(123).getRaw(0);
@@ -473,12 +343,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(123).getOptionalRaw(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultRawThrowsFormatException()
throws Exception {
BdfList.of(123).getRaw(0, new byte[0]);
}
@Test(expected = FormatException.class)
public void testWrongTypeForListThrowsFormatException() throws Exception {
BdfList.of(123).getList(0);
@@ -490,11 +354,6 @@ public class BdfListTest extends BrambleTestCase {
BdfList.of(123).getOptionalList(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultListThrowsFormatException()
throws Exception {
BdfList.of(123).getList(0, new BdfList());
}
@Test(expected = FormatException.class)
public void testWrongTypeForDictionaryThrowsFormatException()
@@ -507,81 +366,4 @@ public class BdfListTest extends BrambleTestCase {
throws Exception {
BdfList.of(123).getOptionalDictionary(0);
}
@Test(expected = FormatException.class)
public void testWrongTypeForDefaultDictionaryThrowsFormatException()
throws Exception {
BdfList.of(123).getDictionary(0, new BdfDictionary());
}
@Test(expected = FormatException.class)
public void testNullValueForBooleanThrowsFormatException()
throws Exception {
BdfList.of(NULL_VALUE).getBoolean(0);
}
@Test(expected = FormatException.class)
public void testNullValueForLongThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getLong(0);
}
@Test(expected = FormatException.class)
public void testNullValueForIntThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getInt(0);
}
@Test(expected = FormatException.class)
public void testNullValueForDoubleThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getDouble(0);
}
@Test(expected = FormatException.class)
public void testNullValueForStringThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getString(0);
}
@Test(expected = FormatException.class)
public void testNullValueForRawThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getRaw(0);
}
@Test(expected = FormatException.class)
public void testNullValueForListThrowsFormatException() throws Exception {
BdfList.of(NULL_VALUE).getList(0);
}
@Test(expected = FormatException.class)
public void testNullValueForDictionaryThrowsFormatException()
throws Exception {
BdfList.of(NULL_VALUE).getDictionary(0);
}
@Test
public void testOptionalMethodsReturnNullForNullValue() throws Exception {
BdfList list = BdfList.of(NULL_VALUE);
assertNull(list.getOptionalBoolean(0));
assertNull(list.getOptionalLong(0));
assertNull(list.getOptionalInt(0));
assertNull(list.getOptionalDouble(0));
assertNull(list.getOptionalString(0));
assertNull(list.getOptionalRaw(0));
assertNull(list.getOptionalList(0));
assertNull(list.getOptionalDictionary(0));
}
@Test
public void testDefaultMethodsReturnDefaultForNullValue() throws Exception {
BdfList list = BdfList.of(NULL_VALUE);
assertEquals(TRUE, list.getBoolean(0, TRUE));
assertEquals(Long.valueOf(123L), list.getLong(0, 123L));
assertEquals(Integer.valueOf(123), list.getInt(0, 123));
assertEquals(Double.valueOf(123D), list.getDouble(0, 123D));
assertEquals("123", list.getString(0, "123"));
byte[] defaultRaw = {1, 2, 3};
assertArrayEquals(defaultRaw, list.getRaw(0, defaultRaw));
BdfList defaultList = BdfList.of(1, 2, 3);
assertEquals(defaultList, list.getList(0, defaultList));
BdfDictionary defaultDict = BdfDictionary.of(new BdfEntry("123", 123));
assertEquals(defaultDict, list.getDictionary(0, defaultDict));
}
}

View File

@@ -155,13 +155,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfList getMessageAsList(Transaction txn, MessageId m)
throws DbException, FormatException {
return getMessageAsList(txn, m, true);
}
@Override
public BdfList getMessageAsList(Transaction txn, MessageId m,
boolean canonical) throws DbException, FormatException {
return toList(db.getMessage(txn, m), canonical);
return toList(db.getMessage(txn, m).getBody());
}
@Override
@@ -319,13 +313,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfList toList(byte[] b, int off, int len) throws FormatException {
return toList(b, off, len, true);
}
private BdfList toList(byte[] b, int off, int len, boolean canonical)
throws FormatException {
ByteArrayInputStream in = new ByteArrayInputStream(b, off, len);
BdfReader reader = bdfReaderFactory.createReader(in, canonical);
BdfReader reader = bdfReaderFactory.createReader(in);
try {
BdfList list = reader.readList();
if (!reader.eof()) throw new FormatException();
@@ -339,7 +328,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfList toList(byte[] b) throws FormatException {
return toList(b, 0, b.length, true);
return toList(b, 0, b.length);
}
@Override
@@ -347,12 +336,6 @@ class ClientHelperImpl implements ClientHelper {
return toList(m.getBody());
}
@Override
public BdfList toList(Message m, boolean canonical) throws FormatException {
byte[] b = m.getBody();
return toList(b, 0, b.length, canonical);
}
@Override
public BdfList toList(Author a) {
return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey());
@@ -378,7 +361,7 @@ class ClientHelperImpl implements ClientHelper {
public Author parseAndValidateAuthor(BdfList author)
throws FormatException {
checkSize(author, 3);
int formatVersion = author.getInt(0);
int formatVersion = author.getLong(0).intValue();
if (formatVersion != FORMAT_VERSION) throw new FormatException();
String name = author.getString(1);
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
@@ -489,7 +472,8 @@ class ClientHelperImpl implements ClientHelper {
if (element.size() != 2) {
throw new FormatException();
}
list.add(new MailboxVersion(element.getInt(0), element.getInt(1)));
list.add(new MailboxVersion(element.getLong(0).intValue(),
element.getLong(1).intValue()));
}
// Sort the list of versions for easier comparison
sort(list);
@@ -502,7 +486,7 @@ class ClientHelperImpl implements ClientHelper {
try {
BdfDictionary meta =
getGroupMetadataAsDictionary(txn, contactGroupId);
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}

View File

@@ -18,18 +18,12 @@ class BdfReaderFactoryImpl implements BdfReaderFactory {
@Override
public BdfReader createReader(InputStream in) {
return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
DEFAULT_MAX_BUFFER_SIZE, true);
}
@Override
public BdfReader createReader(InputStream in, boolean canonical) {
return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
DEFAULT_MAX_BUFFER_SIZE, canonical);
DEFAULT_MAX_BUFFER_SIZE);
}
@Override
public BdfReader createReader(InputStream in, int nestedLimit,
int maxBufferSize, boolean canonical) {
return new BdfReaderImpl(in, nestedLimit, maxBufferSize, canonical);
int maxBufferSize) {
return new BdfReaderImpl(in, nestedLimit, maxBufferSize);
}
}

View File

@@ -33,24 +33,21 @@ import static org.briarproject.bramble.util.StringUtils.fromUtf8;
@NotThreadSafe
@NotNullByDefault
final class BdfReaderImpl implements BdfReader {
class BdfReaderImpl implements BdfReader {
private static final byte[] EMPTY_BUFFER = new byte[0];
private final InputStream in;
private final int nestedLimit, maxBufferSize;
private final boolean canonical;
private boolean hasLookahead = false, eof = false;
private byte next;
private byte[] buf = new byte[8];
BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize,
boolean canonical) {
BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize) {
this.in = in;
this.nestedLimit = nestedLimit;
this.maxBufferSize = maxBufferSize;
this.canonical = canonical;
}
private void readLookahead() throws IOException {
@@ -191,22 +188,13 @@ final class BdfReaderImpl implements BdfReader {
private short readInt16() throws IOException {
readIntoBuffer(2);
short value = (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
if (canonical && value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
// Value could have been encoded as an INT_8
throw new FormatException();
}
return value;
return (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
}
private int readInt32() throws IOException {
readIntoBuffer(4);
int value = 0;
for (int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8);
if (canonical && value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
// Value could have been encoded as an INT_16
throw new FormatException();
}
return value;
}
@@ -214,11 +202,6 @@ final class BdfReaderImpl implements BdfReader {
readIntoBuffer(8);
long value = 0;
for (int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8);
if (canonical && value >= Integer.MIN_VALUE &&
value <= Integer.MAX_VALUE) {
// Value could have been encoded as an INT_32
throw new FormatException();
}
return value;
}
@@ -232,31 +215,6 @@ final class BdfReaderImpl implements BdfReader {
hasLookahead = false;
}
@Override
public boolean hasInt() throws IOException {
if (!hasLookahead) readLookahead();
if (eof) return false;
return next == INT_8 || next == INT_16 || next == INT_32;
}
@Override
public int readInt() throws IOException {
if (!hasInt()) throw new FormatException();
hasLookahead = false;
if (next == INT_8) return readInt8();
if (next == INT_16) return readInt16();
return readInt32();
}
@Override
public void skipInt() throws IOException {
if (!hasInt()) throw new FormatException();
if (next == INT_8) skip(1);
else if (next == INT_16) skip(2);
else skip(4);
hasLookahead = false;
}
@Override
public boolean hasDouble() throws IOException {
if (!hasLookahead) readLookahead();
@@ -365,19 +323,35 @@ final class BdfReaderImpl implements BdfReader {
private BdfList readList(int level) throws IOException {
if (!hasList()) throw new FormatException();
if (level > nestedLimit) throw new FormatException();
hasLookahead = false;
BdfList list = new BdfList();
while (!hasEnd()) list.add(readObject(level + 1));
readEnd();
readListStart();
while (!hasListEnd()) list.add(readObject(level + 1));
readListEnd();
return list;
}
@Override
public void readListStart() throws IOException {
if (!hasList()) throw new FormatException();
hasLookahead = false;
}
@Override
public boolean hasListEnd() throws IOException {
return hasEnd();
}
private boolean hasEnd() throws IOException {
if (!hasLookahead) readLookahead();
if (eof) return false;
return next == END;
}
@Override
public void readListEnd() throws IOException {
readEnd();
}
private void readEnd() throws IOException {
if (!hasEnd()) throw new FormatException();
hasLookahead = false;
@@ -387,7 +361,7 @@ final class BdfReaderImpl implements BdfReader {
public void skipList() throws IOException {
if (!hasList()) throw new FormatException();
hasLookahead = false;
while (!hasEnd()) skipObject();
while (!hasListEnd()) skipObject();
hasLookahead = false;
}
@@ -406,27 +380,35 @@ final class BdfReaderImpl implements BdfReader {
private BdfDictionary readDictionary(int level) throws IOException {
if (!hasDictionary()) throw new FormatException();
if (level > nestedLimit) throw new FormatException();
hasLookahead = false;
BdfDictionary dictionary = new BdfDictionary();
String prevKey = null;
while (!hasEnd()) {
String key = readString();
if (canonical && prevKey != null && key.compareTo(prevKey) <= 0) {
// Keys not unique and sorted
throw new FormatException();
}
dictionary.put(key, readObject(level + 1));
prevKey = key;
}
readEnd();
readDictionaryStart();
while (!hasDictionaryEnd())
dictionary.put(readString(), readObject(level + 1));
readDictionaryEnd();
return dictionary;
}
@Override
public void readDictionaryStart() throws IOException {
if (!hasDictionary()) throw new FormatException();
hasLookahead = false;
}
@Override
public boolean hasDictionaryEnd() throws IOException {
return hasEnd();
}
@Override
public void readDictionaryEnd() throws IOException {
readEnd();
}
@Override
public void skipDictionary() throws IOException {
if (!hasDictionary()) throw new FormatException();
hasLookahead = false;
while (!hasEnd()) {
while (!hasDictionaryEnd()) {
skipString();
skipObject();
}

View File

@@ -2,13 +2,11 @@ package org.briarproject.bramble.data;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfWriter;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -17,7 +15,6 @@ import java.util.Map.Entry;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static java.util.Collections.sort;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.data.Types.DICTIONARY;
import static org.briarproject.bramble.data.Types.END;
@@ -36,11 +33,10 @@ import static org.briarproject.bramble.data.Types.STRING_16;
import static org.briarproject.bramble.data.Types.STRING_32;
import static org.briarproject.bramble.data.Types.STRING_8;
import static org.briarproject.bramble.data.Types.TRUE;
import static org.briarproject.bramble.util.StringUtils.UTF_8;
@NotThreadSafe
@NotNullByDefault
final class BdfWriterImpl implements BdfWriter {
class BdfWriterImpl implements BdfWriter {
private final OutputStream out;
@@ -117,7 +113,7 @@ final class BdfWriterImpl implements BdfWriter {
@Override
public void writeString(String s) throws IOException {
byte[] b = s.getBytes(UTF_8);
byte[] b = s.getBytes("UTF-8");
if (b.length <= Byte.MAX_VALUE) {
out.write(STRING_8);
out.write((byte) b.length);
@@ -165,33 +161,39 @@ final class BdfWriterImpl implements BdfWriter {
else if (o instanceof String) writeString((String) o);
else if (o instanceof byte[]) writeRaw((byte[]) o);
else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes());
else if (o instanceof List) writeList((List<?>) o);
else if (o instanceof Map) writeDictionary((Map<?, ?>) o);
else if (o instanceof List) writeList((List) o);
else if (o instanceof Map) writeDictionary((Map) o);
else throw new FormatException();
}
@Override
public void writeListStart() throws IOException {
out.write(LIST);
}
@Override
public void writeListEnd() throws IOException {
out.write(END);
}
@Override
public void writeDictionary(Map<?, ?> m) throws IOException {
out.write(DICTIONARY);
if (m instanceof BdfDictionary) {
// Entries are already sorted and keys are known to be strings
for (Entry<String, Object> e : ((BdfDictionary) m).entrySet()) {
writeString(e.getKey());
writeObject(e.getValue());
}
} else {
// Check that keys are strings, write entries in canonical order
List<String> keys = new ArrayList<>(m.size());
for (Object k : m.keySet()) {
if (!(k instanceof String)) throw new FormatException();
keys.add((String) k);
}
sort(keys);
for (String key : keys) {
writeString(key);
writeObject(m.get(key));
}
for (Entry<?, ?> e : m.entrySet()) {
if (!(e.getKey() instanceof String)) throw new FormatException();
writeString((String) e.getKey());
writeObject(e.getValue());
}
out.write(END);
}
@Override
public void writeDictionaryStart() throws IOException {
out.write(DICTIONARY);
}
@Override
public void writeDictionaryEnd() throws IOException {
out.write(END);
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.keyagreement;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.BdfWriter;
import org.briarproject.bramble.api.data.BdfWriterFactory;
import org.briarproject.bramble.api.keyagreement.Payload;
@@ -33,14 +32,13 @@ class PayloadEncoderImpl implements PayloadEncoder {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION;
out.write(formatIdAndVersion);
BdfList payload = new BdfList();
payload.add(p.getCommitment());
for (TransportDescriptor d : p.getTransportDescriptors()) {
payload.add(d.getDescriptor());
}
BdfWriter w = bdfWriterFactory.createWriter(out);
try {
w.writeList(payload);
w.writeListStart(); // Payload start
w.writeRaw(p.getCommitment());
for (TransportDescriptor d : p.getTransportDescriptors())
w.writeList(d.getDescriptor());
w.writeListEnd(); // Payload end
} catch (IOException e) {
// Shouldn't happen with ByteArrayOutputStream
throw new AssertionError(e);

View File

@@ -73,7 +73,7 @@ class PayloadParserImpl implements PayloadParser {
List<TransportDescriptor> recognised = new ArrayList<>();
for (int i = 1; i < payload.size(); i++) {
BdfList descriptor = payload.getList(i);
int transportId = descriptor.getInt(0);
long transportId = descriptor.getLong(0);
if (transportId == TRANSPORT_ID_BLUETOOTH) {
TransportId id = BluetoothConstants.ID;
recognised.add(new TransportDescriptor(id, descriptor));

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
@@ -12,15 +11,12 @@ import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.Base32;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
@@ -30,7 +26,6 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
@Immutable
@NotNullByDefault
@@ -103,22 +98,6 @@ class MailboxManagerImpl implements MailboxManager {
return created;
}
@Override
public String convertBase32Payload(String base32Payload)
throws FormatException {
Pattern regex = Pattern.compile("(briar-mailbox://)?([a-z2-7]{104})");
Matcher matcher = regex.matcher(base32Payload);
if (!matcher.find()) throw new FormatException();
String base32 = matcher.group(2);
byte[] payloadBytes;
try {
payloadBytes = Base32.decode(base32, false);
} catch (IllegalArgumentException e) {
throw new FormatException();
}
return new String(payloadBytes, ISO_8859_1);
}
@Override
public boolean checkConnection() {
List<MailboxVersion> versions = null;

View File

@@ -419,7 +419,7 @@ class LanTcpPlugin extends TcpPlugin {
private InetSocketAddress parseSocketAddress(BdfList descriptor)
throws FormatException {
byte[] address = descriptor.getRaw(1);
int port = descriptor.getInt(2);
int port = descriptor.getLong(2).intValue();
if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException();
try {
InetAddress addr = InetAddress.getByAddress(address);

View File

@@ -55,6 +55,7 @@ import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import java.util.zip.ZipInputStream;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
@@ -100,7 +101,6 @@ import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
import static org.briarproject.bramble.util.StringUtils.UTF_8;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
import static org.briarproject.nullsafety.NullSafety.requireNonNull;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -348,7 +348,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO))
LOG.info("Installing Tor binary for " + architecture);
File torFile = getTorExecutableFile();
extract(getExecutableInputStream("tor"), torFile);
extract(getTorInputStream(), torFile);
if (!torFile.setExecutable(true, true)) throw new IOException();
}
@@ -356,7 +356,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO))
LOG.info("Installing obfs4proxy binary for " + architecture);
File obfs4File = getObfs4ExecutableFile();
extract(getExecutableInputStream("obfs4proxy"), obfs4File);
extract(getObfs4InputStream(), obfs4File);
if (!obfs4File.setExecutable(true, true)) throw new IOException();
}
@@ -364,18 +364,28 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO))
LOG.info("Installing snowflake binary for " + architecture);
File snowflakeFile = getSnowflakeExecutableFile();
extract(getExecutableInputStream("snowflake"), snowflakeFile);
extract(getSnowflakeInputStream(), snowflakeFile);
if (!snowflakeFile.setExecutable(true, true)) throw new IOException();
}
private InputStream getExecutableInputStream(String basename) {
String ext = getExecutableExtension();
return requireNonNull(resourceProvider
.getResourceInputStream(architecture + "/" + basename, ext));
private InputStream getTorInputStream() throws IOException {
return getZipInputStream("tor");
}
protected String getExecutableExtension() {
return "";
private InputStream getObfs4InputStream() throws IOException {
return getZipInputStream("obfs4proxy");
}
private InputStream getSnowflakeInputStream() throws IOException {
return getZipInputStream("snowflake");
}
private InputStream getZipInputStream(String basename) throws IOException {
InputStream in = resourceProvider
.getResourceInputStream(basename + "_" + architecture, ".zip");
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private static void append(StringBuilder strb, String name, Object value) {

View File

@@ -201,7 +201,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
// Retrieve and parse the latest local properties
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
BdfList message = clientHelper.getMessageAsList(txn,
e.getValue().messageId, false);
e.getValue().messageId);
local.put(e.getKey(), parseProperties(message));
}
return local;
@@ -222,7 +222,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
if (latest != null) {
// Retrieve and parse the latest local properties
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId, false);
latest.messageId);
p = parseProperties(message);
}
return p == null ? new TransportProperties() : p;
@@ -252,7 +252,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
local = new TransportProperties();
} else {
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId, false);
latest.messageId);
local = parseProperties(message);
}
storeLocalProperties(txn, c, t, local);
@@ -272,8 +272,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
remote = new TransportProperties();
} else {
// Retrieve and parse the latest remote properties
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId, false);
BdfList message =
clientHelper.getMessageAsList(txn, latest.messageId);
remote = parseProperties(message);
}
// Merge in any discovered properties
@@ -317,7 +317,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
changed = true;
} else {
BdfList message = clientHelper.getMessageAsList(txn,
latest.messageId, false);
latest.messageId);
TransportProperties old = parseProperties(message);
merged = new TransportProperties(old);
for (Entry<String, String> e : p.entrySet()) {

View File

@@ -27,10 +27,7 @@ class TransportPropertyValidator extends BdfMessageValidator {
TransportPropertyValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
// Accept transport properties in non-canonical form
// TODO: Remove this after a reasonable migration period
// (added 2023-02-17)
super(clientHelper, metadataEncoder, clock, false);
super(clientHelper, metadataEncoder, clock);
}
@Override

View File

@@ -30,7 +30,6 @@ import static org.briarproject.bramble.api.sync.RecordTypes.OFFER;
import static org.briarproject.bramble.api.sync.RecordTypes.PRIORITY;
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_SUPPORTED_VERSIONS;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PRIORITY_NONCE_BYTES;
@@ -127,8 +126,6 @@ class SyncRecordReaderImpl implements SyncRecordReader {
byte[] payload = nextRecord.getPayload();
if (payload.length <= MESSAGE_HEADER_LENGTH)
throw new FormatException();
if (payload.length > MAX_MESSAGE_LENGTH)
throw new FormatException();
// Validate timestamp
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
if (timestamp < 0) throw new FormatException();

View File

@@ -32,7 +32,8 @@ class SessionParserImpl implements SessionParser {
@Override
public Session parseSession(BdfDictionary meta) throws FormatException {
State state = State.fromValue(meta.getInt(SESSION_KEY_STATE));
State state =
State.fromValue(meta.getLong(SESSION_KEY_STATE).intValue());
MessageId lastLocalMessageId = null;
byte[] lastLocalMessageIdBytes =
@@ -55,9 +56,9 @@ class SessionParserImpl implements SessionParser {
Long localTimestamp = meta.getOptionalLong(SESSION_KEY_LOCAL_TIMESTAMP);
KeySetId keySetId = null;
Integer keySetIdInt = meta.getOptionalInt(SESSION_KEY_KEY_SET_ID);
if (keySetIdInt != null) {
keySetId = new KeySetId(keySetIdInt);
Long keySetIdLong = meta.getOptionalLong(SESSION_KEY_KEY_SET_ID);
if (keySetIdLong != null) {
keySetId = new KeySetId(keySetIdLong.intValue());
}
return new Session(state, lastLocalMessageId, localKeyPair,

View File

@@ -177,8 +177,8 @@ class TransportKeyAgreementManagerImpl extends BdfIncomingMessageHook
protected DeliveryAction incomingMessage(Transaction txn, Message m,
BdfList body, BdfDictionary meta)
throws DbException, FormatException {
MessageType type =
MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE));
MessageType type = MessageType.fromValue(
meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
TransportId t = new TransportId(meta.getString(MSG_KEY_TRANSPORT_ID));
if (LOG.isLoggable(INFO)) {
LOG.info("Received " + type + " message for " + t);

View File

@@ -42,7 +42,7 @@ class TransportKeyAgreementValidator extends BdfMessageValidator {
@Override
protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws FormatException {
MessageType type = MessageType.fromValue(body.getInt(0));
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
if (type == KEY) return validateKeyMessage(m.getTimestamp(), body);
else if (type == ACTIVATE) return validateActivateMessage(body);
else throw new AssertionError();

View File

@@ -301,8 +301,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
for (int i = 0; i < size; i++) {
BdfList cv = body.getList(i);
ClientId clientId = new ClientId(cv.getString(0));
int majorVersion = cv.getInt(1);
int minorVersion = cv.getInt(2);
int majorVersion = cv.getLong(1).intValue();
int minorVersion = cv.getLong(2).intValue();
parsed.add(new ClientVersion(clientId, majorVersion, minorVersion));
}
return parsed;
@@ -408,8 +408,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
throws FormatException {
// Client ID, major version, minor version, active
ClientId clientId = new ClientId(clientState.getString(0));
int majorVersion = clientState.getInt(1);
int minorVersion = clientState.getInt(2);
int majorVersion = clientState.getLong(1).intValue();
int minorVersion = clientState.getLong(2).intValue();
boolean active = clientState.getBoolean(3);
return new ClientState(clientId, majorVersion, minorVersion, active);
}

View File

@@ -43,9 +43,9 @@ class ClientVersioningValidator extends BdfMessageValidator {
checkSize(clientState, 4);
String clientId = clientState.getString(0);
checkLength(clientId, 1, MAX_CLIENT_ID_LENGTH);
int majorVersion = clientState.getInt(1);
int majorVersion = clientState.getLong(1).intValue();
if (majorVersion < 0) throw new FormatException();
int minorVersion = clientState.getInt(2);
int minorVersion = clientState.getLong(2).intValue();
if (minorVersion < 0) throw new FormatException();
clientState.getBoolean(3);
}

View File

@@ -10,21 +10,22 @@ d Bridge obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K
d Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
d Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
n Bridge obfs4 185.181.11.86:443 A961609729E7FDF520B4E81F1F1B8FA1045285C3 cert=e5faG9Zk4Ni+e7z2YgGfevyKPQlMvkVGi4ublSsHYjaBovKeNXpOhbeFxzbZZoAzxAoGUQ iat-mode=0
n Bridge obfs4 93.95.226.151:41185 460B0CFFC0CF1D965F3DE064E08BA1915E7C916A cert=inluPzp5Jp5OzZar1eQb4dcQ/YlAj/v0kHAUCoCr3rmLt03+pVuVTjoH4mRy4+acXpn+Gw iat-mode=0
n Bridge obfs4 120.29.217.52:5223 40FE3DB9800272F9CDC76422F8ED7883280EE96D cert=/71PS4l8c/XJ4DIItlH9xMqNvPFg2RUTrHvPlQWh48u5et8h/yyyjCcYphUadDsfBWpaGQ iat-mode=0
n Bridge obfs4 185.177.207.138:8443 53716FE26F23C8C6A71A2BC5D9D8DC64747278C7 cert=6jcYVilMEzxdsWghSrQFpYYJlkkir/GPIXw/EnddUK3S8ToVpMG8u1SwMOEdEs735RrMHw iat-mode=0
n Bridge obfs4 104.168.68.90:443 ED55B3C321E44EA7E50EF568C8A63CF75E89A58C cert=fgonxDvltTp8nmcOE9sUG94eOAALxETVVXAwnTZJLPpf7rjPuTp+abKl4VyFkxfcLRr5KQ iat-mode=0
n Bridge obfs4 45.142.181.131:42069 6EBCF6B02DA2B982F4080A7119D737366AFB74FA cert=9HyWH/BCwWzNirZdTQtluCgJk+gFhpOqydIuyQ1iDvpnqsAynKF+zcPE/INZFefm86UlBg iat-mode=0
n Bridge obfs4 85.214.28.204:47111 78A36E46BB082A471848239D3F4390A8F8C6084D cert=96sr3eaUFBDu4wFVAQIfNFElh0UNuutJ/3/Fh2Vu2PHfacQ8bwfY02bwG351U8BZpLnfUQ iat-mode=0
n Bridge obfs4 152.67.77.101:4096 B82DB9CDDF887AB8A859420E07DF298E30AF8A6E cert=21OWn3yFo+hulmQNAOtF5uwwOqWtdT5PrLhk8BG9DpOd0/k5DEkQEYPyDdXbS9nZ0E5BJA iat-mode=0
n Bridge obfs4 185.103.252.72:443 75F15E9339FF572F88F5588D429FEA379744BC53 cert=nOZ/SaRE3L1dChvjfe0Ks/wM/F8iFhwd3g2G5zgtcLB8x+wiZRWCwjRrbbiQyb3Gh2mxRQ iat-mode=0
n Bridge obfs4 76.255.201.112:8888 96CF36C2ECCFB7376AB6BE905BECD2C2AE8AEFCD cert=+q0pjaiM0JMqHL/BKqCRD+pjflaw/S406eUDF7CnFgamvQW3l2HVLJhQ6uX9P8zff0PLGg iat-mode=0
n Bridge obfs4 94.142.246.132:8088 135C158527AA9FE9A2F26EC515EB6999D813D347 cert=wTUz0/5FhAZRkitil5MprGbSF3JzjxjxI1kAmxAdSeDy98NgcLr11f/qUXWDC76Y97RiSg iat-mode=0
n Bridge obfs4 20.102.79.78:22022 B5705F7E616DAB0F477E3E1ADC23E40413F683FE cert=1Cc/hwPtPjzFKGHVOP0j/qmBgnvquRx8+im35/u5TIYjDQ3FlMfA5VvTrQ/hbX8BZZooLQ iat-mode=0
n Bridge obfs4 152.70.180.20:1993 3327C43587E66AD5F874C4234A1D72C938AD7318 cert=s7xLRUO2psaX7TMUP2YhXdxItR4U6K7D+E3gQaS/+yWUppevtazIibq4dN1g5Reu6dD2QQ iat-mode=0
n Bridge obfs4 144.202.12.254:10002 4E220F45CD404C8A3082A36326A5ED19BB8D4404 cert=iLz5YYWO4pUw7U7MRNOSvE0qO+IVeE4kVfFVWPO3coH3FmZtrkvlaTklfXxHZaCcXWBgaA iat-mode=0
n Bridge obfs4 109.14.168.159:5082 BFE1416DEFFE969581F016A4A319A87FFB26BA91 cert=n3X1CDdKBPXPIzfKh83p3ydfMzb0AD9gKC+/gIpHb7+xjjAnYO9x3LT+T/MvOIfAXxYySg iat-mode=0
n Bridge obfs4 45.150.172.16:80 82849E69CBB25EA7F479155F7DCD89D85717FF47 cert=+Krdu1jmVQOxWkMj0mqJHgwbQV49eyD6mZDS+mRExssWNHosa60g4P5Gp81sBJKzN8NrSw iat-mode=0
n Bridge obfs4 185.177.207.132:8443 4FB781F7A9DD39DA53A7996907817FC479874D19 cert=UL2gCAXWW5kEWY4TQ0lNeu6OAmzh40bXYVhMnTWVG8USnyy/zEKGSIPgmwTDMumWr9c1Pg iat-mode=0
n Bridge obfs4 213.108.110.149:7499 519344140473CF91030B08F91521F9A6C144ED6C cert=k9fSL/d491qAkGmi2VeSwVlfuyO02jBeN54qxzzQISxpfm3b+a6kJpo8/Bfy1ACbHZIJUg iat-mode=0
n Bridge obfs4 158.174.114.97:3456 32665CD4CBE19092CA47A53D317B8BFF5810441C cert=ne5Zt0TcMedSGmFwAs/AV6J6E9Hn7mG5mR6vQNpEfyuCZK1VRpQvU1LvvtesSu4CXqZtYQ iat-mode=0
n Bridge obfs4 64.4.175.62:8000 8B72740D150795ACB5101AA5F95D1ACDA4FE6B3E cert=vduuNhJ5U/8hjZmllP6AFfXSlSZsnrimdR8Tm8DY9dxWS4n2j92fNc0qHihUwRqwcOfIcg iat-mode=0
n Bridge obfs4 82.64.115.17:990 B08238781C2CD80DBD95AEABEB6F6C75F2E2CEB6 cert=1udeMlFNs3sJ20zwpPE6nShZqqwDb3F1ET4KzfSfD+fktkue9zNx9H3t+yLCPAsg+6UTUA iat-mode=1
n Bridge obfs4 87.161.120.147:9292 9418EEBE8AEAE32CC381AF51610366E8B24651E0 cert=DFRm74qsD1i2/ypaGochpX6CS1j9JTFAKEYaHXrgrx6M2LG5Cvppdt3Ob7lULfhqgtAUdg iat-mode=0
n Bridge obfs4 157.90.245.231:8599 C23CD468EC04555E2B37BE81A771E681049DEA6A cert=UsmDelrbwg4jc6BMvZJ0TS8klUIa2qkbRu3xwQc3ZXPEgpMqyTYUxcVwyPbIU5KmAHsmAA iat-mode=0
v Bridge 92.243.15.235:9001 477EAD3C04036B48235F1F27FC91420A286A4B7F
v Bridge 213.108.108.145:17674 A39C0FE47963B6E8CFE9815549864DE544935A31
v Bridge 213.196.191.96:9060 05E222E2A8C234234FE0CEB58B08A93B8FC360DB

View File

@@ -56,7 +56,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE));
oneOf(clientHelper).toList(message, true);
oneOf(clientHelper).toList(message.getBody());
will(returnValue(body));
oneOf(metadataEncoder).encode(dictionary);
will(returnValue(meta));
@@ -86,7 +86,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp));
oneOf(clientHelper).toList(shortMessage, true);
oneOf(clientHelper).toList(shortMessage.getBody());
will(returnValue(body));
oneOf(metadataEncoder).encode(dictionary);
will(returnValue(meta));
@@ -114,7 +114,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp));
oneOf(clientHelper).toList(message, true);
oneOf(clientHelper).toList(message.getBody());
will(throwException(new FormatException()));
}});
@@ -126,7 +126,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
context.checking(new Expectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(timestamp));
oneOf(clientHelper).toList(message, true);
oneOf(clientHelper).toList(message.getBody());
will(returnValue(body));
}});

View File

@@ -546,7 +546,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
context.checking(new Expectations() {{
oneOf(bdfReaderFactory)
.createReader(with(any(InputStream.class)), with(true));
.createReader(with(any(InputStream.class)));
will(returnValue(bdfReader));
oneOf(bdfReader).readList();
will(returnValue(list));

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -32,14 +31,11 @@ public class BdfReaderImplFuzzingTest extends BrambleTestCase {
buf[1] = 0x14; // Length 20 bytes
in.reset();
BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
DEFAULT_MAX_BUFFER_SIZE, true);
try {
int length = r.readString().length();
assertTrue(length <= 20);
assertTrue(r.eof());
} catch (FormatException e) {
// Expected when bytes are not valid UTF-8
}
DEFAULT_MAX_BUFFER_SIZE);
int length = r.readString().length();
assertTrue(length >= 0);
assertTrue(length <= 20);
assertTrue(r.eof());
}
}
}

View File

@@ -11,7 +11,6 @@ import java.io.ByteArrayInputStream;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE;
import static org.briarproject.bramble.data.BdfReaderImpl.DEFAULT_NESTED_LIMIT;
import static org.briarproject.bramble.util.StringUtils.UTF_8;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@@ -89,18 +88,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
assertTrue(r.eof());
}
@Test(expected = FormatException.class)
public void testReadLong16CouldHaveBeenLong8Max() throws Exception {
setContents("22" + "007F");
r.readLong();
}
@Test(expected = FormatException.class)
public void testReadLong16CouldHaveBeenLong8Min() throws Exception {
setContents("22" + "FF80");
r.readLong();
}
@Test
public void testSkipLong16() throws Exception {
setContents("22" + "0080");
@@ -119,18 +106,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
assertTrue(r.eof());
}
@Test(expected = FormatException.class)
public void testReadLong32CouldHaveBeenLong16Max() throws Exception {
setContents("24" + "00007FFF");
r.readLong();
}
@Test(expected = FormatException.class)
public void testReadLong32CouldHaveBeenLong16Min() throws Exception {
setContents("24" + "FFFF8000");
r.readLong();
}
@Test
public void testSkipLong32() throws Exception {
setContents("24" + "00008000");
@@ -149,48 +124,13 @@ public class BdfReaderImplTest extends BrambleTestCase {
assertTrue(r.eof());
}
@Test(expected = FormatException.class)
public void testReadLong64CouldHaveBeenLong32Max() throws Exception {
setContents("28" + "000000007FFFFFFF");
r.readLong();
}
@Test(expected = FormatException.class)
public void testReadLong64CouldHaveBeenLong32Min() throws Exception {
setContents("28" + "FFFFFFFF80000000");
r.readLong();
}
@Test
public void testSkipLong64() throws Exception {
public void testSkipLong() throws Exception {
setContents("28" + "0000000080000000");
r.skipLong();
assertTrue(r.eof());
}
@Test
public void testReadInt() throws Exception {
setContents("21" + "7F" + "21" + "80"
+ "22" + "7FFF" + "22" + "8000"
+ "24" + "7FFFFFFF" + "24" + "80000000");
assertEquals(Byte.MAX_VALUE, r.readInt());
assertEquals(Byte.MIN_VALUE, r.readInt());
assertEquals(Short.MAX_VALUE, r.readInt());
assertEquals(Short.MIN_VALUE, r.readInt());
assertEquals(Integer.MAX_VALUE, r.readInt());
assertEquals(Integer.MIN_VALUE, r.readInt());
assertTrue(r.eof());
}
@Test
public void testSkipInt() throws Exception {
setContents("21" + "7F" + "22" + "7FFF" + "24" + "7FFFFFFF");
r.skipInt();
r.skipInt();
r.skipInt();
assertTrue(r.eof());
}
@Test
public void testReadDouble() throws Exception {
// http://babbage.cs.qc.edu/IEEE-754/Decimal.html
@@ -222,7 +162,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString8() throws Exception {
String longest = getRandomString(Byte.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
String longHex = toHexString(longest.getBytes("UTF-8"));
// "foo", the empty string, and 127 random letters
setContents("41" + "03" + "666F6F" + "41" + "00" +
"41" + "7F" + longHex);
@@ -246,7 +186,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testSkipString8() throws Exception {
String longest = getRandomString(Byte.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
String longHex = toHexString(longest.getBytes("UTF-8"));
// "foo", the empty string, and 127 random letters
setContents("41" + "03" + "666F6F" + "41" + "00" +
"41" + "7F" + longHex);
@@ -259,9 +199,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString16() throws Exception {
String shortest = getRandomString(Byte.MAX_VALUE + 1);
String shortHex = toHexString(shortest.getBytes(UTF_8));
String shortHex = toHexString(shortest.getBytes("UTF-8"));
String longest = getRandomString(Short.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
String longHex = toHexString(longest.getBytes("UTF-8"));
// 128 random letters and 2^15 -1 random letters
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
assertEquals(shortest, r.readString());
@@ -273,7 +213,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
public void testReadString16ChecksMaxLength() throws Exception {
int maxBufferSize = Byte.MAX_VALUE + 1;
String valid = getRandomString(Byte.MAX_VALUE + 1);
String validHex = toHexString(valid.getBytes(UTF_8));
String validHex = toHexString(valid.getBytes("UTF-8"));
String invalidhex = validHex + "20";
// 128 random letters, the same plus a space
setContents("42" + "0080" + validHex
@@ -283,20 +223,12 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readString();
}
@Test(expected = FormatException.class)
public void testReadString16CouldHaveBeenString8() throws Exception {
String longest = getRandomString(Byte.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
setContents("42" + "007F" + longHex);
r.readString();
}
@Test
public void testSkipString16() throws Exception {
String shortest = getRandomString(Byte.MAX_VALUE + 1);
String shortHex = toHexString(shortest.getBytes(UTF_8));
String shortHex = toHexString(shortest.getBytes("UTF-8"));
String longest = getRandomString(Short.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
String longHex = toHexString(longest.getBytes("UTF-8"));
// 128 random letters and 2^15 - 1 random letters
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
r.skipString();
@@ -307,7 +239,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadString32() throws Exception {
String shortest = getRandomString(Short.MAX_VALUE + 1);
String shortHex = toHexString(shortest.getBytes(UTF_8));
String shortHex = toHexString(shortest.getBytes("UTF-8"));
// 2^15 random letters
setContents("44" + "00008000" + shortHex);
assertEquals(shortest, r.readString());
@@ -318,7 +250,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
public void testReadString32ChecksMaxLength() throws Exception {
int maxBufferSize = Short.MAX_VALUE + 1;
String valid = getRandomString(maxBufferSize);
String validHex = toHexString(valid.getBytes(UTF_8));
String validHex = toHexString(valid.getBytes("UTF-8"));
String invalidHex = validHex + "20";
// 2^15 random letters, the same plus a space
setContents("44" + "00008000" + validHex +
@@ -328,18 +260,10 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readString();
}
@Test(expected = FormatException.class)
public void testReadString32CouldHaveBeenString16() throws Exception {
String longest = getRandomString(Short.MAX_VALUE);
String longHex = toHexString(longest.getBytes(UTF_8));
setContents("44" + "00007FFF" + longHex);
r.readString();
}
@Test
public void testSkipString32() throws Exception {
String shortest = getRandomString(Short.MAX_VALUE + 1);
String shortHex = toHexString(shortest.getBytes(UTF_8));
String shortHex = toHexString(shortest.getBytes("UTF-8"));
// 2^15 random letters, twice
setContents("44" + "00008000" + shortHex +
"44" + "00008000" + shortHex);
@@ -351,7 +275,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadUtf8String() throws Exception {
String unicode = "\uFDD0\uFDD1\uFDD2\uFDD3";
String hex = toHexString(unicode.getBytes(UTF_8));
String hex = toHexString(unicode.getBytes("UTF-8"));
// STRING_8 tag, "foo", the empty string, and the test string
setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "0C" + hex);
assertEquals("foo", r.readString());
@@ -424,14 +348,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readRaw();
}
@Test(expected = FormatException.class)
public void testReadRaw16CouldHaveBeenRaw8() throws Exception {
byte[] longest = new byte[Byte.MAX_VALUE];
String longHex = toHexString(longest);
setContents("52" + "007F" + longHex);
r.readRaw();
}
@Test
public void testSkipRaw16() throws Exception {
byte[] shortest = new byte[Byte.MAX_VALUE + 1];
@@ -469,14 +385,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readRaw();
}
@Test(expected = FormatException.class)
public void testReadRaw32CouldHaveBeenRaw16() throws Exception {
byte[] longest = new byte[Short.MAX_VALUE];
String longHex = toHexString(longest);
setContents("54" + "00007FFF" + longHex);
r.readRaw();
}
@Test
public void testSkipRaw32() throws Exception {
byte[] shortest = new byte[Short.MAX_VALUE + 1];
@@ -526,6 +434,25 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readList();
}
@Test
public void testReadListManually() throws Exception {
// A list containing 1, "foo", and null
setContents("60" + "21" + "01" +
"41" + "03" + "666F6F" +
"00" + "80");
r.readListStart();
assertFalse(r.hasListEnd());
assertEquals(1, r.readLong());
assertFalse(r.hasListEnd());
assertEquals("foo", r.readString());
assertFalse(r.hasListEnd());
assertTrue(r.hasNull());
r.readNull();
assertTrue(r.hasListEnd());
r.readListEnd();
assertTrue(r.eof());
}
@Test
public void testSkipList() throws Exception {
// A list containing 1, "foo", and 128
@@ -538,9 +465,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testReadDictionary() throws Exception {
// A dictionary containing "bar" -> null and "foo" -> 123
setContents("70" + "41" + "03" + "626172" + "00" +
"41" + "03" + "666F6F" + "21" + "7B" + "80");
// A dictionary containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80");
BdfDictionary dictionary = r.readDictionary();
assertEquals(2, dictionary.size());
assertTrue(dictionary.containsKey("foo"));
@@ -590,6 +517,26 @@ public class BdfReaderImplTest extends BrambleTestCase {
r.readDictionary();
}
@Test
public void testReadDictionaryManually() throws Exception {
// A dictionary containing "foo" -> 123 and "bar" -> null
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
"41" + "03" + "626172" + "00" + "80");
r.readDictionaryStart();
assertFalse(r.hasDictionaryEnd());
assertEquals("foo", r.readString());
assertFalse(r.hasDictionaryEnd());
assertEquals(123, r.readLong());
assertFalse(r.hasDictionaryEnd());
assertEquals("bar", r.readString());
assertFalse(r.hasDictionaryEnd());
assertTrue(r.hasNull());
r.readNull();
assertTrue(r.hasDictionaryEnd());
r.readDictionaryEnd();
assertTrue(r.eof());
}
@Test
public void testSkipDictionary() throws Exception {
// A map containing "foo" -> 123 and "bar" -> null
@@ -610,10 +557,10 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test
public void testNestedListWithinDepthLimit() throws Exception {
// A list containing a list containing a list containing a list...
StringBuilder lists = new StringBuilder();
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("60");
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("80");
setContents(lists.toString());
String lists = "";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "60";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "80";
setContents(lists);
r.readList();
assertTrue(r.eof());
}
@@ -621,25 +568,23 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test(expected = FormatException.class)
public void testNestedListOutsideDepthLimit() throws Exception {
// A list containing a list containing a list containing a list...
StringBuilder lists = new StringBuilder();
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("60");
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("80");
setContents(lists.toString());
String lists = "";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "60";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "80";
setContents(lists);
r.readList();
}
@Test
public void testNestedDictionaryWithinDepthLimit() throws Exception {
// A dictionary containing a dictionary containing a dictionary...
StringBuilder dicts = new StringBuilder();
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) {
dicts.append("70").append("41").append("03").append("666F6F");
}
dicts.append("11");
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) {
dicts.append("80");
}
setContents(dicts.toString());
String dicts = "";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++)
dicts += "70" + "41" + "03" + "666F6F";
dicts += "11";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++)
dicts += "80";
setContents(dicts);
r.readDictionary();
assertTrue(r.eof());
}
@@ -647,15 +592,13 @@ public class BdfReaderImplTest extends BrambleTestCase {
@Test(expected = FormatException.class)
public void testNestedDictionaryOutsideDepthLimit() throws Exception {
// A dictionary containing a dictionary containing a dictionary...
StringBuilder dicts = new StringBuilder();
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) {
dicts.append("70").append("41").append("03").append("666F6F");
}
dicts.append("11");
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) {
dicts.append("80");
}
setContents(dicts.toString());
String dicts = "";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++)
dicts += "70" + "41" + "03" + "666F6F";
dicts += "11";
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++)
dicts += "80";
setContents(dicts);
r.readDictionary();
}
@@ -682,6 +625,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
private void setContents(String hex, int maxBufferSize)
throws FormatException {
ByteArrayInputStream in = new ByteArrayInputStream(fromHexString(hex));
r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize, true);
r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize);
}
}

View File

@@ -1,80 +0,0 @@
package org.briarproject.bramble.data;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfReader;
import org.briarproject.bramble.api.data.BdfWriter;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE;
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_NESTED_LIMIT;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class BdfReaderWriterIntegrationTest extends BrambleTestCase {
@Test
public void testConvertStringToCanonicalForm() throws Exception {
// 'foo' as a STRING_16 (not canonical, should be a STRING_8)
String hexIn = "42" + "0003" + "666F6F";
InputStream in = new ByteArrayInputStream(fromHexString(hexIn));
BdfReader r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
DEFAULT_MAX_BUFFER_SIZE, false); // Accept non-canonical
String s = r.readString();
assertEquals("foo", s);
assertTrue(r.eof());
// Convert the string back to BDF
ByteArrayOutputStream out = new ByteArrayOutputStream();
BdfWriter w = new BdfWriterImpl(out);
w.writeString(s);
w.flush();
String hexOut = toHexString(out.toByteArray());
// The BDF should now be in canonical form
assertEquals("41" + "03" + "666F6F", hexOut);
}
@Test
public void testConvertDictionaryToCanonicalForm() throws Exception {
// A dictionary with keys in non-canonical order: 'foo' then 'bar'
String hexIn = "70" + "41" + "03" + "666F6F" + "21" + "01"
+ "41" + "03" + "626172" + "21" + "02" + "80";
InputStream in = new ByteArrayInputStream(fromHexString(hexIn));
BdfReader r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
DEFAULT_MAX_BUFFER_SIZE, false); // Accept non-canonical
BdfDictionary d = r.readDictionary();
assertEquals(2, d.size());
assertTrue(r.eof());
// The entries should be returned in canonical order
Iterator<Entry<String, Object>> it = d.entrySet().iterator();
Entry<String, Object> first = it.next();
assertEquals("bar", first.getKey());
assertEquals(2L, first.getValue());
Entry<String, Object> second = it.next();
assertEquals("foo", second.getKey());
assertEquals(1L, second.getValue());
// Convert a non-canonical map to BDF (use LinkedHashMap so we know
// the entries will be iterated over in non-canonical order)
Map<String, Object> m = new LinkedHashMap<>();
m.put("foo", 1);
m.put("bar", 2);
ByteArrayOutputStream out = new ByteArrayOutputStream();
BdfWriter w = new BdfWriterImpl(out);
w.writeDictionary(m);
w.flush();
String hexOut = toHexString(out.toByteArray());
// The entries should be in canonical order: 'bar' then 'foo'
assertEquals("70" + "41" + "03" + "626172" + "21" + "02"
+ "41" + "03" + "666F6F" + "21" + "01" + "80", hexOut);
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.data;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
@@ -169,11 +168,9 @@ public class BdfWriterImplTest extends BrambleTestCase {
@Test
public void testWriteDictionary() throws IOException {
// Add entries to dictionary in descending order - they should be
// output in ascending order. Use LinkedHashMap to get predictable
// iteration order
// Use LinkedHashMap to get predictable iteration order
Map<String, Object> m = new LinkedHashMap<>();
for (int i = 3; i >= 0; i--) m.put(String.valueOf(i), i);
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
w.writeDictionary(m);
// DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
@@ -183,17 +180,30 @@ public class BdfWriterImplTest extends BrambleTestCase {
}
@Test
public void testWriteBdfDictionary() throws IOException {
// Add entries to dictionary in descending order - they should be
// output in ascending order
BdfDictionary d = new BdfDictionary();
for (int i = 3; i >= 0; i--) d.put(String.valueOf(i), i);
w.writeDictionary(d);
// DICTIONARY tag, keys as strings and values as integers, END tag
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
"41" + "01" + "31" + "21" + "01" +
"41" + "01" + "32" + "21" + "02" +
"41" + "01" + "33" + "21" + "03" + "80");
public void testWriteDelimitedList() throws IOException {
w.writeListStart();
w.writeLong(1);
w.writeString("foo");
w.writeLong(128);
w.writeListEnd();
// LIST tag, 1 as integer, "foo" as string, 128 as integer, END tag
checkContents("60" + "21" + "01" +
"41" + "03" + "666F6F" +
"22" + "0080" + "80");
}
@Test
public void testWriteDelimitedDictionary() throws IOException {
w.writeDictionaryStart();
w.writeString("foo");
w.writeLong(123);
w.writeString("bar");
w.writeNull();
w.writeDictionaryEnd();
// DICTIONARY tag, "foo" as string, 123 as integer, "bar" as string,
// NULL tag, END tag
checkContents("70" + "41" + "03" + "666F6F" +
"21" + "7B" + "41" + "03" + "626172" + "00" + "80");
}
@Test

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
@@ -10,23 +9,17 @@ import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEven
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.briarproject.bramble.util.Base32;
import org.junit.Test;
import java.io.IOException;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.Executor;
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.hasEvent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class MailboxManagerImplTest extends BrambleMockTestCase {
@@ -132,32 +125,4 @@ public class MailboxManagerImplTest extends BrambleMockTestCase {
assertTrue(manager.checkConnection());
}
@Test
public void testConvertBase32Payload() throws FormatException {
byte[] payload = getRandomBytes(65);
String base32payload = Base32.encode(payload).toLowerCase(Locale.ROOT);
String expected = new String(payload, ISO_8859_1);
try {
manager.convertBase32Payload("foo bar");
fail();
} catch (FormatException e) {
// expected
}
try { // doesn't work with shorter link
manager.convertBase32Payload("briar-mailbox://" +
base32payload.substring(0, base32payload.length() - 1));
fail();
} catch (FormatException e) {
// expected
}
// works with white-spaces
assertEquals(expected, manager.convertBase32Payload(
"foo bar briar-mailbox://" + base32payload + " foo bar"));
// even works without white-space at the end
assertEquals(expected, manager.convertBase32Payload(
"foo bar briar-mailbox://" + base32payload + "foobar"));
// even works without schema and extra chars at end
assertEquals(expected, manager.convertBase32Payload(
"foo bar " + base32payload + "foobar"));
}
}

View File

@@ -217,13 +217,13 @@ public class LanTcpPluginTest extends BrambleTestCase {
// The plugin should have bound a socket and stored the port number
BdfList descriptor = kal.getDescriptor();
assertEquals(3, descriptor.size());
assertEquals(TRANSPORT_ID_LAN, descriptor.getInt(0).intValue());
assertEquals(TRANSPORT_ID_LAN, descriptor.getLong(0).longValue());
byte[] address = descriptor.getRaw(1);
InetAddress addr = InetAddress.getByAddress(address);
assertTrue(addr instanceof Inet4Address);
assertFalse(addr.isLoopbackAddress());
assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress());
int port = descriptor.getInt(2);
int port = descriptor.getLong(2).intValue();
assertTrue(port > 0 && port < 65536);
// The plugin should be listening on the port
InetSocketAddress socketAddr = new InetSocketAddress(addr, port);

View File

@@ -404,7 +404,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false);
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
fooPropertiesDict);
@@ -471,7 +471,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup2.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false);
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
will(returnValue(fooUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
fooPropertiesDict);
@@ -526,7 +526,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
contactGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, updateId, false);
oneOf(clientHelper).getMessageAsList(txn, updateId);
will(returnValue(update));
oneOf(clientHelper).parseAndValidateTransportProperties(
fooPropertiesDict);
@@ -564,7 +564,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, updateId, false);
oneOf(clientHelper).getMessageAsList(txn, updateId);
will(returnValue(update));
oneOf(clientHelper).parseAndValidateTransportProperties(
fooPropertiesDict);
@@ -695,8 +695,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(localGroupMessageMetadata));
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId,
false);
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
will(returnValue(oldUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
oldPropertiesDict);
@@ -761,8 +760,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
localGroup.getId());
will(returnValue(localGroupMessageMetadata));
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId,
false);
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
will(returnValue(oldUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
oldPropertiesDict);
@@ -821,12 +819,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
localGroup.getId());
will(returnValue(messageMetadata));
// Retrieve and parse the latest local properties
oneOf(clientHelper).getMessageAsList(txn, fooVersion999, false);
oneOf(clientHelper).getMessageAsList(txn, fooVersion999);
will(returnValue(fooUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
fooPropertiesDict);
will(returnValue(fooProperties));
oneOf(clientHelper).getMessageAsList(txn, barVersion3, false);
oneOf(clientHelper).getMessageAsList(txn, barVersion3);
will(returnValue(barUpdate));
oneOf(clientHelper).parseAndValidateTransportProperties(
barPropertiesDict);

View File

@@ -6,18 +6,13 @@ 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.sync.Ack;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.Priority;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.SyncRecordReader;
import org.briarproject.bramble.api.sync.Versions;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.PredicateMatcher;
import org.hamcrest.Matcher;
import org.jmock.Expectations;
import org.junit.Test;
@@ -28,15 +23,12 @@ 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;
import static org.briarproject.bramble.api.sync.RecordTypes.OFFER;
import static org.briarproject.bramble.api.sync.RecordTypes.PRIORITY;
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_SUPPORTED_VERSIONS;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.PRIORITY_NONCE_BYTES;
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
@@ -54,38 +46,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
private final SyncRecordReader reader =
new SyncRecordReaderImpl(messageFactory, recordReader);
@Test
public void testNoFormatExceptionIfMessageIsMinimumSize() throws Exception {
expectReadRecord(createMessage(MESSAGE_HEADER_LENGTH + 1));
expectCreateMessage(1);
reader.readMessage();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfMessageIsTooSmall() throws Exception {
expectReadRecord(createMessage(MESSAGE_HEADER_LENGTH));
reader.readMessage();
}
@Test
public void testNoFormatExceptionIfMessageIsMaximumSize() throws Exception {
expectReadRecord(createMessage(MESSAGE_HEADER_LENGTH
+ MAX_MESSAGE_BODY_LENGTH));
expectCreateMessage(MAX_MESSAGE_BODY_LENGTH);
reader.readMessage();
}
@Test(expected = FormatException.class)
public void testFormatExceptionIfMessageIsTooLarge() throws Exception {
expectReadRecord(createMessage(MESSAGE_HEADER_LENGTH
+ MAX_MESSAGE_BODY_LENGTH + 1));
reader.readMessage();
}
@Test
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
expectReadRecord(createAck());
@@ -198,20 +158,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
assertTrue(reader.eof());
}
private void expectCreateMessage(int bodyLength) {
MessageId messageId = new MessageId(getRandomId());
GroupId groupId = new GroupId(getRandomId());
long timestamp = System.currentTimeMillis();
context.checking(new Expectations() {{
Matcher<byte[]> matcher = new PredicateMatcher<>(byte[].class,
b -> b.length == MESSAGE_HEADER_LENGTH + bodyLength);
oneOf(messageFactory).createMessage(with(matcher));
will(returnValue(new Message(messageId, groupId, timestamp,
new byte[bodyLength])));
}});
}
private void expectReadRecord(@Nullable Record record) throws Exception {
context.checking(new Expectations() {{
//noinspection unchecked
@@ -221,10 +167,6 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
}});
}
private Record createMessage(int payloadLength) {
return new Record(PROTOCOL_VERSION, MESSAGE, new byte[payloadLength]);
}
private Record createAck() throws Exception {
return new Record(PROTOCOL_VERSION, ACK, createPayload());
}

View File

@@ -88,58 +88,51 @@ public class StringUtilsTest extends BrambleTestCase {
}
@Test
public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8()
throws Exception {
public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8() {
// The UTF-8 encoding of the null character is valid
byte[] utf8 = new byte[1];
String actual = StringUtils.fromUtf8(utf8);
assertEquals("\u0000", actual);
// When we convert back to UTF-8 we should get the original encoding
assertArrayEquals(utf8, StringUtils.toUtf8(actual));
assertEquals("\u0000", StringUtils.fromUtf8(new byte[1]));
}
@Test(expected = FormatException.class)
public void testFromUtf8RejectsNullCharacterUsingModifiedUtf8()
throws Exception {
@Test
public void testFromUtf8RemovesNullCharacterUsingModifiedUtf8() {
// The modified UTF-8 encoding of the null character is not valid
byte[] b = new byte[] {
(byte) 0xC0, (byte) 0x80, // Null character as modified UTF-8
(byte) 0xC8, (byte) 0x85 // U+0205
};
StringUtils.fromUtf8(b);
// Conversion should ignore the invalid character and return the rest
String expected = "\u0205";
assertEquals(expected, StringUtils.fromUtf8(b));
}
@Test
public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8()
throws Exception {
public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8() {
// The UTF-8 encoding of a supplementary character is valid and should
// be converted to a surrogate pair
byte[] utf8 = new byte[] {
byte[] b = new byte[] {
(byte) 0xF0, (byte) 0x90, (byte) 0x90, (byte) 0x80, // U+10400
(byte) 0xC8, (byte) 0x85 // U+0205
};
String expected = "\uD801\uDC00\u0205"; // Surrogate pair
String actual = StringUtils.fromUtf8(utf8);
assertEquals(expected, actual);
// When we convert back to UTF-8 we should get the original encoding
assertArrayEquals(utf8, StringUtils.toUtf8(actual));
assertEquals(expected, StringUtils.fromUtf8(b));
}
@Test(expected = FormatException.class)
public void testFromUtf8RejectsSupplementaryCharacterUsingModifiedUtf8()
throws Exception {
@Test
public void testFromUtf8RemovesSupplementaryCharacterUsingModifiedUtf8() {
// The CESU-8 or modified UTF-8 encoding of a supplementary character
// is not valid
byte[] utf8 = new byte[] {
byte[] b = new byte[] {
(byte) 0xED, (byte) 0xA0, (byte) 0x81, // U+10400 as CSEU-8
(byte) 0xED, (byte) 0xB0, (byte) 0x80,
(byte) 0xC8, (byte) 0x85 // U+0205
};
StringUtils.fromUtf8(utf8);
// Conversion should ignore the invalid character and return the rest
String expected = "\u0205";
assertEquals(expected, StringUtils.fromUtf8(b));
}
@Test
public void testFromUtf8EmptyInput() throws Exception {
public void testFromUtf8EmptyInput() {
assertEquals("", StringUtils.fromUtf8(new byte[0]));
}

View File

@@ -7,6 +7,10 @@ apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
configurations {
tor
}
dependencies {
implementation project(':bramble-core')
@@ -15,9 +19,12 @@ dependencies {
implementation "net.java.dev.jna:jna:$jna_version"
implementation "net.java.dev.jna:jna-platform:$jna_version"
testImplementation "org.briarproject:tor-linux:$tor_version"
testImplementation "org.briarproject:obfs4proxy-linux:$obfs4proxy_version"
testImplementation "org.briarproject:snowflake-linux:$snowflake_version"
tor "org.briarproject:tor-linux:$tor_version"
tor "org.briarproject:tor-windows:$tor_version"
tor "org.briarproject:obfs4proxy-linux:$obfs4proxy_version"
tor "org.briarproject:obfs4proxy-windows:$obfs4proxy_version"
tor "org.briarproject:snowflake-linux:$snowflake_version"
tor "org.briarproject:snowflake-windows:$snowflake_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
@@ -32,6 +39,31 @@ dependencies {
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
}
def torBinariesDir = 'src/main/resources'
task cleanTorBinaries {
doLast {
delete fileTree(torBinariesDir) { include '*.zip' }
}
}
clean.dependsOn cleanTorBinaries
task unpackTorBinaries {
doLast {
copy {
from configurations.tor.collect { zipTree(it) }
into torBinariesDir
}
}
dependsOn cleanTorBinaries
}
processResources {
inputs.dir torBinariesDir
dependsOn unpackTorBinaries
}
tasks.withType(Test) {
systemProperty 'java.library.path', 'libs'
}

View File

@@ -62,9 +62,9 @@ public class UnixTorPluginFactory extends TorPluginFactory {
if (LOG.isLoggable(INFO)) {
LOG.info("System's os.arch is " + arch);
}
if (arch.equals("amd64")) return "x86_64";
else if (arch.equals("aarch64")) return "aarch64";
else if (arch.equals("arm")) return "armhf";
if (arch.equals("amd64")) return "linux-x86_64";
else if (arch.equals("aarch64")) return "linux-aarch64";
else if (arch.equals("arm")) return "linux-armhf";
return null;
}

View File

@@ -94,8 +94,4 @@ class WindowsTorPlugin extends JavaTorPlugin {
if (!success.take()) throw new PluginException();
}
@Override
protected String getExecutableExtension() {
return ".exe";
}
}

View File

@@ -62,7 +62,7 @@ public class WindowsTorPluginFactory extends TorPluginFactory {
if (LOG.isLoggable(INFO)) {
LOG.info("System's os.arch is " + arch);
}
if (arch.equals("amd64")) return "x86_64";
if (arch.equals("amd64")) return "windows-x86_64";
return null;
}

View File

@@ -1,40 +0,0 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.util.OsUtils;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;
public class TestResources {
@Before
public void isRunningOnLinux() {
assumeTrue(OsUtils.isLinux());
}
@Test
public void canReadTorLinux() {
InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("x86_64/tor");
assertNotNull(input);
}
@Test
public void canReadObfs4ProxyLinux() {
InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("x86_64/obfs4proxy");
assertNotNull(input);
}
@Test
public void canReadSnowflakeLinux() {
InputStream input = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("x86_64/snowflake");
assertNotNull(input);
}
}

View File

@@ -26,9 +26,12 @@ dependencyVerification {
'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:obfs4proxy-linux:0.0.14-tor2:obfs4proxy-linux-0.0.14-tor2.jar:bb2431092b5ad998ad620b0223e725c0f7e43f1b02af2f097a2544edc1fd9738',
'org.briarproject:snowflake-linux:2.5.1:snowflake-linux-2.5.1.jar:edc807dcb7758365970d95525e4749349a27f462d0e2df6505ad1ca65fb296d2',
'org.briarproject:tor-linux:0.4.7.13-2:tor-linux-0.4.7.13-2.jar:1e4ca9e0f724e1f17fcce570832704942cc3be26c4c2eccbe5aae29f35afa307',
'org.briarproject:obfs4proxy-linux:0.0.14-tor1:obfs4proxy-linux-0.0.14-tor1.jar:9783b9c7ec588a5246f534a9c5782783c8c9821825f81c3e0c6f1ecee61cfcbb',
'org.briarproject:obfs4proxy-windows:0.0.14-tor1:obfs4proxy-windows-0.0.14-tor1.jar:9dd122b31b3cd1616f168091dcdb01de049d1e052fe5c089b7627618a8a2694b',
'org.briarproject:snowflake-linux:2.3.1:snowflake-linux-2.3.1.jar:99ecf4546d8f79eb8408168c09380fec596558ac934554bf7d4247ea7ef2c9f3',
'org.briarproject:snowflake-windows:2.3.1:snowflake-windows-2.3.1.jar:d011f1a72c00a221f56380c19aad8ff11db8c2bb1adb0784125572d80b4d275a',
'org.briarproject:tor-linux:0.4.7.13:tor-linux-0.4.7.13.jar:9819ee973cbcdc133f7d04aef9d4b957a35087627a790e532142d15412a9636f',
'org.briarproject:tor-windows:0.4.7.13:tor-windows-0.4.7.13.jar:853d2769665614e26703cbe02e43b218b064c04a0bcd120fdc459cda45bd2606',
'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',

View File

@@ -26,8 +26,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 31
versionCode 10423
versionName "1.4.23"
versionCode 10420
versionName "1.4.20"
applicationId "org.briarproject.briar.android"
buildConfigField "String", "TorVersion", "\"$tor_version\""

View File

@@ -5,25 +5,16 @@ import android.os.Bundle;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.blog.RssImportResult.FileImportError;
import org.briarproject.briar.android.blog.RssImportResult.FileImportSuccess;
import org.briarproject.briar.android.blog.RssImportResult.UrlImportError;
import org.briarproject.briar.android.blog.RssImportResult.UrlImportSuccess;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.fragment.ErrorFragment;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;
import static androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
import static org.briarproject.briar.android.util.UiUtils.showFragment;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class RssFeedActivity extends BriarActivity
@@ -54,29 +45,21 @@ public class RssFeedActivity extends BriarActivity
viewModel.getImportResult().observeEvent(this, this::onImportResult);
}
private void onImportResult(@Nullable RssImportResult result) {
FragmentManager fm = getSupportFragmentManager();
if (result instanceof UrlImportSuccess) {
private void onImportResult(boolean result) {
if (result) {
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(RssFeedImportFragment.TAG) != null) {
onBackPressed();
}
} else if (result instanceof UrlImportError) {
String url = ((UrlImportError) result).url;
} else {
String url = viewModel.getUrlFailedImport();
if (url == null) {
throw new AssertionError();
}
RssFeedImportFailedDialogFragment dialog =
RssFeedImportFailedDialogFragment.newInstance(url);
dialog.show(fm, RssFeedImportFailedDialogFragment.TAG);
} else if (result instanceof FileImportSuccess) {
// pop stack back to before the initial import fragment
fm.popBackStackImmediate(RssFeedImportFragment.TAG,
POP_BACK_STACK_INCLUSIVE);
} else if (result instanceof FileImportError) {
// pop stack back to initial import fragment
fm.popBackStackImmediate(RssFeedImportFragment.TAG, 0);
// show error fragment
Fragment f = ErrorFragment.newInstance(
getString(R.string.blogs_rss_feeds_import_error));
String tag = ErrorFragment.TAG;
showFragment(fm, f, tag);
dialog.show(getSupportFragmentManager(),
RssFeedImportFailedDialogFragment.TAG);
}
}
}

View File

@@ -1,13 +1,9 @@
package org.briarproject.briar.android.blog;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -17,27 +13,18 @@ import android.widget.ProgressBar;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.fragment.ProgressFragment;
import org.briarproject.briar.android.util.ActivityLaunchers.GetContentAdvanced;
import org.briarproject.briar.android.util.ActivityLaunchers.OpenDocumentAdvanced;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import static android.os.Build.VERSION.SDK_INT;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
import static org.briarproject.briar.android.util.UiUtils.hideSoftKeyboard;
import static org.briarproject.briar.android.util.UiUtils.launchActivityToOpenFile;
import static org.briarproject.briar.android.util.UiUtils.showFragment;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -52,15 +39,6 @@ public class RssFeedImportFragment extends BaseFragment {
private Button importButton;
private ProgressBar progressBar;
@RequiresApi(19)
private final ActivityResultLauncher<String[]> docLauncher =
registerForActivityResult(new OpenDocumentAdvanced(),
this::onFileChosen);
private final ActivityResultLauncher<String> contentLauncher =
registerForActivityResult(new GetContentAdvanced(),
this::onFileChosen);
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
@@ -74,7 +52,6 @@ public class RssFeedImportFragment extends BaseFragment {
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.blogs_rss_feeds_import));
if (SDK_INT >= 19) setHasOptionsMenu(true);
View v = inflater.inflate(R.layout.fragment_rss_feed_import,
container, false);
@@ -115,40 +92,11 @@ public class RssFeedImportFragment extends BaseFragment {
return v;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (SDK_INT >= 19) {
inflater.inflate(R.menu.rss_feed_import_actions, menu);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_import_file && SDK_INT >= 19) {
launchActivityToOpenFile(requireContext(), docLauncher,
contentLauncher, "*/*");
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public String getUniqueTag() {
return TAG;
}
private void onFileChosen(@Nullable Uri uri) {
if (uri == null) return;
// show progress fragment
Fragment f = ProgressFragment.newInstance(
getString(R.string.blogs_rss_feeds_import_progress));
String tag = ProgressFragment.TAG;
showFragment(getParentFragmentManager(), f, tag);
// view model will import and change state that activity will react to
viewModel.importFeed(uri);
}
private void enableOrDisableImportButton() {
String url = urlInput.getText().toString();
importButton.setEnabled(viewModel.validateAndNormaliseUrl(url) != null);

View File

@@ -1,8 +1,6 @@
package org.briarproject.briar.android.blog;
import android.app.Application;
import android.content.ContentResolver;
import android.net.Uri;
import android.util.Patterns;
import org.briarproject.bramble.api.db.DatabaseExecutor;
@@ -13,10 +11,6 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.blog.RssImportResult.FileImportError;
import org.briarproject.briar.android.blog.RssImportResult.FileImportSuccess;
import org.briarproject.briar.android.blog.RssImportResult.UrlImportError;
import org.briarproject.briar.android.blog.RssImportResult.UrlImportSuccess;
import org.briarproject.briar.android.viewmodel.DbViewModel;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.LiveResult;
@@ -26,7 +20,6 @@ import org.briarproject.briar.api.feed.FeedManager;
import org.briarproject.nullsafety.NotNullByDefault;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -37,7 +30,6 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
@@ -60,9 +52,11 @@ class RssFeedViewModel extends DbViewModel {
private final MutableLiveData<LiveResult<List<Feed>>> feeds =
new MutableLiveData<>();
@Nullable
private volatile String urlFailedImport = null;
private final MutableLiveData<Boolean> isImporting =
new MutableLiveData<>(false);
private final MutableLiveEvent<RssImportResult> importResult =
private final MutableLiveEvent<Boolean> importResult =
new MutableLiveEvent<>();
@Inject
@@ -126,7 +120,7 @@ class RssFeedViewModel extends DbViewModel {
});
}
LiveEvent<RssImportResult> getImportResult() {
LiveEvent<Boolean> getImportResult() {
return importResult;
}
@@ -136,6 +130,7 @@ class RssFeedViewModel extends DbViewModel {
void importFeed(String url) {
isImporting.setValue(true);
urlFailedImport = null;
ioExecutor.execute(() -> {
try {
Feed feed = feedManager.addFeed(url);
@@ -150,38 +145,19 @@ class RssFeedViewModel extends DbViewModel {
updated = feedList;
}
feeds.postValue(new LiveResult<>(updated));
importResult.postEvent(new UrlImportSuccess());
importResult.postEvent(true);
} catch (DbException | IOException e) {
logException(LOG, WARNING, e);
importResult.postEvent(new UrlImportError(url));
urlFailedImport = url;
importResult.postEvent(false);
} finally {
isImporting.postValue(false);
}
});
}
@UiThread
void importFeed(Uri uri) {
ContentResolver contentResolver = getApplication().getContentResolver();
ioExecutor.execute(() -> {
try (InputStream is = contentResolver.openInputStream(uri)) {
Feed feed = feedManager.addFeed(is);
// Update the feed if it was already present
List<Feed> feedList = getList(feeds);
if (feedList == null) feedList = new ArrayList<>();
List<Feed> updated = updateListItems(feedList,
f -> f.equals(feed), f -> feed);
// Add the feed if it wasn't already present
if (updated == null) {
feedList.add(feed);
updated = feedList;
}
feeds.postValue(new LiveResult<>(updated));
importResult.postEvent(new FileImportSuccess());
} catch (IOException | DbException e) {
logException(LOG, WARNING, e);
importResult.postEvent(new FileImportError());
}
});
@Nullable
String getUrlFailedImport() {
return urlFailedImport;
}
}

View File

@@ -1,24 +0,0 @@
package org.briarproject.briar.android.blog;
import org.briarproject.nullsafety.NotNullByDefault;
@NotNullByDefault
abstract class RssImportResult {
static class UrlImportSuccess extends RssImportResult {
}
static class UrlImportError extends RssImportResult {
final String url;
UrlImportError(String url) {
this.url = url;
}
}
static class FileImportSuccess extends RssImportResult {
}
static class FileImportError extends RssImportResult {
}
}

View File

@@ -1,58 +0,0 @@
package org.briarproject.briar.android.fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.briarproject.briar.R;
import org.briarproject.nullsafety.MethodsNotNullByDefault;
import org.briarproject.nullsafety.ParametersNotNullByDefault;
import androidx.annotation.Nullable;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ProgressFragment extends BaseFragment {
public static final String TAG = ProgressFragment.class.getName();
private static final String PROGRESS_MSG = "progressMessage";
public static ProgressFragment newInstance(String message) {
ProgressFragment f = new ProgressFragment();
Bundle args = new Bundle();
args.putString(PROGRESS_MSG, message);
f.setArguments(args);
return f;
}
private String progressMessage;
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = requireArguments();
progressMessage = args.getString(PROGRESS_MSG);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = inflater
.inflate(R.layout.fragment_progress, container, false);
TextView msg = v.findViewById(R.id.progressMessage);
msg.setText(progressMessage);
return v;
}
}

View File

@@ -145,7 +145,19 @@ public class MailboxStatusFragment extends Fragment {
@DrawableRes int iconRes;
String title;
String message = null;
if (status.getMailboxCompatibility() < 0) {
if (status.hasProblem(System.currentTimeMillis())) {
tintRes = R.color.briar_red_500;
title = getString(R.string.mailbox_status_failure_title);
iconRes = R.drawable.alerts_and_states_error;
showUnlinkWarning = false;
wizardButton.setVisibility(VISIBLE);
} else if (status.getAttemptsSinceSuccess() > 0) {
iconRes = R.drawable.ic_help_outline_white;
title = getString(R.string.mailbox_status_problem_title);
tintRes = R.color.briar_orange_500;
showUnlinkWarning = false;
wizardButton.setVisibility(VISIBLE);
} else if (status.getMailboxCompatibility() < 0) {
tintRes = R.color.briar_red_500;
if (status.getMailboxCompatibility() == API_CLIENT_TOO_OLD) {
title = getString(R.string.mailbox_status_app_too_old_title);
@@ -160,18 +172,6 @@ public class MailboxStatusFragment extends Fragment {
iconRes = R.drawable.alerts_and_states_error;
showUnlinkWarning = true;
wizardButton.setVisibility(GONE);
} else if (status.hasProblem(System.currentTimeMillis())) {
tintRes = R.color.briar_red_500;
title = getString(R.string.mailbox_status_failure_title);
iconRes = R.drawable.alerts_and_states_error;
showUnlinkWarning = false;
wizardButton.setVisibility(VISIBLE);
} else if (status.getAttemptsSinceSuccess() > 0) {
iconRes = R.drawable.ic_help_outline_white;
title = getString(R.string.mailbox_status_problem_title);
tintRes = R.color.briar_orange_500;
showUnlinkWarning = false;
wizardButton.setVisibility(VISIBLE);
} else {
iconRes = R.drawable.ic_check_circle_outline;
title = getString(R.string.mailbox_status_connected_title);

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_xlarge">
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="@dimen/hero_square"
android:layout_height="@dimen/hero_square"
android:indeterminate="true"
app:layout_constraintBottom_toTopOf="@+id/progressMessage"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25"
app:layout_constraintVertical_chainStyle="packed"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/progressMessage"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_xlarge"
android:gravity="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progress"
tools:text="@string/blogs_rss_feeds_import_progress" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_import_file"
android:icon="@drawable/ic_add_white"
android:title="@string/blogs_rss_feeds_import_title"
app:showAsAction="never"/>
</menu>

View File

@@ -104,7 +104,7 @@
<string name="bt_plugin_status_disabled">Briar е настроен да не използва Bluetooth</string>
<!--Notifications-->
<string name="reminder_notification_title">Отписани сте от Briar</string>
<string name="reminder_notification_text">За да влезете, докоснете</string>
<string name="reminder_notification_text">Докоснете за повторно влизане.</string>
<string name="reminder_notification_channel_title">Напомняне за вход в Briar</string>
<string name="reminder_notification_dismiss">Отказ</string>
<string name="ongoing_notification_title">Вписани в Briar</string>
@@ -235,8 +235,6 @@
<string name="qr_code_invalid">Кодът за QR е недействителен</string>
<string name="qr_code_too_old_1">Сканираният код за QR е от по-ранно издание на Briar.\n\nНека вашия контакт инсталира последното издание и да пробва отново.</string>
<string name="qr_code_too_new_1">Сканираният код за QR е от по-ново издание на Briar.\n\nИнсталирайте последното издание и пробвайте отново.</string>
<string name="mailbox_qr_code_for_contact">Сканираният код за QR е от Briar Пощенска кутия.\n\nАко искате да свържете Пощенска кутия използвайте Настройки &gt; Пощенска кутия от менюто.</string>
<string name="qr_code_format_unknown">Сканираният код за QR не предназначен за добавяне на контакт в Briar.\n\nЗа тази цел използвайте кода, на екрана на контакта ви.</string>
<string name="camera_error">Грешка в камерата</string>
<string name="connecting_to_device">Свързване с устройство\u2026</string>
<string name="authenticating_with_device">Удостоверяване с устройство\u2026</string>
@@ -482,6 +480,7 @@
<string name="blogs_rss_feeds_import_button">Внасяне</string>
<string name="blogs_rss_feeds_import_hint">рес на емисия</string>
<string name="blogs_rss_feeds_import_error">Грешка при внасяне на емисията.</string>
<string name="blogs_rss_feeds_import_exists">Емисията вече е внесена.</string>
<string name="blogs_rss_feeds">Емисии на RSS</string>
<string name="blogs_rss_feeds_manage_imported">Внесена:</string>
<string name="blogs_rss_feeds_manage_author">Автор:</string>
@@ -592,9 +591,7 @@
<string name="mailbox_setup_download_link">Споделяне на препратка за изтегляне</string>
<string name="mailbox_setup_button_scan">Сканиране на кода за QR на пощенска кутия</string>
<string name="permission_camera_qr_denied_body">Отказахте достъп до камерата, но достъп е необходим за сканиране на кодове за QR.\n\nОбмислете дали да не дадете разрешение.</string>
<string name="mailbox_setup_connecting">Свързване с Пощенска кутия…</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">Може да отнеме %1s</string>
<string name="mailbox_setup_already_paired_title">Пощенската кутия е вече свързана</string>
<string name="mailbox_setup_already_paired_description">Прекъснете връзката с пощенската кутия от другото устройство и опитайте отново.</string>
<string name="mailbox_setup_io_error_title">Грешка при свързване</string>

View File

@@ -489,6 +489,7 @@ Així que l\'actualitzi li veureu una icona diferent .</string>
<string name="blogs_rss_feeds_import_button">Subscriu-me</string>
<string name="blogs_rss_feeds_import_hint">Escriviu l\'URL del canal de notícies RSS</string>
<string name="blogs_rss_feeds_import_error">Ens sap greu! S\'ha produït un error en subscriure-us al vostre canal de notícies.</string>
<string name="blogs_rss_feeds_import_exists">Aquest canal ja s\'ha importat.</string>
<string name="blogs_rss_feeds">Canals RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>

View File

@@ -60,8 +60,8 @@
<string name="old_android_expiry_date_reached">Briar wird auf Android 4 nicht mehr unterstützt.\nBitte installiere Briar auf einem neueren Gerät.</string>
<string name="old_android_delete_account">Du kannst auf die Schaltfläche unten tippen, um dein Konto von diesem Gerät zu löschen.</string>
<string name="delete_account_button">Konto löschen</string>
<string name="startup_open_database">Datenbank wird entschlüsselt</string>
<string name="startup_migrate_database">Datenbank wird aktualisiert</string>
<string name="startup_open_database">Datenbank wird entschlüsselt...</string>
<string name="startup_migrate_database">Datenbank wird aktualisiert...</string>
<string name="startup_compact_database">Datenbank wird komprimiert…</string>
<!--Navigation Drawer-->
<string name="nav_drawer_open_description">Navigationsleiste öffnen</string>
@@ -266,9 +266,9 @@
<string name="pending_contact_requests_snackbar">Es gibt ausstehende Kontaktanfragen</string>
<string name="pending_contact_requests">Ausstehende Kontaktanfragen</string>
<string name="no_pending_contacts">Keine ausstehenden Kontakte</string>
<string name="waiting_for_contact_to_come_online">Warte auf Online-Aktivität des Kontakts</string>
<string name="waiting_for_contact_to_come_online">Warte auf Online-Aktivität des Kontakts ...</string>
<string name="connecting">Verbinde…</string>
<string name="adding_contact">Kontakt hinzufügen</string>
<string name="adding_contact">Kontakt hinzufügen...</string>
<string name="adding_contact_failed">Hinzufügen von Kontakt ist fehlgeschlagen</string>
<string name="dialog_title_remove_pending_contact">Entfernung bestätigen</string>
<string name="dialog_message_remove_pending_contact">Dieser Kontakt befindet sich noch beim Hinzufügen. Wenn er jetzt entfernt wird, wird das Hinzufügen abgebrochen.</string>
@@ -487,9 +487,8 @@
<string name="blogs_rss_feeds_import">RSS-Feed importieren</string>
<string name="blogs_rss_feeds_import_button">Importieren</string>
<string name="blogs_rss_feeds_import_hint">URL des RSS-Feeds eingeben</string>
<string name="blogs_rss_feeds_import_progress">RSS-Feed wird importiert…</string>
<string name="blogs_rss_feeds_import_error">Es tut uns Leid! Es gab einen Fehler beim Importieren deines Feeds.</string>
<string name="blogs_rss_feeds_import_title">Feed aus Datei importieren</string>
<string name="blogs_rss_feeds_import_exists">Dieser Feed ist bereits importiert.</string>
<string name="blogs_rss_feeds">RSS-Feeds</string>
<string name="blogs_rss_feeds_manage_imported">Importiert:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>
@@ -730,7 +729,7 @@
<string name="dev_report_saved">Der Bericht wurde gespeichert. Er wird verschickt, wenn du dich das nächste Mal bei Briar anmeldest.</string>
<string name="dev_report_error">Fehler: Senden des Reports fehlgeschlagen</string>
<!--Sign Out-->
<string name="progress_title_logout">Von Briar abmelden</string>
<string name="progress_title_logout">Von Briar abmelden...</string>
<!--Screen Filters & Tapjacking-->
<string name="screen_filter_title">Bildschirmüberlagerung erkannt</string>
<string name="screen_filter_body">Eine andere App überlagert Briar. Um deine Sicherheit zu gewährleisten, reagiert Briar in diesem Fall nicht auf deine Eingaben.\n\nDie folgenden Apps könnten überlagern:\n\n%1$s</string>

View File

@@ -443,7 +443,6 @@
<string name="forum_declined_toast">La invitación ha sido rechazada</string>
<string name="shared_by_format">Compartido por %s</string>
<string name="forum_invitation_already_sharing">Ya se está compartiendo</string>
<string name="forum_invitation_already_invited">Invitación ya enviada</string>
<string name="forum_invitation_response_accepted_sent">Aceptaste la invitación al foro de %s.</string>
<string name="forum_invitation_response_declined_sent">Rechazaste la invitación al foro de %s.</string>
<string name="forum_invitation_response_declined_auto">La invitación al foro de %s fue automáticamente rechazada.</string>
@@ -496,6 +495,7 @@
<string name="blogs_rss_feeds_import_button">Importar</string>
<string name="blogs_rss_feeds_import_hint">Introduce la URL del canal RSS</string>
<string name="blogs_rss_feeds_import_error">¡Lo sentimos! Hubo un error importando tu canal.</string>
<string name="blogs_rss_feeds_import_exists">Ese canal ya está importado.</string>
<string name="blogs_rss_feeds">Canales RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>

View File

@@ -510,6 +510,7 @@
<string name="blogs_rss_feeds_import_button">وارد کردن</string>
<string name="blogs_rss_feeds_import_hint">آدرس خوراک RSS را وارد کنید</string>
<string name="blogs_rss_feeds_import_error">متاسفیم! وارد کردن خوراک شما با خطا مواجه شده است.</string>
<string name="blogs_rss_feeds_import_exists">این خوراک وارد شده است.</string>
<string name="blogs_rss_feeds">خوراک های RSS</string>
<string name="blogs_rss_feeds_manage_imported">وارد شده:</string>
<string name="blogs_rss_feeds_manage_author">نویسنده:</string>

View File

@@ -482,6 +482,7 @@
<string name="blogs_rss_feeds_import_button">Importer</string>
<string name="blogs_rss_feeds_import_hint">Saisir lURL du fil RSS</string>
<string name="blogs_rss_feeds_import_error">Nous sommes désolés! Une erreur est survenue lors de limportation de votre fil.</string>
<string name="blogs_rss_feeds_import_exists">Ce fil est déjà importé.</string>
<string name="blogs_rss_feeds">Fils RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importés :</string>
<string name="blogs_rss_feeds_manage_author">Auteur :</string>

View File

@@ -466,6 +466,7 @@
<string name="blogs_rss_feeds_import_button">Flytja inn</string>
<string name="blogs_rss_feeds_import_hint">Settu inn slóðina á RSS-streymið</string>
<string name="blogs_rss_feeds_import_error">Því miður! Það kom upp villa við að flytja inn streymið.</string>
<string name="blogs_rss_feeds_import_exists">Þegar er búið að flytja inn þetta streymi.</string>
<string name="blogs_rss_feeds">RSS-fréttastreymi</string>
<string name="blogs_rss_feeds_manage_imported">Flutt inn:</string>
<string name="blogs_rss_feeds_manage_author">Höfundur:</string>

View File

@@ -501,9 +501,8 @@
<string name="blogs_rss_feeds_import">Importa RSS Feed</string>
<string name="blogs_rss_feeds_import_button">Importa</string>
<string name="blogs_rss_feeds_import_hint">Inserire l\'URL dell\'RSS feed</string>
<string name="blogs_rss_feeds_import_progress">Importazione RSS Feed…</string>
<string name="blogs_rss_feeds_import_error">Ci dispiace! C\'è stato un errore nell\'importazione del tuo feed.</string>
<string name="blogs_rss_feeds_import_title">Importa feed da file</string>
<string name="blogs_rss_feeds_import_exists">Quel flusso è già importato.</string>
<string name="blogs_rss_feeds">Flussi RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importato:</string>
<string name="blogs_rss_feeds_manage_author">Autore:</string>

View File

@@ -1,13 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources xmlns:tools="http://schemas.android.com/tools">
<!--Setup-->
<string name="setup_title">Briarへようこそ</string>
<string name="setup_title">Briar へようこそ</string>
<string name="setup_name_explanation">あなたのニックネームは、常に、あなたが投稿するコンテンツとともに表示されます。プロフィール作成後、編集はできません。</string>
<string name="setup_next">次へ</string>
<string name="setup_password_intro">パスワードを選択</string>
<string name="setup_password_explanation">Briarのアカウント情報はクラウドではなく、暗号化された端末に保存されます。アプリのアンインストールやパスワードを紛失した場合、アカウントへのアクセスとデータを回復する手段はありません。\n\n推測するのが難しい、長いパスワードを設定してください。ランダムな単語やランダムな10文字と数字と記号を組み合わせたものなどです。</string>
<string name="dnkm_doze_intro">メッセージを受信するために、Briarはバックグラウンドで接続を維持する必要があります。</string>
<string name="dnkm_doze_explanation">メッセージを受信するために、Briarはバックグラウンドで接続を維持する必要があります。 Briarが接続を維持できるように、バッテリーの最適化を無効にしてください。</string>
<string name="setup_password_explanation">Briar のアカウント情報はクラウドではなく、暗号化された端末に保存されます。アプリのアンインストールやパスワードを紛失した場合、アカウントへのアクセスとデータを回復する手段はありません。\n\n推測するのが難しい、長いパスワードを設定してください。ランダムな単語やランダムな10文字と数字と記号を組み合わせたものなどです。</string>
<string name="dnkm_doze_intro">メッセージを受信するために、Briar はバックグラウンドで接続を維持する必要があります。</string>
<string name="dnkm_doze_explanation">メッセージを受信するために、Briar はバックグラウンドで接続を維持する必要があります。 Briar が接続を維持できるように、バッテリーの最適化を無効にしてください。</string>
<string name="choose_nickname">ニックネームを入力</string>
<string name="choose_password">パスワードを入力</string>
<string name="confirm_password">確認のため再度パスワードを入力</string>
@@ -17,42 +17,42 @@
<string name="create_account_button">アカウントを作成</string>
<string name="more_info">詳細情報</string>
<string name="don_t_ask_again">次からは尋ねない</string>
<string name="dnkm_huawei_protected_text">下のボタンをタップして、「保護されたアプリ」画面で Briarが保護されていることを確認してください。</string>
<string name="dnkm_huawei_protected_button">Briarを保護する</string>
<string name="dnkm_huawei_protected_help">Briarが保護されたアプリのリストに追加されていないと、Briarはバックグラウンドで実行することができません。</string>
<string name="dnkm_huawei_app_launch_text">下のボタンをタップして「アプリの起動」画面を開き、Briarが「手動で管理する」に設定されていることを確認してください。</string>
<string name="dnkm_huawei_app_launch_help">「アプリ起動」画面で Briarを「手動で管理する」に設定していないと、バックグラウンドで動作させることができません。</string>
<string name="dnkm_xiaomi_text">バックグラウンドで実行するには、Briarを最近のアプリのリストにロックする必要があります。</string>
<string name="dnkm_xiaomi_button">Briarを保護する</string>
<string name="dnkm_xiaomi_help">Briarが最近のアプリのリストにロックされていないと、バックグラウンドで実行することができません。</string>
<string name="dnkm_xiaomi_dialog_body_old">1. 最近使ったアプリのリスト(アプリスイッチャーともいう)を開いて下さい。\n\n2. Briarの画像を下にスワイプすると、南京錠のアイコンが表示されます。\n\n3. ロックされていない場合は、タップしてロックします。</string>
<string name="dnkm_warning_dozed_1">Briarはバックグラウンドで実行できませんでした</string>
<string name="dnkm_huawei_protected_text">下のボタンをタップして、「保護されたアプリ」画面で Briar が保護されていることを確認してください。</string>
<string name="dnkm_huawei_protected_button">Briar を保護する</string>
<string name="dnkm_huawei_protected_help">Briar が保護されたアプリのリストに追加されていないと、Briar はバックグラウンドで実行することができません。</string>
<string name="dnkm_huawei_app_launch_text">下のボタンをタップして「アプリの起動」画面を開き、Briar が「手動で管理する」に設定されていることを確認してください。</string>
<string name="dnkm_huawei_app_launch_help">「アプリ起動」画面で Briar を「手動で管理する」に設定していないと、バックグラウンドで動作させることができません。</string>
<string name="dnkm_xiaomi_text">バックグラウンドで実行するには、Briar を最近のアプリのリストにロックする必要があります。</string>
<string name="dnkm_xiaomi_button">Briar を保護する</string>
<string name="dnkm_xiaomi_help">Briar が最近のアプリのリストにロックされていないと、バックグラウンドで実行することができません。</string>
<string name="dnkm_xiaomi_dialog_body_old">1. 最近使ったアプリのリスト(アプリスイッチャーともいう)を開いて下さい。\n\n2. Briar の画像を下にスワイプすると、南京錠のアイコンが表示されます。\n\n3. ロックされていない場合は、タップしてロックします。</string>
<string name="dnkm_warning_dozed_1">Briarはバックグラウンドで実行することができませんでした</string>
<!--Login-->
<string name="enter_password">パスワード</string>
<string name="try_again">パスワードが間違っています。もう一度入力してください。</string>
<string name="dialog_title_cannot_check_password">パスワードを確認できません</string>
<string name="dialog_message_cannot_check_password">Briarがパスワードを確認することができませんでした。この問題を解決するには、端末の再起動を試してください。</string>
<string name="dialog_message_cannot_check_password">Briar がパスワードを確認することができませんでした。この問題を解決するには、端末の再起動を試してください。</string>
<string name="sign_in_button">サインイン</string>
<string name="forgotten_password">パスワードを忘れました</string>
<string name="dialog_title_lost_password">パスワードを紛失</string>
<string name="dialog_message_lost_password">Briarアカウントはクラウド上ではなく、暗号化さた上であなたの端末に保存さています。したがって、Briarはパスワードをリセットできません。アカウントを削除して、はじめからやり直しますか\n\n注意あなたのID、連絡先、メッセージは永久に失われます。</string>
<string name="startup_failed_activity_title">Briarの起動に失敗</string>
<string name="startup_failed_clock_error">お使いの端末の時計が正しくないため、Briarは起動できませんでした。\n\n端末の時計を正しい時刻に設定してから、もう一度試してください。</string>
<string name="startup_failed_db_error">Briarは、あなたのアカウント、連絡先、メッセージを含むデータベースを開くことができませんでした。\n\nアプリを最新版にアップグレードしてもう一度お試しいただくか、パスワード入力画面で「パスワードを忘れました」を選択して新しいアカウントを設定してください。</string>
<string name="dialog_message_lost_password">Briar アカウントはクラウド上ではなく、暗号化さた上であなたの端末に保存さています。したがって、Briar はパスワードをリセットできません。アカウントを削除して、はじめからやり直しますか?\n\n注意あなたのID、連絡先、メッセージは永久に失われます。</string>
<string name="startup_failed_activity_title">Briar の起動に失敗しました</string>
<string name="startup_failed_clock_error">お使いの端末の時計が正しくないため、Briar は起動できませんでした。\n\n端末の時計を正しい時刻に設定してから、もう一度試してください。</string>
<string name="startup_failed_db_error">Briar は、あなたのアカウント、連絡先、メッセージを含むデータベースを開くことができませんでした。\n\nアプリを最新版にアップグレードしてもう一度お試しいただくか、パスワード入力画面で「パスワードを忘れました」を選択して新しいアカウントを設定してください。</string>
<string name="startup_failed_data_too_old_error">あなたのアカウントは古いバージョンのアプリで作成されたもので、このバージョンでは開くことができません。\n\n古いバージョンを再インストールするか、パスワード入力画面で\'パスワードを忘れました\'を選択して新しいアカウントを設定する必要があります。</string>
<string name="startup_failed_data_too_new_error">あなたのアカウントは、このアプリの新しいバージョンで作成されたもので、このバージョンでは開くことができません。\n\n最新版にアップグレードしてから、もう一度試してください。</string>
<string name="startup_failed_service_error">Briarは要求されたコンポーネントを起動できませんでした。\n\nアプリの最新版にアップグレードしてから、もう一度試してください。</string>
<string name="startup_failed_service_error">Briar は、必要なコンポーネントを起動できませんでした。\n\nアプリの最新版にアップグレードしてから、もう一度試してください。</string>
<plurals name="expiry_warning">
<item quantity="other">これは、Briarのテストバージョンです。 アカウントはあと%d日で期限切れになり、更新できません。</item>
<item quantity="other">これは、Briar のテストバージョンです。 アカウントはあと%d日で期限切れになり、更新できません。</item>
</plurals>
<plurals name="old_android_expiry_warning">
<item quantity="other">Android 4はサポートされなくなりました。Briarは(%d日後に)%s上での動作を停止します。新しい端末に Briarをインストールして、新しいアカウントを作成してください。</item>
<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="download_briar">Briarの使用を続けるには、最新リリースをダウンロードしてください。</string>
<string name="create_new_account">新しいアカウントを作成する必要があります。同じニックネームも使用できます。</string>
<string name="download_briar_button">最新リリースをダウンロード</string>
<string name="old_android_expiry_date_reached">BriarAndroid 4では動作しなくなりました。\n新しい端末にBriarをインストールしてください。</string>
<string name="old_android_expiry_date_reached">BriarAndroid 4 では動作しなくなりました。\n新しい端末にBriarをインストールしてください。</string>
<string name="old_android_delete_account">下のボタンをタップして、この端末からあなたのアカウントを削除できます。</string>
<string name="delete_account_button">アカウントを削除</string>
<string name="startup_open_database">データベースの復号化中…</string>
@@ -69,36 +69,36 @@
<string name="lock_button">アプリをロック</string>
<string name="settings_button">設定</string>
<string name="sign_out_button">サインアウト</string>
<string name="transports_onboarding_text">ここにタップすると、Briarがあなたの連絡先に接続する方法を制御できます。</string>
<string name="transports_onboarding_text">ここにタップすると、Briar があなたの連絡先に接続する方法を制御できます。</string>
<!--Transports: Tor-->
<string name="transport_tor">インターネット</string>
<string name="tor_device_status_online_wifi">電話機はWi-Fiでインターネットにアクセスできます</string>
<string name="tor_device_status_online_mobile">電話機はモバイル データでインターネットにアクセスできます</string>
<string name="tor_device_status_offline">電話機がインターネットに接続できません</string>
<string name="tor_plugin_status_enabling">Briarはインターネットに接続中です…</string>
<string name="tor_plugin_status_active">Briarはインターネットに接続されました</string>
<string name="tor_plugin_status_inactive">Briarはインターネットに接続できません</string>
<string name="tor_plugin_status_disabled">Briarはインターネットを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_mobile_data">Briarはモバイルデータを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_battery">Briarはバッテリー駆動時にインターネットを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_country_blocked">Briarはこの国でインターネットを使わないように設定されています</string>
<string name="tor_plugin_status_enabling">Briar はインターネットに接続中です…</string>
<string name="tor_plugin_status_active">Briar はインターネットに接続されました</string>
<string name="tor_plugin_status_inactive">Briar はインターネットに接続できません</string>
<string name="tor_plugin_status_disabled">Briar はインターネットを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_mobile_data">Briar はモバイルデータを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_battery">Briar はバッテリー駆動時にインターネットを使用しないように設定されています</string>
<string name="tor_plugin_status_disabled_country_blocked">Briar はこの国でインターネットを使わないように設定されています</string>
<!--Transports: Wi-Fi-->
<string name="transport_lan">Wi-Fi</string>
<string name="transport_lan_long">同じ Wi-Fi ネットワーク</string>
<string name="lan_device_status_on">電話機は Wi-Fi に接続されました</string>
<string name="lan_device_status_off">電話機はWi-Fiに接続されていません</string>
<string name="lan_plugin_status_enabling">BriarWi-Fiネットワークに接続中です…</string>
<string name="lan_plugin_status_active">BriarWi-Fiネットワークに接続されました</string>
<string name="lan_plugin_status_inactive">BriarWi-Fiネットワークに接続できません</string>
<string name="lan_plugin_status_disabled">BriarWi-Fiネットワークを使用しないように設定されています</string>
<string name="lan_plugin_status_enabling">BriarWi-Fi ネットワークに接続中です…</string>
<string name="lan_plugin_status_active">BriarWi-Fi ネットワークに接続されました</string>
<string name="lan_plugin_status_inactive">BriarWi-Fi ネットワークに接続できません</string>
<string name="lan_plugin_status_disabled">BriarWi-Fi ネットワークを使用しないように設定されています</string>
<!--Transports: Bluetooth-->
<string name="transport_bt">Bluetooth</string>
<string name="bt_device_status_on">携帯電話の Bluetooth はオンになっています</string>
<string name="bt_device_status_off">携帯電話の Bluetooth はオフにされました</string>
<string name="bt_plugin_status_enabling">BriarBluetoothに接続中です…</string>
<string name="bt_plugin_status_active">BriarBluetoothに接続しました</string>
<string name="bt_plugin_status_inactive">BriarBluetoothに接続できません</string>
<string name="bt_plugin_status_disabled">BriarBluetoothを使用しないように設定されています</string>
<string name="bt_plugin_status_enabling">BriarBluetooth に接続中です…</string>
<string name="bt_plugin_status_active">BriarBluetooth に接続しました</string>
<string name="bt_plugin_status_inactive">BriarBluetooth に接続できません</string>
<string name="bt_plugin_status_disabled">BriarBluetooth を使用しないように設定されています</string>
<!--Notifications-->
<string name="reminder_notification_title">Briarからサインアウト</string>
<string name="reminder_notification_text">タップして再ログインします。</string>
@@ -323,7 +323,6 @@
<string name="connect_via_bluetooth_intro">Bluetooth接続が自動的に行われない場合は、この画面を使って手動で接続することができます。\n\nこの機能を利用するには、あなたの連絡先が近くにある必要があります。\n\nあなたと連絡先が同時に\"開始\"を押してください。</string>
<string name="connect_via_bluetooth_already_discovering">既にBluetooth経由での接続を試行中です。すぐに再試行してください。</string>
<string name="connect_via_bluetooth_no_location_permission">位置情報の権限なくして続行不可能</string>
<string name="connect_via_bluetooth_no_bluetooth_permission">付近の端末の権限なくして続行不可能</string>
<string name="connect_via_bluetooth_start">Bluetooth経由で接続中…</string>
<string name="connect_via_bluetooth_success">Bluetooth経由で接続に成功</string>
<string name="connect_via_bluetooth_error">Bluetooth経由で接続不可能。</string>
@@ -349,9 +348,9 @@
<string name="groups_member_created">%sがグループを作成しました</string>
<string name="groups_member_joined_you">グループに参加しました</string>
<string name="groups_member_joined">%sがグループに参加しました</string>
<string name="groups_leave">グループを脱退</string>
<string name="groups_leave">グループをやめる</string>
<string name="groups_leave_dialog_title">グループをやめる確認</string>
<string name="groups_leave_dialog_message">このグループを脱退してもよろしいですか?</string>
<string name="groups_leave_dialog_message">このグループをやめてもよろしいですか?</string>
<string name="groups_dissolve">グループを削除</string>
<string name="groups_dissolve_dialog_title">グループの削除の確認</string>
<string name="groups_dissolve_dialog_message">このグループを削除してもよろしいですか?\n\nグループを削除すると、他のすべてのメンバーは会話を続けることができなくなり、最新のメッセージは受信できなくなります。</string>
@@ -395,10 +394,10 @@
<string name="forum_new_message_hint">新しい投稿</string>
<string name="forum_message_reply_hint">新しい返信</string>
<string name="btn_reply">返信</string>
<string name="forum_leave">フォーラムを脱退</string>
<string name="forum_leave">フォーラムをやめる</string>
<string name="dialog_title_leave_forum">フォーラムをやめる確認</string>
<string name="dialog_message_leave_forum">このフォーラムを脱退してもよろしいですか?\n\nこのフォーラムで共有した連絡先は更新の受信を停止します。</string>
<string name="dialog_button_leave">脱退</string>
<string name="dialog_message_leave_forum">このフォーラムをやめてもよろしいですか?\n\nこのフォーラムで共有した連絡先は更新の受信を停止します。</string>
<string name="dialog_button_leave">脱退する</string>
<string name="forum_left_toast">フォーラムをやめました</string>
<!--Forum Sharing-->
<string name="forum_share_button">フォーラムを共有</string>
@@ -417,10 +416,6 @@
<string name="forum_declined_toast">招待を辞退しました</string>
<string name="shared_by_format">%sによって共有されました。</string>
<string name="forum_invitation_already_sharing">既に共有しています</string>
<string name="forum_invitation_already_invited">招待は既に送信しました</string>
<string name="forum_invitation_invite_received">招待は既に受信されました</string>
<string name="forum_invitation_not_supported">この連絡先によってサポートされていません</string>
<string name="forum_invitation_error">エラー。これはバグか、そうでなければ、あなたの誤りです</string>
<string name="forum_invitation_response_accepted_sent">%sからのフォーラムへの招待を受け入れました。</string>
<string name="forum_invitation_response_declined_sent">%sからのフォーラムへの招待を辞退しました。</string>
<string name="forum_invitation_response_declined_auto">%sからのフォーラムへの招待は自動的に辞退されました。</string>
@@ -470,9 +465,8 @@
<string name="blogs_rss_feeds_import">RSSフィードをインポート</string>
<string name="blogs_rss_feeds_import_button">インポート</string>
<string name="blogs_rss_feeds_import_hint">RSSフィードのURLを入力してください</string>
<string name="blogs_rss_feeds_import_progress">RSSフィードをインポート中…</string>
<string name="blogs_rss_feeds_import_error">申し訳ありません! フィードのインポート中にエラーが発生しました。</string>
<string name="blogs_rss_feeds_import_title">ファイルからフィードインポート</string>
<string name="blogs_rss_feeds_import_exists">そのフィードは既にインポートされています。</string>
<string name="blogs_rss_feeds">RSSフィード</string>
<string name="blogs_rss_feeds_manage_imported">インポート済み:</string>
<string name="blogs_rss_feeds_manage_author">著者:</string>
@@ -579,7 +573,7 @@
<string name="mailbox_setup_title">メールボックスのセットアップ</string>
<string name="mailbox_setup_intro">メールボックスはあなたがオフラインの間、連絡先があなたにメッセージを送信することを有効にします。メールボックスはあなたがオンラインになるまで、メッセージを受信し保管します。\n
\n予備端末上にBriarのメールボックスアプリをインストールできます。それを電源とWi-Fiに接続し、常時オンラインにしてください。</string>
<string name="mailbox_setup_download">最初に、Google PlayまたはBriarをダウンロードしたどこかで\"BriarMailbox\"を検索して、他の端末上にメールボックスアプリをインストールします。\n
<string name="mailbox_setup_download">最初に、Google PlayまたはBriarをダウンロードしたどこかで\"Briar Mailbox\"を検索して、他の端末上にメールボックスアプリをインストールします。\n
\nそして、メールボックスアプリによって表示されるQRコードを読み取って、Briarとあなたのメールボックス結びつけます。</string>
<string name="mailbox_setup_download_link">ダウンロードリンクを共有</string>
<string name="mailbox_setup_button_scan">メールボックスのQRコードを読み取る</string>
@@ -591,15 +585,15 @@
<string name="mailbox_qr_code_too_new">読み取ったQRコードは、新しいバージョンのBriarメールボックスから生じました。\n\nBriarを最新版にアップグレードしてから、もう一度お試しください。</string>
<string name="contact_qr_code_for_mailbox">読み取ったQRコードは、Briarの連絡先を追加するためのものです。\n\n連絡先を追加したいならば、連絡先一覧に行き、+アイコンをタップしてください。</string>
<string name="mailbox_setup_qr_code_wrong_description">読み取ったQRコードは、Briarメールボックスから生じたものではありません。メールボックス端末上のBriarメールボックスアプリを開き、提示されたQRコードを読み取ってください。</string>
<string name="mailbox_setup_already_paired_title">メールボックスは既にリンクされています</string>
<string name="mailbox_setup_already_paired_description">あなたの端末上のメールボックスのリンクを解き、再試行してください。</string>
<string name="mailbox_setup_already_paired_title">メールボックスは既に結びつけられています</string>
<string name="mailbox_setup_already_paired_description">あなたの端末上のメールボックスの結びつけを解き、再試行してください。</string>
<string name="mailbox_setup_io_error_title">接続できません</string>
<string name="mailbox_setup_io_error_description">双方の端末がインターネットに接続されていることを確かにして、再試行してください。</string>
<string name="mailbox_setup_assertion_error_title">メールボックスのエラー</string>
<string name="mailbox_setup_assertion_error_description">もし問題が続くのであれば、Briarアプリ経由で匿名データ付きのフィードバックを送信してください。</string>
<string name="mailbox_setup_camera_error_description">カメラにアクセスできません。端末を再起動してから、もう一度試してみてください。</string>
<string name="mailbox_setup_paired_title">接続済み</string>
<string name="mailbox_setup_paired_description">あなたのメールボックスはBriarとのリンクに成功しています。\n
<string name="mailbox_setup_paired_description">あなたのメールボックスはBriarとの結びつけられるのに成功しています。\n
メールボックスを電源とW-Fiに接続して、常時オンラインにしてください。</string>
<string name="tor_offline_title">オフライン</string>
<string name="tor_offline_description">この端末がオンラインかつインターネットへの接続が許可されていること確かにしてください。\n
@@ -639,7 +633,7 @@
<string name="mailbox_error_wizard_answer1_1">メールボックスの設定方法が表示される</string>
<string name="mailbox_error_wizard_answer1_2">QRコードが表示される</string>
<string name="mailbox_error_wizard_answer1_3">「メールボックスは実行中」と表示される</string>
<string name="mailbox_error_wizard_answer1_4">端末がオフライン」と表示されます</string>
<string name="mailbox_error_wizard_answer1_4">デバイスがオフライン」と表示されます</string>
<string name="mailbox_error_wizard_info1_1_1">以下のボタンでメールボックスのリンクを解除し、メールボックスの端末の指示に従って再度リンクしてください。</string>
<string name="mailbox_error_wizard_info_1_1_2">以下のボタンでメールボックスのリンクを解除し、QRコードを読み取って再度リンクしてください。</string>
<string name="mailbox_error_wizard_info1_1_3">以下のボタンを使用して、Briarとメールボックスの間での接続を確認してください。\n\n
@@ -651,7 +645,7 @@
<string name="mailbox_error_wizard_info3">以下のボタンを使用してメールボックスをリンク解除してください。\n\n古いメールボックスをリンク解除した後、いつでも新しいメールボックスをセットアップできます。</string>
<!--About-->
<string name="about_title">Tor Project について</string>
<string name="briar_version">Briarバージョン: %s</string>
<string name="briar_version">Briar バージョン: %s</string>
<string name="tor_version">Tor バージョン: %s</string>
<string name="links">リンク</string>
<string name="briar_website">\u2022 <a href="">ウェブサイト</a></string>
@@ -783,7 +777,7 @@
<string name="hotspot_manual_site_address">アドレスURL</string>
<string name="hotspot_qr_site">あなたの電話機はWi-Fiホットスポットを提供しています。ホットスポットに接続された人は、このQRコードを読み取って、Briarをダウンロードできます。</string>
<!--e.g. Download Briar 1.2.20-->
<string name="website_download_title_1">Briar%sをダウンロード</string>
<string name="website_download_title_1">Briar %sをダウンロード</string>
<string name="website_download_intro_1">近くの誰かが、あなたとBriarを共有しました。</string>
<string name="website_download_button">Briarをダウンロード</string>
<string name="website_download_outro">ダウンロードが完了した後に、ダウンロードしたファイルを開いて、インストールしてください。</string>

View File

@@ -477,6 +477,7 @@
<string name="blogs_rss_feeds_import_button">იმპორტი</string>
<string name="blogs_rss_feeds_import_hint">შეიყვანეთ RSS არხის URL</string>
<string name="blogs_rss_feeds_import_error">ვწუხვართ! არხის იმპორტირებისას შეცდომა წარმოიშვა.</string>
<string name="blogs_rss_feeds_import_exists">არხი უკვე იმპორტირებულია.</string>
<string name="blogs_rss_feeds">RSS არხები</string>
<string name="blogs_rss_feeds_manage_imported">იმპორტირებული:</string>
<string name="blogs_rss_feeds_manage_author">ავტორი:</string>

View File

@@ -313,8 +313,6 @@
<string name="duplicate_link_dialog_text_3">%1$s ir %2$s išsiuntė jums tą pačią nuorodą.\n\nGali būti, kad vienas iš šių asmenų bando sužinoti kas yra jūsų adresatų sąraše.\n\nNesakykite šiems asmenims, kad gavote tokią pačią nuorodą iš kito asmens.</string>
<string name="pending_contact_updated_toast">Laukiantis adresatas atnaujintas</string>
<!--Peer trust levels-->
<string name="peer_trust_level_ourselves"></string>
<string name="peer_trust_level_stranger">Nepažįstamasis</string>
<!--Introductions-->
<string name="introduction_onboarding_title">Supažindinkite savo adresatus</string>
<string name="introduction_menu_item">Supažindinti</string>
@@ -444,9 +442,6 @@
<string name="forum_declined_toast">Pakvietimas atmestas</string>
<string name="shared_by_format">Bendrina %s</string>
<string name="forum_invitation_already_sharing">Jau bendrinama</string>
<string name="forum_invitation_already_invited">Pakvietimas jau išsiųstas</string>
<string name="forum_invitation_invite_received">Pakvietimas jau gautas</string>
<string name="forum_invitation_error">Klaida. Tai yra triktis ir ne jūsų kaltė</string>
<string name="forum_invitation_response_accepted_sent">Jūs priėmėte pakvietimą į forumą iš %s.</string>
<string name="forum_invitation_response_declined_sent">Jūs atmetėte pakvietimą į forumą iš %s.</string>
<string name="forum_invitation_response_declined_auto">Pakvietimas į forumą nuo %s buvo automatiškai atmestas.</string>
@@ -499,9 +494,8 @@
<string name="blogs_rss_feeds_import">Importuoti RSS kanalą</string>
<string name="blogs_rss_feeds_import_button">Importuoti</string>
<string name="blogs_rss_feeds_import_hint">Įveskite RSS kanalo URL</string>
<string name="blogs_rss_feeds_import_progress">Importuojamas RSS kanalas…</string>
<string name="blogs_rss_feeds_import_error">Atleiskite! Importuojant jūsų kanalą, įvyko klaida.</string>
<string name="blogs_rss_feeds_import_title">Importuoti kanalą iš failo</string>
<string name="blogs_rss_feeds_import_exists">Tas kanalas jau yra importuotas.</string>
<string name="blogs_rss_feeds">RSS kanalai</string>
<string name="blogs_rss_feeds_manage_imported">Importuota:</string>
<string name="blogs_rss_feeds_manage_author">Autorius:</string>
@@ -611,7 +605,6 @@
<string name="mailbox_setup_download_link">Bendrinti atsisiuntimo nuorodą</string>
<string name="mailbox_setup_button_scan">Skenuoti pašto dėžutės QR kodą</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">Tai gali užtrukti iki %1s</string>
<string name="mailbox_setup_already_paired_title">Pašto dėžutė jau susieta</string>
<string name="mailbox_setup_io_error_title">Nepavyko prisijungti</string>
<string name="mailbox_setup_io_error_description">Įsitikinkite, kad abu įrenginiai yra prisijungę prie interneto ir bandykite dar kartą.</string>
@@ -648,7 +641,6 @@
<string name="briar_changelog">\u2022 <a href="">Keitinių žurnalas</a></string>
<string name="briar_privacy_policy">\u2022 <a href="">Privatumo politika</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">Dėkojame talkininkams iš Localization Lab, ypač Moo už vertimą į lietuvių kalbą</string>
<!--Conversation Settings-->
<string name="disappearing_messages_title">Išnykstančios žinutės</string>
<string name="disappearing_messages_explanation_long">Įjungus šį nustatymą, naujos žinutės

View File

@@ -460,6 +460,7 @@
<string name="blogs_rss_feeds_import_button">တင်သွင်းမည်</string>
<string name="blogs_rss_feeds_import_hint">RSS သတင်းပို့စ်အလွှာ၏ URL ရိုက်ထည့်ပေးပါ</string>
<string name="blogs_rss_feeds_import_error">ဝမ်းနည်းပါသည်! သင့် သတင်းပို့စ်အလွှာအား တင်သွင်းရာတွင် ပျက်ကွက်မှု ဖြစ်ခဲ့ပါသည်။</string>
<string name="blogs_rss_feeds_import_exists">Feed ကို တင်ပို့ပြီး ဖြစ်သည်။</string>
<string name="blogs_rss_feeds">RSS သတင်းလွှာများ</string>
<string name="blogs_rss_feeds_manage_imported">တင်သွင်းထားသော</string>
<string name="blogs_rss_feeds_manage_author">စာရေးဆရာ -</string>

View File

@@ -477,6 +477,7 @@
<string name="blogs_rss_feeds_import_button">Importer</string>
<string name="blogs_rss_feeds_import_hint">Skriv inn nettadresse for RSS-strøm</string>
<string name="blogs_rss_feeds_import_error">Vi beklager! Feil under importering av strøm.</string>
<string name="blogs_rss_feeds_import_exists">Den feed\'en er importert allerede</string>
<string name="blogs_rss_feeds">RSS-feed\'er</string>
<string name="blogs_rss_feeds_manage_imported">Importert:</string>
<string name="blogs_rss_feeds_manage_author">Forfatter:</string>

View File

@@ -244,7 +244,6 @@
<string name="menu_contact">Kontakt</string>
<!--Adding Contacts-->
<string name="add_contact_title">Dodaj kontakt w pobliżu</string>
<string name="add_contact_error_two_way">Czy oboje skanowaliście nawzajem swoje kody QR?</string>
<string name="face_to_face">Musisz spotkać się z osobą którą chcesz dodać jako kontakt.\n\nTo uniemożliwi komukolwiek udawanie Ciebie lub czytanie Twoich wiadomości w przyszłości.</string>
<string name="continue_button">Kontynuuj</string>
<string name="try_again_button">Spróbuj ponownie</string>
@@ -260,7 +259,6 @@
<string name="authenticating_with_device">Autoryzowanie z urządzeniem\u2026</string>
<string name="connection_error_title">Nie udało się połączyć z kontaktem</string>
<string name="connection_error_feedback">Jeśli problem będzie występować dalej, proszę <a href="feedback">wysłać opinię</a> aby pomóc nam ulepszyć aplikację.</string>
<string name="info_both_must_scan">Oboje musicie skanować nawzajem swoje kody QR</string>
<!--Adding Contacts Remotely-->
<string name="add_contact_remotely_title_case">Dodaj Kontakt na odległość</string>
<string name="add_contact_nearby_title">Dodaj kontakt w pobliżu</string>
@@ -320,7 +318,6 @@
<string name="different_person_button">Inna osoba</string>
<string name="duplicate_link_dialog_text_3">%1$si %2$s wysłał ci ten sam link.\n\nJeden z nich może próbować odkryć, kim są twoje kontakty.\n\nNie mów im, że otrzymałeś ten sam link od kogoś innego.</string>
<string name="pending_contact_updated_toast">Oczekujący kontakt zaktualizowany</string>
<string name="info_both_must_enter_links">Oboje musicie dodać swoje linki</string>
<!--Peer trust levels-->
<string name="peer_trust_level_unverified">Niezweryfikowane kontakty</string>
<string name="peer_trust_level_verified">Zweryfikowane kontakty</string>
@@ -354,7 +351,6 @@
<string name="connect_via_bluetooth_intro">W przypadku gdy połączenia przez Bluetooth nie działają automatycznie, możesz użyć tego ekranu do połączenia ręcznego.\n\nTwój kontakt musi znajdować się w pobliżu, żeby to zadziałało.\n\nTy i Twój kontakt powinniście jednocześnie wcisnąć \"Start\".</string>
<string name="connect_via_bluetooth_already_discovering">Próba połączenia przez Bluetooth jest już w trakcie. Spróbuj ponownie za chwilę.</string>
<string name="connect_via_bluetooth_no_location_permission">Nie można kontynuować bez dostępu do lokalizacji</string>
<string name="connect_via_bluetooth_no_bluetooth_permission">Nie można kontynuować bez pozwolenia na urządzenia w pobliżu</string>
<string name="connect_via_bluetooth_start">Łączenie przez Bluetooth...</string>
<string name="connect_via_bluetooth_success">Udało się połączyć przez Bluetooth.</string>
<string name="connect_via_bluetooth_error">Nie można się połączyć przez Bluetooth.</string>
@@ -457,10 +453,6 @@
<string name="forum_declined_toast">Zaproszenie odrzucone</string>
<string name="shared_by_format">Udostępnione przez %s</string>
<string name="forum_invitation_already_sharing">Już udostępnione</string>
<string name="forum_invitation_already_invited">Wysłano już zaproszenie</string>
<string name="forum_invitation_invite_received">Odebrano już zaproszenie</string>
<string name="forum_invitation_not_supported">Nie obsługiwane przez ten kontakt</string>
<string name="forum_invitation_error">Błąd. Jest to błąd w naszej aplikacji, to nie twoja wina</string>
<string name="forum_invitation_response_accepted_sent">Przyjąłeś zaproszenie do forum od %s</string>
<string name="forum_invitation_response_declined_sent">Odrzuciłeś zaproszenie do forum od %s</string>
<string name="forum_invitation_response_declined_auto">Zaproszenie do forum od %s zostało automatycznie odrzucone.</string>
@@ -513,9 +505,8 @@
<string name="blogs_rss_feeds_import">Zaimportuj kanał RSS</string>
<string name="blogs_rss_feeds_import_button">Zaimportuj</string>
<string name="blogs_rss_feeds_import_hint">Wprowadź adres URL do kanału RSS</string>
<string name="blogs_rss_feeds_import_progress">Importowanie kanału RSS…</string>
<string name="blogs_rss_feeds_import_error">Przepraszamy! Wystąpił błąd podczas importowania twojego kanału RSS</string>
<string name="blogs_rss_feeds_import_title">Importuj kanał z pliku</string>
<string name="blogs_rss_feeds_import_exists">Ten feed został już zaimportowany.</string>
<string name="blogs_rss_feeds">Feedy RSS</string>
<string name="blogs_rss_feeds_manage_imported">Zaimportowane:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>
@@ -627,9 +618,7 @@
<string name="mailbox_setup_download_link">Udostępnij łącze pobierania</string>
<string name="mailbox_setup_button_scan">Zeskanuj kod QR aplikacji Mailbox</string>
<string name="permission_camera_qr_denied_body">Odmówiłeś dostępu do aparatu, ale zeskanowanie kodu QR wymaga użycia aparatu.\n\nRozważ przyznanie dostępu.</string>
<string name="mailbox_setup_connecting">Łączenie się ze Skrzynką odbiorczą…</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">Może to potrwać do %1s</string>
<string name="mailbox_setup_already_paired_title">Mailbox już podłączony</string>
<string name="mailbox_setup_already_paired_description">Odłącz Mailbox na drugim urządzeniu i spróbuj ponownie.</string>
<string name="mailbox_setup_io_error_title">Nie udało się połączyć</string>
@@ -767,15 +756,11 @@ Brak dostępu do aparatu. Spróbuj ponownie, może po ponownym uruchomieniu urz
<string name="permission_location_request_body">Aby odkryć urządzenia Bluetooth, Briar potrzebuje zezwolenia na dostęp do twojej lokalizacji.\n\nBriar nie przechowuje twojej lokalizacji ani nie udostępnia jej nikomu.</string>
<string name="permission_camera_location_title">Kamera i lokalizacja</string>
<string name="permission_camera_location_request_body">Aby zeskanować kod QR, Briar potrzebuje dostępu do kamery.\n\nAby odkryć urządzenia Bluetooth, Briar potrzebuje zezwolenia na dostęp do Twojej lokalizacji.\n\nBriar nie przechowuje Twojej lokalizacji ani nie udostępnia jej nikomu.</string>
<string name="permission_camera_bluetooth_title">Aparat i urządzenia w pobliżu</string>
<string name="permission_camera_denied_body">Odmówiłeś dostępu do aparatu, lecz dodawanie kontaktów wymaga jego użycia.\n\nProszę rozważyć udzielenie dostępu do aparatu</string>
<string name="permission_location_denied_body">Zabroniłeś dostępu do Twojej lokalizacji, ale Briar potrzebuje tego uprawnienia do wykrywania urządzeń Bluetooth.\n\nRozważ przyznanie tego dostępu.</string>
<string name="permission_location_setting_title">Ustawienia lokalizacji</string>
<string name="permission_location_setting_body">Ustawienie lokalizacji urządzenia musi być włączone, aby można było znaleźć inne urządzenia przez Bluetooth. Włącz lokalizację, aby kontynuować. Później możesz ją ponownie wyłączyć.</string>
<string name="permission_location_setting_button">Włącz lokalizację</string>
<string name="permission_bluetooth_title">Pozwolenie do urządzeń w pobliżu</string>
<string name="permission_bluetooth_body">Aby korzystać z komunikacji Bluetooth, Briar potrzebuje uprawnień do znajdowania i łączenia się z pobliskimi urządzeniami.</string>
<string name="permission_bluetooth_denied_body">Odmówiono dostępu do pobliskich urządzeń, ale Briar potrzebuje tego uprawnienia, aby korzystać z Bluetooth.\n\nRozważ udzielenie dostępu.</string>
<string name="qr_code">Kod QR</string>
<string name="show_qr_code_fullscreen">Pokaż QR na pełnym ekranie</string>
<!--App Locking-->

View File

@@ -488,6 +488,7 @@
<string name="blogs_rss_feeds_import_button">Importar</string>
<string name="blogs_rss_feeds_import_hint">Entre a URL do feed RSS</string>
<string name="blogs_rss_feeds_import_error">Nós lamentamos! Houve um erro ao importar seu Feed.</string>
<string name="blogs_rss_feeds_import_exists">Esse feed já foi importado.</string>
<string name="blogs_rss_feeds">Feeds RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>

View File

@@ -446,10 +446,6 @@
<string name="forum_declined_toast">Invitația a fost refuzată</string>
<string name="shared_by_format">Partajat de %s</string>
<string name="forum_invitation_already_sharing">Deja partajat</string>
<string name="forum_invitation_already_invited">Invitație deja trimisă</string>
<string name="forum_invitation_invite_received">Invitație deja primită</string>
<string name="forum_invitation_not_supported">Nu este susținut de acest contact</string>
<string name="forum_invitation_error">Eroare. Aceasta este o eroare și nu este vina dumneavoastră</string>
<string name="forum_invitation_response_accepted_sent">Ați acceptat invitația la forum de la %s.</string>
<string name="forum_invitation_response_declined_sent">Ați refuzat invitația la forum de la %s.</string>
<string name="forum_invitation_response_declined_auto">Invitația la forumu de la %s a fost refuzată automat.</string>
@@ -501,9 +497,8 @@
<string name="blogs_rss_feeds_import">Importați flux RSS</string>
<string name="blogs_rss_feeds_import_button">Importați</string>
<string name="blogs_rss_feeds_import_hint">Introduceți adresa URL a fluxului RSS</string>
<string name="blogs_rss_feeds_import_progress">Importarea RSS Feed…</string>
<string name="blogs_rss_feeds_import_error">Ne pare rău, dar a apărut o eroare la importarea fluxului dvs.</string>
<string name="blogs_rss_feeds_import_title">Importați feed din fișier</string>
<string name="blogs_rss_feeds_import_exists">Fluxul respectiv este deja importat.</string>
<string name="blogs_rss_feeds">Fluxuri RSS</string>
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>

View File

@@ -462,7 +462,7 @@
<string name="forum_invitation_already_invited">Приглашение уже отправлено</string>
<string name="forum_invitation_invite_received">Приглашение уже получено</string>
<string name="forum_invitation_not_supported">Не поддерживается этим контактом</string>
<string name="forum_invitation_error">Это ошибка программы. Вы тут ни причем.</string>
<string name="forum_invitation_error">Ошибка. Это программная ошибка, а не ваша вина</string>
<string name="forum_invitation_response_accepted_sent">Вы приняли приглашение на форум от %s.</string>
<string name="forum_invitation_response_declined_sent">Вы отклонили приглашение на форум от %s.</string>
<string name="forum_invitation_response_declined_auto">Приглашение на форум от %s было отклонено автоматически.</string>
@@ -515,9 +515,8 @@
<string name="blogs_rss_feeds_import">Импорт RSS-ленты</string>
<string name="blogs_rss_feeds_import_button">Импорт</string>
<string name="blogs_rss_feeds_import_hint">Введите URL-адрес RSS-ленты</string>
<string name="blogs_rss_feeds_import_progress">Импорт RSS-лент...</string>
<string name="blogs_rss_feeds_import_error">Мы сожалеем! Произошла ошибка при импорте ленты.</string>
<string name="blogs_rss_feeds_import_title">Импорт ленты из файла</string>
<string name="blogs_rss_feeds_import_exists">Эта лента уже импортирована.</string>
<string name="blogs_rss_feeds">RSS-ленты</string>
<string name="blogs_rss_feeds_manage_imported">Импортирован:</string>
<string name="blogs_rss_feeds_manage_author">Автор:</string>

View File

@@ -488,9 +488,8 @@ dhe smund të hapet me këtë version.\n\nJu lutemi, përmirësojeni me versi
<string name="blogs_rss_feeds_import">Importoni Prurje RSS</string>
<string name="blogs_rss_feeds_import_button">Importo</string>
<string name="blogs_rss_feeds_import_hint">Jepni URL-në e prurjes RSS</string>
<string name="blogs_rss_feeds_import_progress">Po importohet Prurje RSS…</string>
<string name="blogs_rss_feeds_import_error">Na ndjeni! Pati një gabim me importimin e prurjes tuaj.</string>
<string name="blogs_rss_feeds_import_title">Importo prurje nga kartelë</string>
<string name="blogs_rss_feeds_import_exists">Ajo prurje është importuar tashmë.</string>
<string name="blogs_rss_feeds">Prurje RSS</string>
<string name="blogs_rss_feeds_manage_imported">Të importuara:</string>
<string name="blogs_rss_feeds_manage_author">Autor:</string>

View File

@@ -478,6 +478,7 @@ Vänlige installera Briar på en nyare enhet.</string>
<string name="blogs_rss_feeds_import_button">Importera</string>
<string name="blogs_rss_feeds_import_hint">Skriv URL till RSS-flödet</string>
<string name="blogs_rss_feeds_import_error">Tyvärr! Något gick fel när flödet skulle importeras.</string>
<string name="blogs_rss_feeds_import_exists">Det flödet importeras redan.</string>
<string name="blogs_rss_feeds">RSS-flöden</string>
<string name="blogs_rss_feeds_manage_imported">Importerade:</string>
<string name="blogs_rss_feeds_manage_author">Författare:</string>

View File

@@ -482,6 +482,7 @@
<string name="blogs_rss_feeds_import_button">İçe Aktar</string>
<string name="blogs_rss_feeds_import_hint">RSS beslemesi URL\'sini girin</string>
<string name="blogs_rss_feeds_import_error">Üzgünüz! RSS beslemeniz içe aktarılırken bir hata oluştu.</string>
<string name="blogs_rss_feeds_import_exists">Bu besleme zaten içe aktarılmış.</string>
<string name="blogs_rss_feeds">RSS beslemeleri</string>
<string name="blogs_rss_feeds_manage_imported">İçe Aktarıldı:</string>
<string name="blogs_rss_feeds_manage_author">Yazar:</string>
@@ -593,7 +594,9 @@
<string name="mailbox_setup_download_link">İndirme Bağlantısını Paylaş</string>
<string name="mailbox_setup_button_scan">Mailbox Karekodunu Tara</string>
<string name="permission_camera_qr_denied_body">Kameraya erişimi engellediniz, ancak Mailbox karekodunu taramak için kamerayı kullanmanız gerekiyor.\n\nLütfen erişim izni vermeyi düşünün.</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">Bağlantı kuruluyor…</string>
<string name="mailbox_setup_qr_code_wrong_title">Yanlış Karekod</string>
<string name="mailbox_setup_qr_code_wrong_description">Taranan kod geçersiz. Lütfen Briar Mailbox uygulamasını Mailbox aygıtınızda açın ve gösterdiği Karekodu tarayın.</string>
<string name="mailbox_setup_already_paired_title">Mailbox zaten bağlanmış</string>
<string name="mailbox_setup_already_paired_description">Diğer aygıttan Mailbox bağlantısını kaldırın ve tekrar deneyin</string>
<string name="mailbox_setup_io_error_title">Bağlantı kurulamıyor</string>

View File

@@ -20,7 +20,7 @@
<string name="dnkm_huawei_protected_text">Будь ласка, натисніть кнопку, що знаходиться нижче і впевніться у тому, що Briar захищено на екрані \"Захищені додатки\".</string>
<string name="dnkm_huawei_protected_button">Захистити Briar</string>
<string name="dnkm_huawei_protected_help">Якщо Briar немає у списку захищених додатків, він не зможе працювати у фоновому режимі.</string>
<string name="dnkm_huawei_app_launch_text">Будь ласка, торкніться кнопки внизу, відкрийте екран «Запуск програми» й переконайтесь, що Briar має налаштування «Керувати вручну».</string>
<string name="dnkm_huawei_app_launch_text">Будь ласка, торкніть кнопку внизу, відкрийте екран «Запуск програми» й переконайтесь, що Briar має налаштування «Керувати вручну».</string>
<string name="dnkm_huawei_app_launch_help">Якщо не вказати «Керувати вручну» для Briar на екрані «Запуск програми», він не зможе працювати в фоновому режимі.</string>
<string name="dnkm_xiaomi_text">Щоб Briar працював у фоновому режимі, закріпіть його в переліку недавніх застосунків.</string>
<string name="dnkm_xiaomi_button">Захистити Briar</string>
@@ -505,6 +505,7 @@
<string name="blogs_rss_feeds_import_button">Імпортувати</string>
<string name="blogs_rss_feeds_import_hint">Введіть URL-посилання RSS-стрічки</string>
<string name="blogs_rss_feeds_import_error">Нам шкода! Виникла помилка під час імпорту вашої стрічки.</string>
<string name="blogs_rss_feeds_import_exists">Цю стрічку вже імпортовано.</string>
<string name="blogs_rss_feeds">RSS-стрічки</string>
<string name="blogs_rss_feeds_manage_imported">Імпортовано:</string>
<string name="blogs_rss_feeds_manage_author">Автор:</string>
@@ -515,7 +516,7 @@
<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>
<string name="change_profile_picture">Торкніть, щоб змінити зображення профілю</string>
<string name="dialog_confirm_profile_picture_title">Змінити зображення профілю</string>
<string name="dialog_confirm_profile_picture_remark">Лише ваші контакти можуть бачити це зображення</string>
<string name="change_profile_picture_failed_message">Перепрошуємо, щось пішло не так при оновленні вашого зображення профілю</string>
@@ -826,12 +827,12 @@
<string name="removable_drive_explanation">Якщо не вдається з\'єднатися з контактом через інтернет, Wi-Fi та Bluetooth, Briar ще може передавати повідомлення за допомогою флешки чи SD-картки.\n\nКоли ви натиснете кнопку «Надіслати дані», будь-які дані в очікуванні надсилання контактові буде записано на флешку. Зокрема дані особистих повідомлень, прикріплень, блогів, форумів і приватних груп.\n\nПеред записом на флешку все буде зашифровано.\n\nОтримавши флешку, ваш контакт зможе імпортувати повідомлення в свій Briar кнопкою «Отримати дані».</string>
<string name="removable_drive_title_send">Надіслати дані</string>
<string name="removable_drive_title_receive">Отримати дані</string>
<string name="removable_drive_send_intro">Торкніться кнопки внизу, щоб створити файл із зашифрованими повідомленнями. Ви зможете обрати, куди зберегти файл.\n\nЯкщо бажаєте зберегти файл на флешку, під\'єднайте її зараз.</string>
<string name="removable_drive_send_intro">Торкніть кнопку внизу, щоб створити файл зашифрованих повідомлень. Ви зможете обрати, куди зберегти файл.\n\nЯкщо бажаєте зберегти файл на флешку, під\'єднайте її зараз.</string>
<string name="removable_drive_send_no_data">Жодне повідомлення не очікує на надсилання цьому контактові.</string>
<string name="removable_drive_send_not_supported">Контакт використовує стару версію Briar чи старий пристрій, що не підтримує цієї можливості.</string>
<string name="removable_drive_send_button">Оберіть файл експорту</string>
<string name="removable_drive_ongoing">Дочекайтесь завершення поточного завдання</string>
<string name="removable_drive_receive_intro">Торкніться кнопки внизу, щоб обрати файл, надісланий вам контактом.\n\nЯкщо файл на флешці, під\'єднайте її зараз.</string>
<string name="removable_drive_receive_intro">Торкніть кнопку внизу, щоб обрати файл, надісланий вам контактом.\n\nЯкщо файл на флешці, під\'єднайте її зараз.</string>
<string name="removable_drive_receive_button">Оберіть файл імпорту</string>
<string name="removable_drive_success_send_title">Експорт успішний</string>
<string name="removable_drive_success_send_text">Дані успішно експортовано. Маєте 28 днів, щоб передати файл контактові.\n\nЯкщо файл на флешці, перед від\'єднанням вимкніть її за допомогою сповіщення в рядку стану.</string>

View File

@@ -473,9 +473,8 @@
<string name="blogs_rss_feeds_import">导入 RSS 订阅源</string>
<string name="blogs_rss_feeds_import_button">导入</string>
<string name="blogs_rss_feeds_import_hint">输入 RSS 订阅源链接</string>
<string name="blogs_rss_feeds_import_progress">导入 RSS 订阅源中…</string>
<string name="blogs_rss_feeds_import_error">抱歉!导入订阅源时发生错误。</string>
<string name="blogs_rss_feeds_import_title">从文件导入</string>
<string name="blogs_rss_feeds_import_exists">已经导入那个</string>
<string name="blogs_rss_feeds">RSS源 </string>
<string name="blogs_rss_feeds_manage_imported">已导入:</string>
<string name="blogs_rss_feeds_manage_author">作者:</string>

View File

@@ -423,10 +423,6 @@
<string name="forum_declined_toast">邀請已謝絕</string>
<string name="shared_by_format">由 %s 分享</string>
<string name="forum_invitation_already_sharing">已在分享</string>
<string name="forum_invitation_already_invited">已發送邀請</string>
<string name="forum_invitation_invite_received">已收到邀請</string>
<string name="forum_invitation_not_supported">此聯絡人無法使用</string>
<string name="forum_invitation_error">出錯,出了點問題與您無關</string>
<string name="forum_invitation_response_accepted_sent">您接受了來自 %s的論壇邀請</string>
<string name="forum_invitation_response_declined_sent">您謝絕了來自 %s的論壇邀請</string>
<string name="forum_invitation_response_declined_auto">來自%s論壇的邀請已自動拒絕</string>
@@ -476,9 +472,8 @@
<string name="blogs_rss_feeds_import">導入 RSS 訂閱源</string>
<string name="blogs_rss_feeds_import_button">導入</string>
<string name="blogs_rss_feeds_import_hint">輸入 RSS 訂閱源鏈接</string>
<string name="blogs_rss_feeds_import_progress">滙入 RSS 消息來源</string>
<string name="blogs_rss_feeds_import_error">抱歉!導入訂閱源時發生錯誤。</string>
<string name="blogs_rss_feeds_import_title">透過檔案滙入消息源</string>
<string name="blogs_rss_feeds_import_exists">此來源已滙入</string>
<string name="blogs_rss_feeds">RSS 消息源</string>
<string name="blogs_rss_feeds_manage_imported">已導入:</string>
<string name="blogs_rss_feeds_manage_author">作者:</string>

View File

@@ -519,9 +519,7 @@
<string name="blogs_rss_feeds_import">Import RSS Feed</string>
<string name="blogs_rss_feeds_import_button">Import</string>
<string name="blogs_rss_feeds_import_hint">Enter the URL of the RSS feed</string>
<string name="blogs_rss_feeds_import_progress">Importing RSS Feed…</string>
<string name="blogs_rss_feeds_import_error">We are sorry! There was an error importing your feed.</string>
<string name="blogs_rss_feeds_import_title">Import feed from file</string>
<string name="blogs_rss_feeds">RSS Feeds</string>
<string name="blogs_rss_feeds_manage_imported">Imported:</string>
<string name="blogs_rss_feeds_manage_author">Author:</string>

View File

@@ -56,7 +56,7 @@ public class AttachmentReaderImpl implements AttachmentReader {
String contentType = meta.getString(MSG_KEY_CONTENT_TYPE);
if (!contentType.equals(h.getContentType()))
throw new NoSuchMessageException();
int offset = meta.getInt(MSG_KEY_DESCRIPTOR_LENGTH);
int offset = meta.getLong(MSG_KEY_DESCRIPTOR_LENGTH).intValue();
InputStream stream = new ByteArrayInputStream(body, offset,
body.length - offset);
return new Attachment(h, stream);

View File

@@ -250,7 +250,7 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
try {
BdfDictionary meta =
clientHelper.getGroupMetadataAsDictionary(txn, g);
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e);
}

View File

@@ -76,7 +76,7 @@ class AvatarValidator implements MessageValidator {
// 0.0: Message Type, Version, Content-Type
checkSize(body, 3);
// Message Type
int messageType = body.getInt(0);
long messageType = body.getLong(0);
if (messageType != MSG_TYPE_UPDATE) throw new FormatException();
// Version
long version = body.getLong(1);

View File

@@ -487,7 +487,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
}
private String getPostText(BdfList message) throws FormatException {
MessageType type = MessageType.valueOf(message.getInt(0));
MessageType type = MessageType.valueOf(message.getLong(0).intValue());
if (type == POST) {
// Type, text, signature
return message.getString(1);
@@ -621,6 +621,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
}
private MessageType getMessageType(BdfDictionary d) throws FormatException {
return MessageType.valueOf(d.getInt(KEY_TYPE));
Long longType = d.getLong(KEY_TYPE);
return MessageType.valueOf(longType.intValue());
}
}

View File

@@ -167,6 +167,6 @@ class BlogPostFactoryImpl implements BlogPostFactory {
}
private MessageType getType(BdfList body) throws FormatException {
return MessageType.valueOf(body.getInt(0));
return MessageType.valueOf(body.getLong(0).intValue());
}
}

View File

@@ -72,7 +72,7 @@ class BlogPostValidator extends BdfMessageValidator {
BdfMessageContext c;
int type = body.getInt(0);
int type = body.getLong(0).intValue();
body.remove(0);
switch (MessageType.valueOf(type)) {
case POST:

View File

@@ -114,8 +114,8 @@ class MessageTrackerImpl implements MessageTracker {
try {
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
return new GroupCount(
d.getInt(GROUP_KEY_MSG_COUNT, 0),
d.getInt(GROUP_KEY_UNREAD_COUNT, 0),
d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(),
d.getLong(GROUP_KEY_LATEST_MSG, 0L)
);
} catch (FormatException e) {

View File

@@ -47,7 +47,7 @@ class IntroductionValidator extends BdfMessageValidator {
@Override
protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws FormatException {
MessageType type = MessageType.fromValue(body.getInt(0));
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
switch (type) {
case REQUEST:

View File

@@ -59,8 +59,8 @@ class MessageParserImpl implements MessageParser {
@Override
public MessageMetadata parseMetadata(BdfDictionary d)
throws FormatException {
MessageType type =
MessageType.fromValue(d.getInt(MSG_KEY_MESSAGE_TYPE));
MessageType type = MessageType
.fromValue(d.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
byte[] sessionIdBytes = d.getOptionalRaw(MSG_KEY_SESSION_ID);
SessionId sessionId =
sessionIdBytes == null ? null : new SessionId(sessionIdBytes);

View File

@@ -72,7 +72,7 @@ class SessionParserImpl implements SessionParser {
@Override
public Role getRole(BdfDictionary d) throws FormatException {
return Role.fromValue(d.getInt(SESSION_KEY_ROLE));
return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue());
}
@Override
@@ -97,7 +97,7 @@ class SessionParserImpl implements SessionParser {
MessageId lastRemoteMessageId =
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
GroupId groupId = getGroupId(d);
GroupId groupId = getGroupId(d, SESSION_KEY_GROUP_ID);
Author author = getAuthor(d, SESSION_KEY_AUTHOR);
return new Introducee(sessionId, groupId, author, localTimestamp,
lastLocalMessageId, lastRemoteMessageId);
@@ -126,10 +126,12 @@ class SessionParserImpl implements SessionParser {
MessageId lastLocalMessageId =
getMessageId(d, SESSION_KEY_LAST_LOCAL_MESSAGE_ID);
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
PublicKey ephemeralPublicKey = getEphemeralPublicKey(d);
PublicKey ephemeralPublicKey =
getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
BdfDictionary tpDict =
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
PrivateKey ephemeralPrivateKey = getEphemeralPrivateKey(d);
PrivateKey ephemeralPrivateKey =
getEphemeralPrivateKey(d, SESSION_KEY_EPHEMERAL_PRIVATE_KEY);
Map<TransportId, TransportProperties> transportProperties =
tpDict == null ? null : clientHelper
.parseAndValidateTransportPropertiesMap(tpDict);
@@ -145,7 +147,8 @@ class SessionParserImpl implements SessionParser {
Author remoteAuthor = getAuthor(d, SESSION_KEY_REMOTE_AUTHOR);
MessageId lastRemoteMessageId =
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
PublicKey ephemeralPublicKey = getEphemeralPublicKey(d);
PublicKey ephemeralPublicKey =
getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
BdfDictionary tpDict =
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
Map<TransportId, TransportProperties> transportProperties =
@@ -159,7 +162,7 @@ class SessionParserImpl implements SessionParser {
}
private int getState(BdfDictionary d) throws FormatException {
return d.getInt(SESSION_KEY_STATE);
return d.getLong(SESSION_KEY_STATE).intValue();
}
private SessionId getSessionId(BdfDictionary d) throws FormatException {
@@ -174,8 +177,9 @@ class SessionParserImpl implements SessionParser {
return b == null ? null : new MessageId(b);
}
private GroupId getGroupId(BdfDictionary d) throws FormatException {
return new GroupId(d.getRaw(SESSION_KEY_GROUP_ID));
private GroupId getGroupId(BdfDictionary d, String key)
throws FormatException {
return new GroupId(d.getRaw(key));
}
private Author getAuthor(BdfDictionary d, String key)
@@ -189,22 +193,23 @@ class SessionParserImpl implements SessionParser {
if (d == null) return null;
Map<TransportId, KeySetId> map = new HashMap<>(d.size());
for (String key : d.keySet()) {
map.put(new TransportId(key), new KeySetId(d.getInt(key)));
map.put(new TransportId(key),
new KeySetId(d.getLong(key).intValue()));
}
return map;
}
@Nullable
private PublicKey getEphemeralPublicKey(BdfDictionary d)
throws FormatException {
byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
private PublicKey getEphemeralPublicKey(BdfDictionary d, String key)
throws FormatException {
byte[] keyBytes = d.getOptionalRaw(key);
return keyBytes == null ? null : new AgreementPublicKey(keyBytes);
}
@Nullable
private PrivateKey getEphemeralPrivateKey(BdfDictionary d)
throws FormatException {
byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PRIVATE_KEY);
private PrivateKey getEphemeralPrivateKey(BdfDictionary d, String key)
throws FormatException {
byte[] keyBytes = d.getOptionalRaw(key);
return keyBytes == null ? null : new AgreementPrivateKey(keyBytes);
}
}

View File

@@ -182,7 +182,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
try {
BdfDictionary metaDict = metadataParser.parse(meta);
// Message type is null for version 0.0 private messages
Integer messageType = metaDict.getOptionalInt(MSG_KEY_MSG_TYPE);
Long messageType = metaDict.getOptionalLong(MSG_KEY_MSG_TYPE);
if (messageType == null) {
incomingPrivateMessage(txn, m, metaDict, true, emptyList());
} else if (messageType == PRIVATE_MESSAGE) {
@@ -371,7 +371,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
try {
BdfDictionary meta =
clientHelper.getGroupMetadataAsDictionary(txn, g);
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e);
}
@@ -381,7 +381,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
public ContactId getContactId(GroupId g) throws DbException {
try {
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g);
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e);
}
@@ -419,7 +419,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
if (meta == null) continue;
try {
// Message type is null for version 0.0 private messages
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
if (messageType != null && messageType != PRIVATE_MESSAGE)
continue;
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
@@ -453,8 +453,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
Map<MessageId, BdfDictionary> messages =
clientHelper.getMessageMetadataAsDictionary(txn, g);
for (Entry<MessageId, BdfDictionary> entry : messages.entrySet()) {
Integer type =
entry.getValue().getOptionalInt(MSG_KEY_MSG_TYPE);
Long type = entry.getValue().getOptionalLong(MSG_KEY_MSG_TYPE);
if (type == null || type == PRIVATE_MESSAGE)
result.add(entry.getKey());
}
@@ -528,7 +527,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
try {
BdfDictionary meta =
clientHelper.getMessageMetadataAsDictionary(txn, m);
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
if (messageType != null && messageType == PRIVATE_MESSAGE) {
for (AttachmentHeader h : parseAttachmentHeaders(g, meta)) {
try {
@@ -555,7 +554,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
int unreadCount = 0;
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
BdfDictionary meta = entry.getValue();
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
if (messageType == null || messageType == PRIVATE_MESSAGE) {
msgCount++;
if (!meta.getBoolean(MSG_KEY_READ)) unreadCount++;

View File

@@ -84,7 +84,7 @@ class PrivateMessageValidator implements MessageValidator {
context = validateLegacyPrivateMessage(m, list);
} else {
// Private message or attachment
int messageType = list.getInt(0);
int messageType = list.getLong(0).intValue();
if (messageType == PRIVATE_MESSAGE) {
if (!reader.eof()) throw new FormatException();
context = validatePrivateMessage(m, list);

View File

@@ -63,7 +63,7 @@ class GroupMessageValidator extends BdfMessageValidator {
checkSize(body, 4, 6);
// Message type (int)
int type = body.getInt(0);
int type = body.getLong(0).intValue();
// Member (author)
BdfList memberList = body.getList(1);

View File

@@ -366,7 +366,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
// parse the metadata
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
BdfDictionary meta = entry.getValue();
if (meta.getInt(KEY_TYPE) == JOIN.getInt()) {
if (meta.getLong(KEY_TYPE) == JOIN.getInt()) {
headers.add(getJoinMessageHeader(txn, g, entry.getKey(),
meta, authorInfos));
} else {
@@ -530,7 +530,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
BdfList body, BdfDictionary meta)
throws DbException, FormatException {
MessageType type = MessageType.valueOf(meta.getInt(KEY_TYPE));
MessageType type =
MessageType.valueOf(meta.getLong(KEY_TYPE).intValue());
switch (type) {
case JOIN:
handleJoinMessage(txn, m, meta);
@@ -575,8 +576,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
.getMessageMetadataAsDictionary(txn, parentId);
if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP))
throw new FormatException();
MessageType parentType =
MessageType.valueOf(parentMeta.getInt(KEY_TYPE));
MessageType parentType = MessageType
.valueOf(parentMeta.getLong(KEY_TYPE).intValue());
if (parentType != POST)
throw new FormatException();
}
@@ -591,8 +592,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
if (!getAuthor(meta).equals(getAuthor(previousMeta)))
throw new FormatException();
// previous message must be a POST or JOIN
MessageType previousType =
MessageType.valueOf(previousMeta.getInt(KEY_TYPE));
MessageType previousType = MessageType
.valueOf(previousMeta.getLong(KEY_TYPE).intValue());
if (previousType != JOIN && previousType != POST)
throw new FormatException();
// track message and broadcast event
@@ -640,7 +641,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
private Visibility getVisibility(BdfDictionary meta)
throws FormatException {
return Visibility.valueOf(meta.getInt(GROUP_KEY_VISIBILITY));
return Visibility
.valueOf(meta.getLong(GROUP_KEY_VISIBILITY).intValue());
}
}

View File

@@ -2,6 +2,12 @@ package org.briarproject.briar.privategroup.invitation;
interface GroupInvitationConstants {
/**
* Metadata key for the client's local group, indicating that contact
* groups have been created for all contacts.
*/
String GROUP_KEY_SETUP = "setup";
// Message metadata keys
String MSG_KEY_MESSAGE_TYPE = "messageType";
String MSG_KEY_PRIVATE_GROUP_ID = "privateGroupId";

View File

@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
@@ -63,6 +64,7 @@ import static org.briarproject.briar.privategroup.invitation.CreatorState.ERROR;
import static org.briarproject.briar.privategroup.invitation.CreatorState.INVITED;
import static org.briarproject.briar.privategroup.invitation.CreatorState.JOINED;
import static org.briarproject.briar.privategroup.invitation.CreatorState.START;
import static org.briarproject.briar.privategroup.invitation.GroupInvitationConstants.GROUP_KEY_SETUP;
import static org.briarproject.briar.privategroup.invitation.MessageType.ABORT;
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
@@ -114,13 +116,35 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
@Override
public void onDatabaseOpened(Transaction txn) throws DbException {
// Create a local group to indicate that we've set this client up
// If the feature flag for this client was set and then cleared, we may
// have set things up for some pre-existing contacts and not others.
// If the local group exists and has GROUP_KEY_SETUP == true in its
// metadata then we've set things up for all contacts. Otherwise we
// need to check whether a contact group exists for each contact.
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION);
if (db.containsGroup(txn, localGroup.getId())) return;
db.addGroup(txn, localGroup);
// Set things up for any pre-existing contacts
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
try {
if (db.containsGroup(txn, localGroup.getId())) {
// If GROUP_KEY_SETUP == true then we're done
BdfDictionary meta = clientHelper
.getGroupMetadataAsDictionary(txn, localGroup.getId());
if (meta.getBoolean(GROUP_KEY_SETUP, false)) return;
} else {
db.addGroup(txn, localGroup);
}
BdfDictionary meta =
BdfDictionary.of(new BdfEntry(GROUP_KEY_SETUP, true));
clientHelper.mergeGroupMetadata(txn, localGroup.getId(), meta);
} catch (FormatException e) {
throw new DbException(e);
}
// Set things up for any contacts that haven't already been set up
for (Contact c : db.getContacts(txn)) {
Group contactGroup = getContactGroup(c);
if (!db.containsGroup(txn, contactGroup.getId())) {
addingContact(txn, c);
}
}
}
@Override
@@ -712,9 +736,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
// get all sessions and their states
Map<GroupId, DeletableSession> sessions = new HashMap<>();
for (BdfDictionary d : metadata.values()) {
if (!sessionParser.isSession(d)) continue;
Session<?> session;
try {
if (!sessionParser.isSession(d)) continue;
session = sessionParser.parseSession(g, d);
} catch (FormatException e) {
throw new DbException(e);
@@ -776,12 +800,13 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
// assign protocol messages to their sessions
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
// skip all sessions, we are only interested in messages
BdfDictionary d = entry.getValue();
if (sessionParser.isSession(d)) continue;
// parse message metadata and skip messages not visible in UI
MessageMetadata m;
try {
// skip all sessions, we are only interested in messages
BdfDictionary d = entry.getValue();
if (sessionParser.isSession(d)) continue;
m = messageParser.parseMetadata(d);
} catch (FormatException e) {
throw new DbException(e);

View File

@@ -56,7 +56,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
@Override
protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws FormatException {
MessageType type = MessageType.fromValue(body.getInt(0));
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
switch (type) {
case INVITE:
return validateInviteMessage(m, body);

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