mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Compare commits
30 Commits
feature-fl
...
alpha-1.4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f02bbebf6c | ||
|
|
b8612715f8 | ||
|
|
b86ddfa22f | ||
|
|
0dd4d86f4a | ||
|
|
17e0829f42 | ||
|
|
938d8b71a0 | ||
|
|
1b808584b6 | ||
|
|
36db5b48ef | ||
|
|
ccd6ed9ff0 | ||
|
|
0ced10b3a9 | ||
|
|
98064e9efe | ||
|
|
63172ef2e4 | ||
|
|
7a854e70cb | ||
|
|
ac8a4db457 | ||
|
|
5a09530670 | ||
|
|
4fe91bacc6 | ||
|
|
7f70a1519b | ||
|
|
c92ee0458e | ||
|
|
10b1fe756d | ||
|
|
1a2a250be0 | ||
|
|
a621b8077e | ||
|
|
19084d4060 | ||
|
|
2f73ee1b57 | ||
|
|
45fa12c0b3 | ||
|
|
4253bbaaf5 | ||
|
|
8c2e58796b | ||
|
|
3f13e7e9c3 | ||
|
|
421a93b9a6 | ||
|
|
8a088638db | ||
|
|
a888c5f632 |
@@ -83,7 +83,8 @@ android test:
|
|||||||
test_reproducible:
|
test_reproducible:
|
||||||
stage: check_reproducibility
|
stage: check_reproducibility
|
||||||
script:
|
script:
|
||||||
- "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"
|
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=\"briar ${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[RELEASE_TAG]=\"briar-headless ${CI_COMMIT_REF_NAME}\" https://code.briarproject.org/api/v4/projects/307/trigger/pipeline"
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 10420
|
versionCode 10422
|
||||||
versionName "1.4.20"
|
versionName "1.4.22"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@@ -23,17 +24,24 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
|
|||||||
public abstract class BdfMessageValidator implements MessageValidator {
|
public abstract class BdfMessageValidator implements MessageValidator {
|
||||||
|
|
||||||
protected static final Logger LOG =
|
protected static final Logger LOG =
|
||||||
Logger.getLogger(BdfMessageValidator.class.getName());
|
getLogger(BdfMessageValidator.class.getName());
|
||||||
|
|
||||||
protected final ClientHelper clientHelper;
|
protected final ClientHelper clientHelper;
|
||||||
protected final MetadataEncoder metadataEncoder;
|
protected final MetadataEncoder metadataEncoder;
|
||||||
protected final Clock clock;
|
protected final Clock clock;
|
||||||
|
protected final boolean canonical;
|
||||||
|
|
||||||
protected BdfMessageValidator(ClientHelper clientHelper,
|
protected BdfMessageValidator(ClientHelper clientHelper,
|
||||||
MetadataEncoder metadataEncoder, Clock clock) {
|
MetadataEncoder metadataEncoder, Clock clock, boolean canonical) {
|
||||||
this.clientHelper = clientHelper;
|
this.clientHelper = clientHelper;
|
||||||
this.metadataEncoder = metadataEncoder;
|
this.metadataEncoder = metadataEncoder;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
|
this.canonical = canonical;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BdfMessageValidator(ClientHelper clientHelper,
|
||||||
|
MetadataEncoder metadataEncoder, Clock clock) {
|
||||||
|
this(clientHelper, metadataEncoder, clock, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract BdfMessageContext validateMessage(Message m, Group g,
|
protected abstract BdfMessageContext validateMessage(Message m, Group g,
|
||||||
@@ -49,7 +57,7 @@ public abstract class BdfMessageValidator implements MessageValidator {
|
|||||||
"Timestamp is too far in the future");
|
"Timestamp is too far in the future");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
BdfList bodyList = clientHelper.toList(m.getBody());
|
BdfList bodyList = clientHelper.toList(m, canonical);
|
||||||
BdfMessageContext result = validateMessage(m, g, bodyList);
|
BdfMessageContext result = validateMessage(m, g, bodyList);
|
||||||
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
Metadata meta = metadataEncoder.encode(result.getDictionary());
|
||||||
return new MessageContext(meta, result.getDependencies());
|
return new MessageContext(meta, result.getDependencies());
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ public interface ClientHelper {
|
|||||||
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
|
BdfList getMessageAsList(Transaction txn, MessageId m) throws DbException,
|
||||||
FormatException;
|
FormatException;
|
||||||
|
|
||||||
|
BdfList getMessageAsList(Transaction txn, MessageId m, boolean canonical)
|
||||||
|
throws DbException, FormatException;
|
||||||
|
|
||||||
BdfDictionary getGroupMetadataAsDictionary(GroupId g) throws DbException,
|
BdfDictionary getGroupMetadataAsDictionary(GroupId g) throws DbException,
|
||||||
FormatException;
|
FormatException;
|
||||||
|
|
||||||
@@ -106,6 +109,8 @@ public interface ClientHelper {
|
|||||||
|
|
||||||
BdfList toList(Message m) throws FormatException;
|
BdfList toList(Message m) throws FormatException;
|
||||||
|
|
||||||
|
BdfList toList(Message m, boolean canonical) throws FormatException;
|
||||||
|
|
||||||
BdfList toList(Author a);
|
BdfList toList(Author a);
|
||||||
|
|
||||||
byte[] sign(String label, BdfList toSign, PrivateKey privateKey)
|
byte[] sign(String label, BdfList toSign, PrivateKey privateKey)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class BdfDictionary extends TreeMap<String, Object> {
|
public final class BdfDictionary extends TreeMap<String, Object> {
|
||||||
|
|
||||||
public static final Object NULL_VALUE = new Object();
|
public static final Object NULL_VALUE = new Object();
|
||||||
|
|
||||||
@@ -39,9 +39,9 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getBoolean(String key) throws FormatException {
|
public Boolean getBoolean(String key) throws FormatException {
|
||||||
Object o = get(key);
|
Boolean value = getOptionalBoolean(key);
|
||||||
if (o instanceof Boolean) return (Boolean) o;
|
if (value == null) throw new FormatException();
|
||||||
throw new FormatException();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -52,19 +52,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getBoolean(String key, Boolean defaultValue) {
|
public Boolean getBoolean(String key, Boolean defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof Boolean) return (Boolean) o;
|
Boolean value = getOptionalBoolean(key);
|
||||||
return defaultValue;
|
return value == null ? defaultValue : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLong(String key) throws FormatException {
|
public Long getLong(String key) throws FormatException {
|
||||||
Object o = get(key);
|
Long value = getOptionalLong(key);
|
||||||
if (o instanceof Long) return (Long) o;
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Integer) return ((Integer) o).longValue();
|
return value;
|
||||||
if (o instanceof Short) return ((Short) o).longValue();
|
|
||||||
if (o instanceof Byte) return ((Byte) o).longValue();
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -78,20 +75,37 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLong(String key, Long defaultValue) {
|
public Long getLong(String key, Long defaultValue) throws FormatException {
|
||||||
Object o = get(key);
|
Long value = getOptionalLong(key);
|
||||||
if (o instanceof Long) return (Long) o;
|
return value == null ? defaultValue : value;
|
||||||
if (o instanceof Integer) return ((Integer) o).longValue();
|
}
|
||||||
if (o instanceof Short) return ((Short) o).longValue();
|
|
||||||
if (o instanceof Byte) return ((Byte) o).longValue();
|
public Integer getInt(String key) throws FormatException {
|
||||||
return defaultValue;
|
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 Double getDouble(String key) throws FormatException {
|
public Double getDouble(String key) throws FormatException {
|
||||||
Object o = get(key);
|
Double value = getOptionalDouble(key);
|
||||||
if (o instanceof Double) return (Double) o;
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Float) return ((Float) o).doubleValue();
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -103,17 +117,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Double getDouble(String key, Double defaultValue) {
|
public Double getDouble(String key, Double defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof Double) return (Double) o;
|
Double value = getOptionalDouble(key);
|
||||||
if (o instanceof Float) return ((Float) o).doubleValue();
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(String key) throws FormatException {
|
public String getString(String key) throws FormatException {
|
||||||
Object o = get(key);
|
String value = getOptionalString(key);
|
||||||
if (o instanceof String) return (String) o;
|
if (value == null) throw new FormatException();
|
||||||
throw new FormatException();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -124,17 +137,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(String key, String defaultValue) {
|
public String getString(String key, String defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof String) return (String) o;
|
String value = getOptionalString(key);
|
||||||
return defaultValue;
|
return value == null ? defaultValue : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRaw(String key) throws FormatException {
|
public byte[] getRaw(String key) throws FormatException {
|
||||||
Object o = get(key);
|
byte[] value = getOptionalRaw(key);
|
||||||
if (o instanceof byte[]) return (byte[]) o;
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Bytes) return ((Bytes) o).getBytes();
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -146,17 +158,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRaw(String key, byte[] defaultValue) {
|
public byte[] getRaw(String key, byte[] defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof byte[]) return (byte[]) o;
|
byte[] value = getOptionalRaw(key);
|
||||||
if (o instanceof Bytes) return ((Bytes) o).getBytes();
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfList getList(String key) throws FormatException {
|
public BdfList getList(String key) throws FormatException {
|
||||||
Object o = get(key);
|
BdfList value = getOptionalList(key);
|
||||||
if (o instanceof BdfList) return (BdfList) o;
|
if (value == null) throw new FormatException();
|
||||||
throw new FormatException();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -167,16 +178,16 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfList getList(String key, BdfList defaultValue) {
|
public BdfList getList(String key, BdfList defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof BdfList) return (BdfList) o;
|
BdfList value = getOptionalList(key);
|
||||||
return defaultValue;
|
return value == null ? defaultValue : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getDictionary(String key) throws FormatException {
|
public BdfDictionary getDictionary(String key) throws FormatException {
|
||||||
Object o = get(key);
|
BdfDictionary value = getOptionalDictionary(key);
|
||||||
if (o instanceof BdfDictionary) return (BdfDictionary) o;
|
if (value == null) throw new FormatException();
|
||||||
throw new FormatException();
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -188,9 +199,9 @@ public class BdfDictionary extends TreeMap<String, Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue) {
|
public BdfDictionary getDictionary(String key, BdfDictionary defaultValue)
|
||||||
Object o = get(key);
|
throws FormatException {
|
||||||
if (o instanceof BdfDictionary) return (BdfDictionary) o;
|
BdfDictionary value = getOptionalDictionary(key);
|
||||||
return defaultValue;
|
return value == null ? defaultValue : value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class BdfList extends ArrayList<Object> {
|
public final class BdfList extends ArrayList<Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method for constructing lists inline.
|
* Factory method for constructing lists inline.
|
||||||
@@ -33,15 +33,15 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
super(items);
|
super(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
private boolean isInRange(int index) {
|
private boolean isInRange(int index) {
|
||||||
return index >= 0 && index < size();
|
return index >= 0 && index < size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getBoolean(int index) throws FormatException {
|
public Boolean getBoolean(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
Boolean value = getOptionalBoolean(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Boolean) return (Boolean) o;
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -53,21 +53,16 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getBoolean(int index, Boolean defaultValue) {
|
public Boolean getBoolean(int index, Boolean defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
Boolean value = getOptionalBoolean(index);
|
||||||
if (o instanceof Boolean) return (Boolean) o;
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLong(int index) throws FormatException {
|
public Long getLong(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
Long value = getOptionalLong(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Long) return (Long) o;
|
return value;
|
||||||
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
|
@Nullable
|
||||||
@@ -82,22 +77,37 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getLong(int index, Long defaultValue) {
|
public Long getLong(int index, Long defaultValue) throws FormatException {
|
||||||
if (!isInRange(index)) return defaultValue;
|
Long value = getOptionalLong(index);
|
||||||
Object o = get(index);
|
return value == null ? defaultValue : value;
|
||||||
if (o instanceof Long) return (Long) o;
|
}
|
||||||
if (o instanceof Integer) return ((Integer) o).longValue();
|
|
||||||
if (o instanceof Short) return ((Short) o).longValue();
|
public Integer getInt(int index) throws FormatException {
|
||||||
if (o instanceof Byte) return ((Byte) o).longValue();
|
Integer value = getOptionalInt(index);
|
||||||
return defaultValue;
|
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 Double getDouble(int index) throws FormatException {
|
public Double getDouble(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
Double value = getOptionalDouble(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof Double) return (Double) o;
|
return value;
|
||||||
if (o instanceof Float) return ((Float) o).doubleValue();
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -110,19 +120,16 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Double getDouble(int index, Double defaultValue) {
|
public Double getDouble(int index, Double defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
Double value = getOptionalDouble(index);
|
||||||
if (o instanceof Double) return (Double) o;
|
return value == null ? defaultValue : value;
|
||||||
if (o instanceof Float) return ((Float) o).doubleValue();
|
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(int index) throws FormatException {
|
public String getString(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
String value = getOptionalString(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof String) return (String) o;
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -134,19 +141,16 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getString(int index, String defaultValue) {
|
public String getString(int index, String defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
String value = getOptionalString(index);
|
||||||
if (o instanceof String) return (String) o;
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRaw(int index) throws FormatException {
|
public byte[] getRaw(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
byte[] value = getOptionalRaw(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof byte[]) return (byte[]) o;
|
return value;
|
||||||
if (o instanceof Bytes) return ((Bytes) o).getBytes();
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -159,19 +163,16 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getRaw(int index, byte[] defaultValue) {
|
public byte[] getRaw(int index, byte[] defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
byte[] value = getOptionalRaw(index);
|
||||||
if (o instanceof byte[]) return (byte[]) o;
|
return value == null ? defaultValue : value;
|
||||||
if (o instanceof Bytes) return ((Bytes) o).getBytes();
|
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfList getList(int index) throws FormatException {
|
public BdfList getList(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
BdfList value = getOptionalList(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof BdfList) return (BdfList) o;
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -183,18 +184,16 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfList getList(int index, BdfList defaultValue) {
|
public BdfList getList(int index, BdfList defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
BdfList value = getOptionalList(index);
|
||||||
if (o instanceof BdfList) return (BdfList) o;
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getDictionary(int index) throws FormatException {
|
public BdfDictionary getDictionary(int index) throws FormatException {
|
||||||
if (!isInRange(index)) throw new FormatException();
|
BdfDictionary value = getOptionalDictionary(index);
|
||||||
Object o = get(index);
|
if (value == null) throw new FormatException();
|
||||||
if (o instanceof BdfDictionary) return (BdfDictionary) o;
|
return value;
|
||||||
throw new FormatException();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -207,10 +206,9 @@ public class BdfList extends ArrayList<Object> {
|
|||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue) {
|
public BdfDictionary getDictionary(int index, BdfDictionary defaultValue)
|
||||||
if (!isInRange(index)) return defaultValue;
|
throws FormatException {
|
||||||
Object o = get(index);
|
BdfDictionary value = getOptionalDictionary(index);
|
||||||
if (o instanceof BdfDictionary) return (BdfDictionary) o;
|
return value == null ? defaultValue : value;
|
||||||
return defaultValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ public interface BdfReader {
|
|||||||
|
|
||||||
void skipLong() throws IOException;
|
void skipLong() throws IOException;
|
||||||
|
|
||||||
|
boolean hasInt() throws IOException;
|
||||||
|
|
||||||
|
int readInt() throws IOException;
|
||||||
|
|
||||||
|
void skipInt() throws IOException;
|
||||||
|
|
||||||
boolean hasDouble() throws IOException;
|
boolean hasDouble() throws IOException;
|
||||||
|
|
||||||
double readDouble() throws IOException;
|
double readDouble() throws IOException;
|
||||||
@@ -54,23 +60,11 @@ public interface BdfReader {
|
|||||||
|
|
||||||
BdfList readList() throws IOException;
|
BdfList readList() throws IOException;
|
||||||
|
|
||||||
void readListStart() throws IOException;
|
|
||||||
|
|
||||||
boolean hasListEnd() throws IOException;
|
|
||||||
|
|
||||||
void readListEnd() throws IOException;
|
|
||||||
|
|
||||||
void skipList() throws IOException;
|
void skipList() throws IOException;
|
||||||
|
|
||||||
boolean hasDictionary() throws IOException;
|
boolean hasDictionary() throws IOException;
|
||||||
|
|
||||||
BdfDictionary readDictionary() throws IOException;
|
BdfDictionary readDictionary() throws IOException;
|
||||||
|
|
||||||
void readDictionaryStart() throws IOException;
|
|
||||||
|
|
||||||
boolean hasDictionaryEnd() throws IOException;
|
|
||||||
|
|
||||||
void readDictionaryEnd() throws IOException;
|
|
||||||
|
|
||||||
void skipDictionary() throws IOException;
|
void skipDictionary() throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public interface BdfReaderFactory {
|
|||||||
|
|
||||||
BdfReader createReader(InputStream in);
|
BdfReader createReader(InputStream in);
|
||||||
|
|
||||||
|
BdfReader createReader(InputStream in, boolean canonical);
|
||||||
|
|
||||||
BdfReader createReader(InputStream in, int nestedLimit,
|
BdfReader createReader(InputStream in, int nestedLimit,
|
||||||
int maxBufferSize);
|
int maxBufferSize, boolean canonical);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,5 @@ public interface BdfWriter {
|
|||||||
|
|
||||||
void writeList(Collection<?> c) throws IOException;
|
void writeList(Collection<?> c) throws IOException;
|
||||||
|
|
||||||
void writeListStart() throws IOException;
|
|
||||||
|
|
||||||
void writeListEnd() throws IOException;
|
|
||||||
|
|
||||||
void writeDictionary(Map<?, ?> m) throws IOException;
|
void writeDictionary(Map<?, ?> m) throws IOException;
|
||||||
|
|
||||||
void writeDictionaryStart() throws IOException;
|
|
||||||
|
|
||||||
void writeDictionaryEnd() throws IOException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.api.mailbox;
|
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.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
@@ -34,6 +35,16 @@ public interface MailboxManager {
|
|||||||
*/
|
*/
|
||||||
MailboxPairingTask startPairingTask(String qrCodePayload);
|
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.
|
* Can be used by the UI to test the mailbox connection.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import java.util.regex.Pattern;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.nio.charset.CodingErrorAction.IGNORE;
|
import static java.nio.charset.CodingErrorAction.IGNORE;
|
||||||
|
import static java.nio.charset.CodingErrorAction.REPORT;
|
||||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
|
||||||
@SuppressWarnings("CharsetObjectCanBeUsed")
|
@SuppressWarnings("CharsetObjectCanBeUsed")
|
||||||
@@ -52,26 +53,38 @@ public class StringUtils {
|
|||||||
return s.getBytes(UTF_8);
|
return s.getBytes(UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String fromUtf8(byte[] bytes) {
|
public static String fromUtf8(byte[] bytes) throws FormatException {
|
||||||
return fromUtf8(bytes, 0, bytes.length);
|
return fromUtf8(bytes, 0, bytes.length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String fromUtf8(byte[] bytes, int off, int len) {
|
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 {
|
||||||
CharsetDecoder decoder = UTF_8.newDecoder();
|
CharsetDecoder decoder = UTF_8.newDecoder();
|
||||||
decoder.onMalformedInput(IGNORE);
|
decoder.onMalformedInput(strict ? REPORT : IGNORE);
|
||||||
decoder.onUnmappableCharacter(IGNORE);
|
decoder.onUnmappableCharacter(strict ? REPORT : IGNORE);
|
||||||
ByteBuffer buffer = ByteBuffer.wrap(bytes, off, len);
|
ByteBuffer buffer = ByteBuffer.wrap(bytes, off, len);
|
||||||
try {
|
try {
|
||||||
return decoder.decode(buffer).toString();
|
return decoder.decode(buffer).toString();
|
||||||
} catch (CharacterCodingException e) {
|
} catch (CharacterCodingException e) {
|
||||||
throw new AssertionError(e);
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String truncateUtf8(String s, int maxUtf8Length) {
|
public static String truncateUtf8(String s, int maxUtf8Length) {
|
||||||
byte[] utf8 = toUtf8(s);
|
byte[] utf8 = toUtf8(s);
|
||||||
if (utf8.length <= maxUtf8Length) return s;
|
if (utf8.length <= maxUtf8Length) return s;
|
||||||
return fromUtf8(utf8, 0, maxUtf8Length);
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.bramble.api.data;
|
package org.briarproject.bramble.api.data;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Bytes;
|
import org.briarproject.bramble.api.Bytes;
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -8,9 +9,12 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map.Entry;
|
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.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class BdfDictionaryTest extends BrambleTestCase {
|
public class BdfDictionaryTest extends BrambleTestCase {
|
||||||
@@ -19,20 +23,20 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
public void testConstructors() {
|
public void testConstructors() {
|
||||||
assertEquals(Collections.<String, Object>emptyMap(),
|
assertEquals(Collections.<String, Object>emptyMap(),
|
||||||
new BdfDictionary());
|
new BdfDictionary());
|
||||||
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
|
assertEquals(singletonMap("foo", NULL_VALUE),
|
||||||
new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE)));
|
new BdfDictionary(singletonMap("foo", NULL_VALUE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFactoryMethod() {
|
public void testFactoryMethod() {
|
||||||
assertEquals(Collections.<String, Object>emptyMap(),
|
assertEquals(Collections.<String, Object>emptyMap(),
|
||||||
BdfDictionary.of());
|
BdfDictionary.of());
|
||||||
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
|
assertEquals(singletonMap("foo", NULL_VALUE),
|
||||||
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
|
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIntegerPromotion() throws Exception {
|
public void testLongPromotion() throws Exception {
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
d.put("foo", (byte) 1);
|
d.put("foo", (byte) 1);
|
||||||
d.put("bar", (short) 2);
|
d.put("bar", (short) 2);
|
||||||
@@ -44,6 +48,33 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
assertEquals(Long.valueOf(4), d.getLong("bam"));
|
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
|
@Test
|
||||||
public void testFloatPromotion() throws Exception {
|
public void testFloatPromotion() throws Exception {
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
@@ -67,7 +98,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeySetIteratorIsOrderedByKeys() throws Exception {
|
public void testKeySetIteratorIsOrderedByKeys() {
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
d.put("a", 1);
|
d.put("a", 1);
|
||||||
d.put("d", 4);
|
d.put("d", 4);
|
||||||
@@ -86,7 +117,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValuesIteratorIsOrderedByKeys() throws Exception {
|
public void testValuesIteratorIsOrderedByKeys() {
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
d.put("a", 1);
|
d.put("a", 1);
|
||||||
d.put("d", 4);
|
d.put("d", 4);
|
||||||
@@ -105,7 +136,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEntrySetIteratorIsOrderedByKeys() throws Exception {
|
public void testEntrySetIteratorIsOrderedByKeys() {
|
||||||
BdfDictionary d = new BdfDictionary();
|
BdfDictionary d = new BdfDictionary();
|
||||||
d.put("a", 1);
|
d.put("a", 1);
|
||||||
d.put("d", 4);
|
d.put("d", 4);
|
||||||
@@ -130,4 +161,284 @@ public class BdfDictionaryTest extends BrambleTestCase {
|
|||||||
assertEquals("d", e.getKey());
|
assertEquals("d", e.getKey());
|
||||||
assertEquals(4, e.getValue());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,31 +5,31 @@ import org.briarproject.bramble.api.FormatException;
|
|||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import static java.lang.Boolean.TRUE;
|
||||||
import java.util.Collections;
|
import static java.util.Arrays.asList;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
public class BdfListTest extends BrambleTestCase {
|
public class BdfListTest extends BrambleTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstructors() {
|
public void testConstructors() {
|
||||||
assertEquals(Collections.emptyList(), new BdfList());
|
assertEquals(emptyList(), new BdfList());
|
||||||
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
|
assertEquals(asList(1, 2, NULL_VALUE),
|
||||||
new BdfList(Arrays.asList(1, 2, NULL_VALUE)));
|
new BdfList(asList(1, 2, NULL_VALUE)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFactoryMethod() {
|
public void testFactoryMethod() {
|
||||||
assertEquals(Collections.emptyList(), BdfList.of());
|
assertEquals(emptyList(), BdfList.of());
|
||||||
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
|
assertEquals(asList(1, 2, NULL_VALUE), BdfList.of(1, 2, NULL_VALUE));
|
||||||
BdfList.of(1, 2, NULL_VALUE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIntegerPromotion() throws Exception {
|
public void testLongPromotion() throws Exception {
|
||||||
BdfList list = new BdfList();
|
BdfList list = new BdfList();
|
||||||
list.add((byte) 1);
|
list.add((byte) 1);
|
||||||
list.add((short) 2);
|
list.add((short) 2);
|
||||||
@@ -41,6 +41,31 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
assertEquals(Long.valueOf(4), list.getLong(3));
|
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
|
@Test
|
||||||
public void testFloatPromotion() throws Exception {
|
public void testFloatPromotion() throws Exception {
|
||||||
BdfList list = new BdfList();
|
BdfList list = new BdfList();
|
||||||
@@ -63,61 +88,6 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
assertArrayEquals(new byte[123], second);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForBooleanThrowsFormatException()
|
public void testNegativeIndexForBooleanThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -130,6 +100,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalBoolean(-1);
|
new BdfList().getOptionalBoolean(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultBooleanThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getBoolean(-1, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForLongThrowsFormatException()
|
public void testNegativeIndexForLongThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -142,6 +118,30 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalLong(-1);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForDoubleThrowsFormatException()
|
public void testNegativeIndexForDoubleThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -154,6 +154,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalDouble(-1);
|
new BdfList().getOptionalDouble(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultDoubleThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getDouble(-1, 1D);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForStringThrowsFormatException()
|
public void testNegativeIndexForStringThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -166,6 +172,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalString(-1);
|
new BdfList().getOptionalString(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultStringThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getString(-1, "");
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForRawThrowsFormatException()
|
public void testNegativeIndexForRawThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -178,6 +190,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalRaw(-1);
|
new BdfList().getOptionalRaw(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultRawThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getRaw(-1, new byte[0]);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForListThrowsFormatException()
|
public void testNegativeIndexForListThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -190,6 +208,11 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalList(-1);
|
new BdfList().getOptionalList(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultListThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getList(-1, new BdfList());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNegativeIndexForDictionaryThrowsFormatException()
|
public void testNegativeIndexForDictionaryThrowsFormatException()
|
||||||
@@ -203,6 +226,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalDictionary(-1);
|
new BdfList().getOptionalDictionary(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testNegativeIndexForDefaultDictionaryThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getDictionary(-1, new BdfDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForBooleanThrowsFormatException()
|
public void testTooLargeIndexForBooleanThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -215,6 +244,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalBoolean(0);
|
new BdfList().getOptionalBoolean(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultBooleanThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getBoolean(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForLongThrowsFormatException()
|
public void testTooLargeIndexForLongThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -227,6 +262,30 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalLong(0);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForDoubleThrowsFormatException()
|
public void testTooLargeIndexForDoubleThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -239,6 +298,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalDouble(0);
|
new BdfList().getOptionalDouble(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultDoubleThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getDouble(0, 1D);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForStringThrowsFormatException()
|
public void testTooLargeIndexForStringThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -251,6 +316,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalString(0);
|
new BdfList().getOptionalString(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultStringThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getString(0, "");
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForRawThrowsFormatException()
|
public void testTooLargeIndexForRawThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -263,6 +334,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalRaw(0);
|
new BdfList().getOptionalRaw(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultRawThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getRaw(0, new byte[0]);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForListThrowsFormatException()
|
public void testTooLargeIndexForListThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -275,6 +352,11 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
new BdfList().getOptionalList(0);
|
new BdfList().getOptionalList(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultListThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getList(0, new BdfList());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testTooLargeIndexForDictionaryThrowsFormatException()
|
public void testTooLargeIndexForDictionaryThrowsFormatException()
|
||||||
@@ -287,6 +369,13 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
new BdfList().getOptionalDictionary(0);
|
new BdfList().getOptionalDictionary(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testTooLargeIndexForDefaultDictionaryThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
new BdfList().getDictionary(0, new BdfDictionary());
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForBooleanThrowsFormatException()
|
public void testWrongTypeForBooleanThrowsFormatException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
@@ -299,6 +388,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(123).getOptionalBoolean(0);
|
BdfList.of(123).getOptionalBoolean(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testWrongTypeForDefaultBooleanThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
BdfList.of(123).getBoolean(0, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForLongThrowsFormatException() throws Exception {
|
public void testWrongTypeForLongThrowsFormatException() throws Exception {
|
||||||
BdfList.of(1.23).getLong(0);
|
BdfList.of(1.23).getLong(0);
|
||||||
@@ -310,6 +405,29 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(1.23).getOptionalLong(0);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForDoubleThrowsFormatException() throws Exception {
|
public void testWrongTypeForDoubleThrowsFormatException() throws Exception {
|
||||||
BdfList.of(123).getDouble(0);
|
BdfList.of(123).getDouble(0);
|
||||||
@@ -321,6 +439,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(123).getOptionalDouble(0);
|
BdfList.of(123).getOptionalDouble(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testWrongTypeForDefaultDoubleThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
BdfList.of(123).getDouble(0, 1D);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForStringThrowsFormatException() throws Exception {
|
public void testWrongTypeForStringThrowsFormatException() throws Exception {
|
||||||
BdfList.of(123).getString(0);
|
BdfList.of(123).getString(0);
|
||||||
@@ -332,6 +456,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(123).getOptionalString(0);
|
BdfList.of(123).getOptionalString(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = FormatException.class)
|
||||||
|
public void testWrongTypeForDefaultStringThrowsFormatException()
|
||||||
|
throws Exception {
|
||||||
|
BdfList.of(123).getString(0, "");
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForRawThrowsFormatException() throws Exception {
|
public void testWrongTypeForRawThrowsFormatException() throws Exception {
|
||||||
BdfList.of(123).getRaw(0);
|
BdfList.of(123).getRaw(0);
|
||||||
@@ -343,6 +473,12 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(123).getOptionalRaw(0);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForListThrowsFormatException() throws Exception {
|
public void testWrongTypeForListThrowsFormatException() throws Exception {
|
||||||
BdfList.of(123).getList(0);
|
BdfList.of(123).getList(0);
|
||||||
@@ -354,6 +490,11 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
BdfList.of(123).getOptionalList(0);
|
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)
|
@Test(expected = FormatException.class)
|
||||||
public void testWrongTypeForDictionaryThrowsFormatException()
|
public void testWrongTypeForDictionaryThrowsFormatException()
|
||||||
@@ -366,4 +507,81 @@ public class BdfListTest extends BrambleTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
BdfList.of(123).getOptionalDictionary(0);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,13 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public BdfList getMessageAsList(Transaction txn, MessageId m)
|
public BdfList getMessageAsList(Transaction txn, MessageId m)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
return toList(db.getMessage(txn, m).getBody());
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -313,8 +319,13 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BdfList toList(byte[] b, int off, int len) throws FormatException {
|
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);
|
ByteArrayInputStream in = new ByteArrayInputStream(b, off, len);
|
||||||
BdfReader reader = bdfReaderFactory.createReader(in);
|
BdfReader reader = bdfReaderFactory.createReader(in, canonical);
|
||||||
try {
|
try {
|
||||||
BdfList list = reader.readList();
|
BdfList list = reader.readList();
|
||||||
if (!reader.eof()) throw new FormatException();
|
if (!reader.eof()) throw new FormatException();
|
||||||
@@ -328,7 +339,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BdfList toList(byte[] b) throws FormatException {
|
public BdfList toList(byte[] b) throws FormatException {
|
||||||
return toList(b, 0, b.length);
|
return toList(b, 0, b.length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -336,6 +347,12 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
return toList(m.getBody());
|
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
|
@Override
|
||||||
public BdfList toList(Author a) {
|
public BdfList toList(Author a) {
|
||||||
return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey());
|
return BdfList.of(a.getFormatVersion(), a.getName(), a.getPublicKey());
|
||||||
@@ -361,7 +378,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
public Author parseAndValidateAuthor(BdfList author)
|
public Author parseAndValidateAuthor(BdfList author)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
checkSize(author, 3);
|
checkSize(author, 3);
|
||||||
int formatVersion = author.getLong(0).intValue();
|
int formatVersion = author.getInt(0);
|
||||||
if (formatVersion != FORMAT_VERSION) throw new FormatException();
|
if (formatVersion != FORMAT_VERSION) throw new FormatException();
|
||||||
String name = author.getString(1);
|
String name = author.getString(1);
|
||||||
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
|
checkLength(name, 1, MAX_AUTHOR_NAME_LENGTH);
|
||||||
@@ -472,8 +489,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
if (element.size() != 2) {
|
if (element.size() != 2) {
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
list.add(new MailboxVersion(element.getLong(0).intValue(),
|
list.add(new MailboxVersion(element.getInt(0), element.getInt(1)));
|
||||||
element.getLong(1).intValue()));
|
|
||||||
}
|
}
|
||||||
// Sort the list of versions for easier comparison
|
// Sort the list of versions for easier comparison
|
||||||
sort(list);
|
sort(list);
|
||||||
@@ -486,7 +502,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
try {
|
try {
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
getGroupMetadataAsDictionary(txn, contactGroupId);
|
getGroupMetadataAsDictionary(txn, contactGroupId);
|
||||||
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e); // Invalid group metadata
|
throw new DbException(e); // Invalid group metadata
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,18 @@ class BdfReaderFactoryImpl implements BdfReaderFactory {
|
|||||||
@Override
|
@Override
|
||||||
public BdfReader createReader(InputStream in) {
|
public BdfReader createReader(InputStream in) {
|
||||||
return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
return new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
||||||
DEFAULT_MAX_BUFFER_SIZE);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BdfReader createReader(InputStream in, int nestedLimit,
|
public BdfReader createReader(InputStream in, int nestedLimit,
|
||||||
int maxBufferSize) {
|
int maxBufferSize, boolean canonical) {
|
||||||
return new BdfReaderImpl(in, nestedLimit, maxBufferSize);
|
return new BdfReaderImpl(in, nestedLimit, maxBufferSize, canonical);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,21 +33,24 @@ import static org.briarproject.bramble.util.StringUtils.fromUtf8;
|
|||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class BdfReaderImpl implements BdfReader {
|
final class BdfReaderImpl implements BdfReader {
|
||||||
|
|
||||||
private static final byte[] EMPTY_BUFFER = new byte[0];
|
private static final byte[] EMPTY_BUFFER = new byte[0];
|
||||||
|
|
||||||
private final InputStream in;
|
private final InputStream in;
|
||||||
private final int nestedLimit, maxBufferSize;
|
private final int nestedLimit, maxBufferSize;
|
||||||
|
private final boolean canonical;
|
||||||
|
|
||||||
private boolean hasLookahead = false, eof = false;
|
private boolean hasLookahead = false, eof = false;
|
||||||
private byte next;
|
private byte next;
|
||||||
private byte[] buf = new byte[8];
|
private byte[] buf = new byte[8];
|
||||||
|
|
||||||
BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize) {
|
BdfReaderImpl(InputStream in, int nestedLimit, int maxBufferSize,
|
||||||
|
boolean canonical) {
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.nestedLimit = nestedLimit;
|
this.nestedLimit = nestedLimit;
|
||||||
this.maxBufferSize = maxBufferSize;
|
this.maxBufferSize = maxBufferSize;
|
||||||
|
this.canonical = canonical;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readLookahead() throws IOException {
|
private void readLookahead() throws IOException {
|
||||||
@@ -188,13 +191,22 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
|
|
||||||
private short readInt16() throws IOException {
|
private short readInt16() throws IOException {
|
||||||
readIntoBuffer(2);
|
readIntoBuffer(2);
|
||||||
return (short) (((buf[0] & 0xFF) << 8) + (buf[1] & 0xFF));
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readInt32() throws IOException {
|
private int readInt32() throws IOException {
|
||||||
readIntoBuffer(4);
|
readIntoBuffer(4);
|
||||||
int value = 0;
|
int value = 0;
|
||||||
for (int i = 0; i < 4; i++) value |= (buf[i] & 0xFF) << (24 - i * 8);
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +214,11 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
readIntoBuffer(8);
|
readIntoBuffer(8);
|
||||||
long value = 0;
|
long value = 0;
|
||||||
for (int i = 0; i < 8; i++) value |= (buf[i] & 0xFFL) << (56 - i * 8);
|
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;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,6 +232,31 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
hasLookahead = false;
|
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
|
@Override
|
||||||
public boolean hasDouble() throws IOException {
|
public boolean hasDouble() throws IOException {
|
||||||
if (!hasLookahead) readLookahead();
|
if (!hasLookahead) readLookahead();
|
||||||
@@ -323,22 +365,11 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
private BdfList readList(int level) throws IOException {
|
private BdfList readList(int level) throws IOException {
|
||||||
if (!hasList()) throw new FormatException();
|
if (!hasList()) throw new FormatException();
|
||||||
if (level > nestedLimit) throw new FormatException();
|
if (level > nestedLimit) throw new FormatException();
|
||||||
BdfList list = new BdfList();
|
|
||||||
readListStart();
|
|
||||||
while (!hasListEnd()) list.add(readObject(level + 1));
|
|
||||||
readListEnd();
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readListStart() throws IOException {
|
|
||||||
if (!hasList()) throw new FormatException();
|
|
||||||
hasLookahead = false;
|
hasLookahead = false;
|
||||||
}
|
BdfList list = new BdfList();
|
||||||
|
while (!hasEnd()) list.add(readObject(level + 1));
|
||||||
@Override
|
readEnd();
|
||||||
public boolean hasListEnd() throws IOException {
|
return list;
|
||||||
return hasEnd();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasEnd() throws IOException {
|
private boolean hasEnd() throws IOException {
|
||||||
@@ -347,11 +378,6 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
return next == END;
|
return next == END;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void readListEnd() throws IOException {
|
|
||||||
readEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readEnd() throws IOException {
|
private void readEnd() throws IOException {
|
||||||
if (!hasEnd()) throw new FormatException();
|
if (!hasEnd()) throw new FormatException();
|
||||||
hasLookahead = false;
|
hasLookahead = false;
|
||||||
@@ -361,7 +387,7 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
public void skipList() throws IOException {
|
public void skipList() throws IOException {
|
||||||
if (!hasList()) throw new FormatException();
|
if (!hasList()) throw new FormatException();
|
||||||
hasLookahead = false;
|
hasLookahead = false;
|
||||||
while (!hasListEnd()) skipObject();
|
while (!hasEnd()) skipObject();
|
||||||
hasLookahead = false;
|
hasLookahead = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,35 +406,27 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
private BdfDictionary readDictionary(int level) throws IOException {
|
private BdfDictionary readDictionary(int level) throws IOException {
|
||||||
if (!hasDictionary()) throw new FormatException();
|
if (!hasDictionary()) throw new FormatException();
|
||||||
if (level > nestedLimit) throw new FormatException();
|
if (level > nestedLimit) throw new FormatException();
|
||||||
BdfDictionary dictionary = new BdfDictionary();
|
|
||||||
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;
|
hasLookahead = false;
|
||||||
}
|
BdfDictionary dictionary = new BdfDictionary();
|
||||||
|
String prevKey = null;
|
||||||
@Override
|
while (!hasEnd()) {
|
||||||
public boolean hasDictionaryEnd() throws IOException {
|
String key = readString();
|
||||||
return hasEnd();
|
if (canonical && prevKey != null && key.compareTo(prevKey) <= 0) {
|
||||||
}
|
// Keys not unique and sorted
|
||||||
|
throw new FormatException();
|
||||||
@Override
|
}
|
||||||
public void readDictionaryEnd() throws IOException {
|
dictionary.put(key, readObject(level + 1));
|
||||||
|
prevKey = key;
|
||||||
|
}
|
||||||
readEnd();
|
readEnd();
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skipDictionary() throws IOException {
|
public void skipDictionary() throws IOException {
|
||||||
if (!hasDictionary()) throw new FormatException();
|
if (!hasDictionary()) throw new FormatException();
|
||||||
hasLookahead = false;
|
hasLookahead = false;
|
||||||
while (!hasDictionaryEnd()) {
|
while (!hasEnd()) {
|
||||||
skipString();
|
skipString();
|
||||||
skipObject();
|
skipObject();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package org.briarproject.bramble.data;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.Bytes;
|
import org.briarproject.bramble.api.Bytes;
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
import org.briarproject.bramble.api.data.BdfWriter;
|
import org.briarproject.bramble.api.data.BdfWriter;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -15,6 +17,7 @@ import java.util.Map.Entry;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
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.api.data.BdfDictionary.NULL_VALUE;
|
||||||
import static org.briarproject.bramble.data.Types.DICTIONARY;
|
import static org.briarproject.bramble.data.Types.DICTIONARY;
|
||||||
import static org.briarproject.bramble.data.Types.END;
|
import static org.briarproject.bramble.data.Types.END;
|
||||||
@@ -33,10 +36,11 @@ 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_32;
|
||||||
import static org.briarproject.bramble.data.Types.STRING_8;
|
import static org.briarproject.bramble.data.Types.STRING_8;
|
||||||
import static org.briarproject.bramble.data.Types.TRUE;
|
import static org.briarproject.bramble.data.Types.TRUE;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.UTF_8;
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class BdfWriterImpl implements BdfWriter {
|
final class BdfWriterImpl implements BdfWriter {
|
||||||
|
|
||||||
private final OutputStream out;
|
private final OutputStream out;
|
||||||
|
|
||||||
@@ -113,7 +117,7 @@ class BdfWriterImpl implements BdfWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeString(String s) throws IOException {
|
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) {
|
if (b.length <= Byte.MAX_VALUE) {
|
||||||
out.write(STRING_8);
|
out.write(STRING_8);
|
||||||
out.write((byte) b.length);
|
out.write((byte) b.length);
|
||||||
@@ -161,39 +165,33 @@ class BdfWriterImpl implements BdfWriter {
|
|||||||
else if (o instanceof String) writeString((String) o);
|
else if (o instanceof String) writeString((String) o);
|
||||||
else if (o instanceof byte[]) writeRaw((byte[]) o);
|
else if (o instanceof byte[]) writeRaw((byte[]) o);
|
||||||
else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes());
|
else if (o instanceof Bytes) writeRaw(((Bytes) o).getBytes());
|
||||||
else if (o instanceof List) writeList((List) o);
|
else if (o instanceof List) writeList((List<?>) o);
|
||||||
else if (o instanceof Map) writeDictionary((Map) o);
|
else if (o instanceof Map) writeDictionary((Map<?, ?>) o);
|
||||||
else throw new FormatException();
|
else throw new FormatException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeListStart() throws IOException {
|
|
||||||
out.write(LIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeListEnd() throws IOException {
|
|
||||||
out.write(END);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeDictionary(Map<?, ?> m) throws IOException {
|
public void writeDictionary(Map<?, ?> m) throws IOException {
|
||||||
out.write(DICTIONARY);
|
out.write(DICTIONARY);
|
||||||
for (Entry<?, ?> e : m.entrySet()) {
|
if (m instanceof BdfDictionary) {
|
||||||
if (!(e.getKey() instanceof String)) throw new FormatException();
|
// Entries are already sorted and keys are known to be strings
|
||||||
writeString((String) e.getKey());
|
for (Entry<String, Object> e : ((BdfDictionary) m).entrySet()) {
|
||||||
writeObject(e.getValue());
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.write(END);
|
out.write(END);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeDictionaryStart() throws IOException {
|
|
||||||
out.write(DICTIONARY);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeDictionaryEnd() throws IOException {
|
|
||||||
out.write(END);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.keyagreement;
|
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.BdfWriter;
|
||||||
import org.briarproject.bramble.api.data.BdfWriterFactory;
|
import org.briarproject.bramble.api.data.BdfWriterFactory;
|
||||||
import org.briarproject.bramble.api.keyagreement.Payload;
|
import org.briarproject.bramble.api.keyagreement.Payload;
|
||||||
@@ -32,13 +33,14 @@ class PayloadEncoderImpl implements PayloadEncoder {
|
|||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION;
|
int formatIdAndVersion = (QR_FORMAT_ID << 5) | QR_FORMAT_VERSION;
|
||||||
out.write(formatIdAndVersion);
|
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);
|
BdfWriter w = bdfWriterFactory.createWriter(out);
|
||||||
try {
|
try {
|
||||||
w.writeListStart(); // Payload start
|
w.writeList(payload);
|
||||||
w.writeRaw(p.getCommitment());
|
|
||||||
for (TransportDescriptor d : p.getTransportDescriptors())
|
|
||||||
w.writeList(d.getDescriptor());
|
|
||||||
w.writeListEnd(); // Payload end
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// Shouldn't happen with ByteArrayOutputStream
|
// Shouldn't happen with ByteArrayOutputStream
|
||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class PayloadParserImpl implements PayloadParser {
|
|||||||
List<TransportDescriptor> recognised = new ArrayList<>();
|
List<TransportDescriptor> recognised = new ArrayList<>();
|
||||||
for (int i = 1; i < payload.size(); i++) {
|
for (int i = 1; i < payload.size(); i++) {
|
||||||
BdfList descriptor = payload.getList(i);
|
BdfList descriptor = payload.getList(i);
|
||||||
long transportId = descriptor.getLong(0);
|
int transportId = descriptor.getInt(0);
|
||||||
if (transportId == TRANSPORT_ID_BLUETOOTH) {
|
if (transportId == TRANSPORT_ID_BLUETOOTH) {
|
||||||
TransportId id = BluetoothConstants.ID;
|
TransportId id = BluetoothConstants.ID;
|
||||||
recognised.add(new TransportDescriptor(id, descriptor));
|
recognised.add(new TransportDescriptor(id, descriptor));
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.mailbox;
|
package org.briarproject.bramble.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
@@ -11,12 +12,15 @@ import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
|
|||||||
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
import org.briarproject.bramble.api.mailbox.MailboxStatus;
|
||||||
import org.briarproject.bramble.api.mailbox.MailboxVersion;
|
import org.briarproject.bramble.api.mailbox.MailboxVersion;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.util.Base32;
|
||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
@@ -26,6 +30,7 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.ISO_8859_1;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -98,6 +103,22 @@ class MailboxManagerImpl implements MailboxManager {
|
|||||||
return created;
|
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
|
@Override
|
||||||
public boolean checkConnection() {
|
public boolean checkConnection() {
|
||||||
List<MailboxVersion> versions = null;
|
List<MailboxVersion> versions = null;
|
||||||
|
|||||||
@@ -419,7 +419,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
private InetSocketAddress parseSocketAddress(BdfList descriptor)
|
private InetSocketAddress parseSocketAddress(BdfList descriptor)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
byte[] address = descriptor.getRaw(1);
|
byte[] address = descriptor.getRaw(1);
|
||||||
int port = descriptor.getLong(2).intValue();
|
int port = descriptor.getInt(2);
|
||||||
if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException();
|
if (port < 1 || port > MAX_16_BIT_UNSIGNED) throw new FormatException();
|
||||||
try {
|
try {
|
||||||
InetAddress addr = InetAddress.getByAddress(address);
|
InetAddress addr = InetAddress.getByAddress(address);
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
// Retrieve and parse the latest local properties
|
// Retrieve and parse the latest local properties
|
||||||
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
|
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
e.getValue().messageId);
|
e.getValue().messageId, false);
|
||||||
local.put(e.getKey(), parseProperties(message));
|
local.put(e.getKey(), parseProperties(message));
|
||||||
}
|
}
|
||||||
return local;
|
return local;
|
||||||
@@ -222,7 +222,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
if (latest != null) {
|
if (latest != null) {
|
||||||
// Retrieve and parse the latest local properties
|
// Retrieve and parse the latest local properties
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
latest.messageId);
|
latest.messageId, false);
|
||||||
p = parseProperties(message);
|
p = parseProperties(message);
|
||||||
}
|
}
|
||||||
return p == null ? new TransportProperties() : p;
|
return p == null ? new TransportProperties() : p;
|
||||||
@@ -252,7 +252,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
local = new TransportProperties();
|
local = new TransportProperties();
|
||||||
} else {
|
} else {
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
latest.messageId);
|
latest.messageId, false);
|
||||||
local = parseProperties(message);
|
local = parseProperties(message);
|
||||||
}
|
}
|
||||||
storeLocalProperties(txn, c, t, local);
|
storeLocalProperties(txn, c, t, local);
|
||||||
@@ -272,8 +272,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
remote = new TransportProperties();
|
remote = new TransportProperties();
|
||||||
} else {
|
} else {
|
||||||
// Retrieve and parse the latest remote properties
|
// Retrieve and parse the latest remote properties
|
||||||
BdfList message =
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
clientHelper.getMessageAsList(txn, latest.messageId);
|
latest.messageId, false);
|
||||||
remote = parseProperties(message);
|
remote = parseProperties(message);
|
||||||
}
|
}
|
||||||
// Merge in any discovered properties
|
// Merge in any discovered properties
|
||||||
@@ -317,7 +317,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
changed = true;
|
changed = true;
|
||||||
} else {
|
} else {
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
latest.messageId);
|
latest.messageId, false);
|
||||||
TransportProperties old = parseProperties(message);
|
TransportProperties old = parseProperties(message);
|
||||||
merged = new TransportProperties(old);
|
merged = new TransportProperties(old);
|
||||||
for (Entry<String, String> e : p.entrySet()) {
|
for (Entry<String, String> e : p.entrySet()) {
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ class TransportPropertyValidator extends BdfMessageValidator {
|
|||||||
|
|
||||||
TransportPropertyValidator(ClientHelper clientHelper,
|
TransportPropertyValidator(ClientHelper clientHelper,
|
||||||
MetadataEncoder metadataEncoder, Clock clock) {
|
MetadataEncoder metadataEncoder, Clock clock) {
|
||||||
super(clientHelper, metadataEncoder, 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ 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.PRIORITY;
|
||||||
import static org.briarproject.bramble.api.sync.RecordTypes.REQUEST;
|
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.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.MAX_SUPPORTED_VERSIONS;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
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.PRIORITY_NONCE_BYTES;
|
||||||
@@ -126,6 +127,8 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
byte[] payload = nextRecord.getPayload();
|
byte[] payload = nextRecord.getPayload();
|
||||||
if (payload.length <= MESSAGE_HEADER_LENGTH)
|
if (payload.length <= MESSAGE_HEADER_LENGTH)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
|
if (payload.length > MAX_MESSAGE_LENGTH)
|
||||||
|
throw new FormatException();
|
||||||
// Validate timestamp
|
// Validate timestamp
|
||||||
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
|
||||||
if (timestamp < 0) throw new FormatException();
|
if (timestamp < 0) throw new FormatException();
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Session parseSession(BdfDictionary meta) throws FormatException {
|
public Session parseSession(BdfDictionary meta) throws FormatException {
|
||||||
State state =
|
State state = State.fromValue(meta.getInt(SESSION_KEY_STATE));
|
||||||
State.fromValue(meta.getLong(SESSION_KEY_STATE).intValue());
|
|
||||||
|
|
||||||
MessageId lastLocalMessageId = null;
|
MessageId lastLocalMessageId = null;
|
||||||
byte[] lastLocalMessageIdBytes =
|
byte[] lastLocalMessageIdBytes =
|
||||||
@@ -56,9 +55,9 @@ class SessionParserImpl implements SessionParser {
|
|||||||
Long localTimestamp = meta.getOptionalLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
Long localTimestamp = meta.getOptionalLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
||||||
|
|
||||||
KeySetId keySetId = null;
|
KeySetId keySetId = null;
|
||||||
Long keySetIdLong = meta.getOptionalLong(SESSION_KEY_KEY_SET_ID);
|
Integer keySetIdInt = meta.getOptionalInt(SESSION_KEY_KEY_SET_ID);
|
||||||
if (keySetIdLong != null) {
|
if (keySetIdInt != null) {
|
||||||
keySetId = new KeySetId(keySetIdLong.intValue());
|
keySetId = new KeySetId(keySetIdInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Session(state, lastLocalMessageId, localKeyPair,
|
return new Session(state, lastLocalMessageId, localKeyPair,
|
||||||
|
|||||||
@@ -177,8 +177,8 @@ class TransportKeyAgreementManagerImpl extends BdfIncomingMessageHook
|
|||||||
protected DeliveryAction incomingMessage(Transaction txn, Message m,
|
protected DeliveryAction incomingMessage(Transaction txn, Message m,
|
||||||
BdfList body, BdfDictionary meta)
|
BdfList body, BdfDictionary meta)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
MessageType type = MessageType.fromValue(
|
MessageType type =
|
||||||
meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
|
MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE));
|
||||||
TransportId t = new TransportId(meta.getString(MSG_KEY_TRANSPORT_ID));
|
TransportId t = new TransportId(meta.getString(MSG_KEY_TRANSPORT_ID));
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Received " + type + " message for " + t);
|
LOG.info("Received " + type + " message for " + t);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class TransportKeyAgreementValidator extends BdfMessageValidator {
|
|||||||
@Override
|
@Override
|
||||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||||
BdfList body) throws FormatException {
|
BdfList body) throws FormatException {
|
||||||
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
|
MessageType type = MessageType.fromValue(body.getInt(0));
|
||||||
if (type == KEY) return validateKeyMessage(m.getTimestamp(), body);
|
if (type == KEY) return validateKeyMessage(m.getTimestamp(), body);
|
||||||
else if (type == ACTIVATE) return validateActivateMessage(body);
|
else if (type == ACTIVATE) return validateActivateMessage(body);
|
||||||
else throw new AssertionError();
|
else throw new AssertionError();
|
||||||
|
|||||||
@@ -301,8 +301,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
|
|||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
BdfList cv = body.getList(i);
|
BdfList cv = body.getList(i);
|
||||||
ClientId clientId = new ClientId(cv.getString(0));
|
ClientId clientId = new ClientId(cv.getString(0));
|
||||||
int majorVersion = cv.getLong(1).intValue();
|
int majorVersion = cv.getInt(1);
|
||||||
int minorVersion = cv.getLong(2).intValue();
|
int minorVersion = cv.getInt(2);
|
||||||
parsed.add(new ClientVersion(clientId, majorVersion, minorVersion));
|
parsed.add(new ClientVersion(clientId, majorVersion, minorVersion));
|
||||||
}
|
}
|
||||||
return parsed;
|
return parsed;
|
||||||
@@ -408,8 +408,8 @@ class ClientVersioningManagerImpl implements ClientVersioningManager,
|
|||||||
throws FormatException {
|
throws FormatException {
|
||||||
// Client ID, major version, minor version, active
|
// Client ID, major version, minor version, active
|
||||||
ClientId clientId = new ClientId(clientState.getString(0));
|
ClientId clientId = new ClientId(clientState.getString(0));
|
||||||
int majorVersion = clientState.getLong(1).intValue();
|
int majorVersion = clientState.getInt(1);
|
||||||
int minorVersion = clientState.getLong(2).intValue();
|
int minorVersion = clientState.getInt(2);
|
||||||
boolean active = clientState.getBoolean(3);
|
boolean active = clientState.getBoolean(3);
|
||||||
return new ClientState(clientId, majorVersion, minorVersion, active);
|
return new ClientState(clientId, majorVersion, minorVersion, active);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ class ClientVersioningValidator extends BdfMessageValidator {
|
|||||||
checkSize(clientState, 4);
|
checkSize(clientState, 4);
|
||||||
String clientId = clientState.getString(0);
|
String clientId = clientState.getString(0);
|
||||||
checkLength(clientId, 1, MAX_CLIENT_ID_LENGTH);
|
checkLength(clientId, 1, MAX_CLIENT_ID_LENGTH);
|
||||||
int majorVersion = clientState.getLong(1).intValue();
|
int majorVersion = clientState.getInt(1);
|
||||||
if (majorVersion < 0) throw new FormatException();
|
if (majorVersion < 0) throw new FormatException();
|
||||||
int minorVersion = clientState.getLong(2).intValue();
|
int minorVersion = clientState.getInt(2);
|
||||||
if (minorVersion < 0) throw new FormatException();
|
if (minorVersion < 0) throw new FormatException();
|
||||||
clientState.getBoolean(3);
|
clientState.getBoolean(3);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clock).currentTimeMillis();
|
oneOf(clock).currentTimeMillis();
|
||||||
will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE));
|
will(returnValue(timestamp - MAX_CLOCK_DIFFERENCE));
|
||||||
oneOf(clientHelper).toList(message.getBody());
|
oneOf(clientHelper).toList(message, true);
|
||||||
will(returnValue(body));
|
will(returnValue(body));
|
||||||
oneOf(metadataEncoder).encode(dictionary);
|
oneOf(metadataEncoder).encode(dictionary);
|
||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
@@ -86,7 +86,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clock).currentTimeMillis();
|
oneOf(clock).currentTimeMillis();
|
||||||
will(returnValue(timestamp));
|
will(returnValue(timestamp));
|
||||||
oneOf(clientHelper).toList(shortMessage.getBody());
|
oneOf(clientHelper).toList(shortMessage, true);
|
||||||
will(returnValue(body));
|
will(returnValue(body));
|
||||||
oneOf(metadataEncoder).encode(dictionary);
|
oneOf(metadataEncoder).encode(dictionary);
|
||||||
will(returnValue(meta));
|
will(returnValue(meta));
|
||||||
@@ -114,7 +114,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clock).currentTimeMillis();
|
oneOf(clock).currentTimeMillis();
|
||||||
will(returnValue(timestamp));
|
will(returnValue(timestamp));
|
||||||
oneOf(clientHelper).toList(message.getBody());
|
oneOf(clientHelper).toList(message, true);
|
||||||
will(throwException(new FormatException()));
|
will(throwException(new FormatException()));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(clock).currentTimeMillis();
|
oneOf(clock).currentTimeMillis();
|
||||||
will(returnValue(timestamp));
|
will(returnValue(timestamp));
|
||||||
oneOf(clientHelper).toList(message.getBody());
|
oneOf(clientHelper).toList(message, true);
|
||||||
will(returnValue(body));
|
will(returnValue(body));
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
|||||||
@@ -546,7 +546,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory)
|
oneOf(bdfReaderFactory)
|
||||||
.createReader(with(any(InputStream.class)));
|
.createReader(with(any(InputStream.class)), with(true));
|
||||||
will(returnValue(bdfReader));
|
will(returnValue(bdfReader));
|
||||||
oneOf(bdfReader).readList();
|
oneOf(bdfReader).readList();
|
||||||
will(returnValue(list));
|
will(returnValue(list));
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.data;
|
package org.briarproject.bramble.data;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -31,11 +32,14 @@ public class BdfReaderImplFuzzingTest extends BrambleTestCase {
|
|||||||
buf[1] = 0x14; // Length 20 bytes
|
buf[1] = 0x14; // Length 20 bytes
|
||||||
in.reset();
|
in.reset();
|
||||||
BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
||||||
DEFAULT_MAX_BUFFER_SIZE);
|
DEFAULT_MAX_BUFFER_SIZE, true);
|
||||||
int length = r.readString().length();
|
try {
|
||||||
assertTrue(length >= 0);
|
int length = r.readString().length();
|
||||||
assertTrue(length <= 20);
|
assertTrue(length <= 20);
|
||||||
assertTrue(r.eof());
|
assertTrue(r.eof());
|
||||||
|
} catch (FormatException e) {
|
||||||
|
// Expected when bytes are not valid UTF-8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
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.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE;
|
||||||
import static org.briarproject.bramble.data.BdfReaderImpl.DEFAULT_NESTED_LIMIT;
|
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.fromHexString;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
@@ -88,6 +89,18 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
assertTrue(r.eof());
|
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
|
@Test
|
||||||
public void testSkipLong16() throws Exception {
|
public void testSkipLong16() throws Exception {
|
||||||
setContents("22" + "0080");
|
setContents("22" + "0080");
|
||||||
@@ -106,6 +119,18 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
assertTrue(r.eof());
|
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
|
@Test
|
||||||
public void testSkipLong32() throws Exception {
|
public void testSkipLong32() throws Exception {
|
||||||
setContents("24" + "00008000");
|
setContents("24" + "00008000");
|
||||||
@@ -124,13 +149,48 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
assertTrue(r.eof());
|
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
|
@Test
|
||||||
public void testSkipLong() throws Exception {
|
public void testSkipLong64() throws Exception {
|
||||||
setContents("28" + "0000000080000000");
|
setContents("28" + "0000000080000000");
|
||||||
r.skipLong();
|
r.skipLong();
|
||||||
assertTrue(r.eof());
|
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
|
@Test
|
||||||
public void testReadDouble() throws Exception {
|
public void testReadDouble() throws Exception {
|
||||||
// http://babbage.cs.qc.edu/IEEE-754/Decimal.html
|
// http://babbage.cs.qc.edu/IEEE-754/Decimal.html
|
||||||
@@ -162,7 +222,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadString8() throws Exception {
|
public void testReadString8() throws Exception {
|
||||||
String longest = getRandomString(Byte.MAX_VALUE);
|
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
|
// "foo", the empty string, and 127 random letters
|
||||||
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
||||||
"41" + "7F" + longHex);
|
"41" + "7F" + longHex);
|
||||||
@@ -186,7 +246,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testSkipString8() throws Exception {
|
public void testSkipString8() throws Exception {
|
||||||
String longest = getRandomString(Byte.MAX_VALUE);
|
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
|
// "foo", the empty string, and 127 random letters
|
||||||
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
||||||
"41" + "7F" + longHex);
|
"41" + "7F" + longHex);
|
||||||
@@ -199,9 +259,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadString16() throws Exception {
|
public void testReadString16() throws Exception {
|
||||||
String shortest = getRandomString(Byte.MAX_VALUE + 1);
|
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 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
|
// 128 random letters and 2^15 -1 random letters
|
||||||
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
||||||
assertEquals(shortest, r.readString());
|
assertEquals(shortest, r.readString());
|
||||||
@@ -213,7 +273,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
public void testReadString16ChecksMaxLength() throws Exception {
|
public void testReadString16ChecksMaxLength() throws Exception {
|
||||||
int maxBufferSize = Byte.MAX_VALUE + 1;
|
int maxBufferSize = Byte.MAX_VALUE + 1;
|
||||||
String valid = getRandomString(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";
|
String invalidhex = validHex + "20";
|
||||||
// 128 random letters, the same plus a space
|
// 128 random letters, the same plus a space
|
||||||
setContents("42" + "0080" + validHex
|
setContents("42" + "0080" + validHex
|
||||||
@@ -223,12 +283,20 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readString();
|
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
|
@Test
|
||||||
public void testSkipString16() throws Exception {
|
public void testSkipString16() throws Exception {
|
||||||
String shortest = getRandomString(Byte.MAX_VALUE + 1);
|
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 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
|
// 128 random letters and 2^15 - 1 random letters
|
||||||
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
||||||
r.skipString();
|
r.skipString();
|
||||||
@@ -239,7 +307,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadString32() throws Exception {
|
public void testReadString32() throws Exception {
|
||||||
String shortest = getRandomString(Short.MAX_VALUE + 1);
|
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
|
// 2^15 random letters
|
||||||
setContents("44" + "00008000" + shortHex);
|
setContents("44" + "00008000" + shortHex);
|
||||||
assertEquals(shortest, r.readString());
|
assertEquals(shortest, r.readString());
|
||||||
@@ -250,7 +318,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
public void testReadString32ChecksMaxLength() throws Exception {
|
public void testReadString32ChecksMaxLength() throws Exception {
|
||||||
int maxBufferSize = Short.MAX_VALUE + 1;
|
int maxBufferSize = Short.MAX_VALUE + 1;
|
||||||
String valid = getRandomString(maxBufferSize);
|
String valid = getRandomString(maxBufferSize);
|
||||||
String validHex = toHexString(valid.getBytes("UTF-8"));
|
String validHex = toHexString(valid.getBytes(UTF_8));
|
||||||
String invalidHex = validHex + "20";
|
String invalidHex = validHex + "20";
|
||||||
// 2^15 random letters, the same plus a space
|
// 2^15 random letters, the same plus a space
|
||||||
setContents("44" + "00008000" + validHex +
|
setContents("44" + "00008000" + validHex +
|
||||||
@@ -260,10 +328,18 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readString();
|
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
|
@Test
|
||||||
public void testSkipString32() throws Exception {
|
public void testSkipString32() throws Exception {
|
||||||
String shortest = getRandomString(Short.MAX_VALUE + 1);
|
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
|
// 2^15 random letters, twice
|
||||||
setContents("44" + "00008000" + shortHex +
|
setContents("44" + "00008000" + shortHex +
|
||||||
"44" + "00008000" + shortHex);
|
"44" + "00008000" + shortHex);
|
||||||
@@ -275,7 +351,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadUtf8String() throws Exception {
|
public void testReadUtf8String() throws Exception {
|
||||||
String unicode = "\uFDD0\uFDD1\uFDD2\uFDD3";
|
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
|
// STRING_8 tag, "foo", the empty string, and the test string
|
||||||
setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "0C" + hex);
|
setContents("41" + "03" + "666F6F" + "41" + "00" + "41" + "0C" + hex);
|
||||||
assertEquals("foo", r.readString());
|
assertEquals("foo", r.readString());
|
||||||
@@ -348,6 +424,14 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readRaw();
|
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
|
@Test
|
||||||
public void testSkipRaw16() throws Exception {
|
public void testSkipRaw16() throws Exception {
|
||||||
byte[] shortest = new byte[Byte.MAX_VALUE + 1];
|
byte[] shortest = new byte[Byte.MAX_VALUE + 1];
|
||||||
@@ -385,6 +469,14 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readRaw();
|
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
|
@Test
|
||||||
public void testSkipRaw32() throws Exception {
|
public void testSkipRaw32() throws Exception {
|
||||||
byte[] shortest = new byte[Short.MAX_VALUE + 1];
|
byte[] shortest = new byte[Short.MAX_VALUE + 1];
|
||||||
@@ -434,25 +526,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readList();
|
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
|
@Test
|
||||||
public void testSkipList() throws Exception {
|
public void testSkipList() throws Exception {
|
||||||
// A list containing 1, "foo", and 128
|
// A list containing 1, "foo", and 128
|
||||||
@@ -465,9 +538,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadDictionary() throws Exception {
|
public void testReadDictionary() throws Exception {
|
||||||
// A dictionary containing "foo" -> 123 and "bar" -> null
|
// A dictionary containing "bar" -> null and "foo" -> 123
|
||||||
setContents("70" + "41" + "03" + "666F6F" + "21" + "7B" +
|
setContents("70" + "41" + "03" + "626172" + "00" +
|
||||||
"41" + "03" + "626172" + "00" + "80");
|
"41" + "03" + "666F6F" + "21" + "7B" + "80");
|
||||||
BdfDictionary dictionary = r.readDictionary();
|
BdfDictionary dictionary = r.readDictionary();
|
||||||
assertEquals(2, dictionary.size());
|
assertEquals(2, dictionary.size());
|
||||||
assertTrue(dictionary.containsKey("foo"));
|
assertTrue(dictionary.containsKey("foo"));
|
||||||
@@ -517,26 +590,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
r.readDictionary();
|
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
|
@Test
|
||||||
public void testSkipDictionary() throws Exception {
|
public void testSkipDictionary() throws Exception {
|
||||||
// A map containing "foo" -> 123 and "bar" -> null
|
// A map containing "foo" -> 123 and "bar" -> null
|
||||||
@@ -557,10 +610,10 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testNestedListWithinDepthLimit() throws Exception {
|
public void testNestedListWithinDepthLimit() throws Exception {
|
||||||
// A list containing a list containing a list containing a list...
|
// A list containing a list containing a list containing a list...
|
||||||
String lists = "";
|
StringBuilder lists = new StringBuilder();
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "60";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("60");
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists += "80";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) lists.append("80");
|
||||||
setContents(lists);
|
setContents(lists.toString());
|
||||||
r.readList();
|
r.readList();
|
||||||
assertTrue(r.eof());
|
assertTrue(r.eof());
|
||||||
}
|
}
|
||||||
@@ -568,23 +621,25 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNestedListOutsideDepthLimit() throws Exception {
|
public void testNestedListOutsideDepthLimit() throws Exception {
|
||||||
// A list containing a list containing a list containing a list...
|
// A list containing a list containing a list containing a list...
|
||||||
String lists = "";
|
StringBuilder lists = new StringBuilder();
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "60";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("60");
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists += "80";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) lists.append("80");
|
||||||
setContents(lists);
|
setContents(lists.toString());
|
||||||
r.readList();
|
r.readList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNestedDictionaryWithinDepthLimit() throws Exception {
|
public void testNestedDictionaryWithinDepthLimit() throws Exception {
|
||||||
// A dictionary containing a dictionary containing a dictionary...
|
// A dictionary containing a dictionary containing a dictionary...
|
||||||
String dicts = "";
|
StringBuilder dicts = new StringBuilder();
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++)
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) {
|
||||||
dicts += "70" + "41" + "03" + "666F6F";
|
dicts.append("70").append("41").append("03").append("666F6F");
|
||||||
dicts += "11";
|
}
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++)
|
dicts.append("11");
|
||||||
dicts += "80";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT; i++) {
|
||||||
setContents(dicts);
|
dicts.append("80");
|
||||||
|
}
|
||||||
|
setContents(dicts.toString());
|
||||||
r.readDictionary();
|
r.readDictionary();
|
||||||
assertTrue(r.eof());
|
assertTrue(r.eof());
|
||||||
}
|
}
|
||||||
@@ -592,13 +647,15 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testNestedDictionaryOutsideDepthLimit() throws Exception {
|
public void testNestedDictionaryOutsideDepthLimit() throws Exception {
|
||||||
// A dictionary containing a dictionary containing a dictionary...
|
// A dictionary containing a dictionary containing a dictionary...
|
||||||
String dicts = "";
|
StringBuilder dicts = new StringBuilder();
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++)
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) {
|
||||||
dicts += "70" + "41" + "03" + "666F6F";
|
dicts.append("70").append("41").append("03").append("666F6F");
|
||||||
dicts += "11";
|
}
|
||||||
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++)
|
dicts.append("11");
|
||||||
dicts += "80";
|
for (int i = 1; i <= DEFAULT_NESTED_LIMIT + 1; i++) {
|
||||||
setContents(dicts);
|
dicts.append("80");
|
||||||
|
}
|
||||||
|
setContents(dicts.toString());
|
||||||
r.readDictionary();
|
r.readDictionary();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,6 +682,6 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
private void setContents(String hex, int maxBufferSize)
|
private void setContents(String hex, int maxBufferSize)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(fromHexString(hex));
|
ByteArrayInputStream in = new ByteArrayInputStream(fromHexString(hex));
|
||||||
r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize);
|
r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT, maxBufferSize, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.data;
|
package org.briarproject.bramble.data;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -168,9 +169,11 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteDictionary() throws IOException {
|
public void testWriteDictionary() throws IOException {
|
||||||
// Use LinkedHashMap to get predictable iteration order
|
// Add entries to dictionary in descending order - they should be
|
||||||
|
// output in ascending order. Use LinkedHashMap to get predictable
|
||||||
|
// iteration order
|
||||||
Map<String, Object> m = new LinkedHashMap<>();
|
Map<String, Object> m = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
|
for (int i = 3; i >= 0; i--) m.put(String.valueOf(i), i);
|
||||||
w.writeDictionary(m);
|
w.writeDictionary(m);
|
||||||
// DICTIONARY tag, keys as strings and values as integers, END tag
|
// DICTIONARY tag, keys as strings and values as integers, END tag
|
||||||
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
|
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
|
||||||
@@ -180,30 +183,17 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteDelimitedList() throws IOException {
|
public void testWriteBdfDictionary() throws IOException {
|
||||||
w.writeListStart();
|
// Add entries to dictionary in descending order - they should be
|
||||||
w.writeLong(1);
|
// output in ascending order
|
||||||
w.writeString("foo");
|
BdfDictionary d = new BdfDictionary();
|
||||||
w.writeLong(128);
|
for (int i = 3; i >= 0; i--) d.put(String.valueOf(i), i);
|
||||||
w.writeListEnd();
|
w.writeDictionary(d);
|
||||||
// LIST tag, 1 as integer, "foo" as string, 128 as integer, END tag
|
// DICTIONARY tag, keys as strings and values as integers, END tag
|
||||||
checkContents("60" + "21" + "01" +
|
checkContents("70" + "41" + "01" + "30" + "21" + "00" +
|
||||||
"41" + "03" + "666F6F" +
|
"41" + "01" + "31" + "21" + "01" +
|
||||||
"22" + "0080" + "80");
|
"41" + "01" + "32" + "21" + "02" +
|
||||||
}
|
"41" + "01" + "33" + "21" + "03" + "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
|
@Test
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.mailbox;
|
package org.briarproject.bramble.mailbox;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.db.TransactionManager;
|
import org.briarproject.bramble.api.db.TransactionManager;
|
||||||
@@ -9,17 +10,23 @@ import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEven
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
import org.briarproject.bramble.test.DbExpectations;
|
||||||
|
import org.briarproject.bramble.util.Base32;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.Executor;
|
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.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
|
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.briarproject.bramble.test.TestUtils.hasEvent;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class MailboxManagerImplTest extends BrambleMockTestCase {
|
public class MailboxManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
@@ -125,4 +132,32 @@ public class MailboxManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(manager.checkConnection());
|
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"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,13 +217,13 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
// The plugin should have bound a socket and stored the port number
|
// The plugin should have bound a socket and stored the port number
|
||||||
BdfList descriptor = kal.getDescriptor();
|
BdfList descriptor = kal.getDescriptor();
|
||||||
assertEquals(3, descriptor.size());
|
assertEquals(3, descriptor.size());
|
||||||
assertEquals(TRANSPORT_ID_LAN, descriptor.getLong(0).longValue());
|
assertEquals(TRANSPORT_ID_LAN, descriptor.getInt(0).intValue());
|
||||||
byte[] address = descriptor.getRaw(1);
|
byte[] address = descriptor.getRaw(1);
|
||||||
InetAddress addr = InetAddress.getByAddress(address);
|
InetAddress addr = InetAddress.getByAddress(address);
|
||||||
assertTrue(addr instanceof Inet4Address);
|
assertTrue(addr instanceof Inet4Address);
|
||||||
assertFalse(addr.isLoopbackAddress());
|
assertFalse(addr.isLoopbackAddress());
|
||||||
assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress());
|
assertTrue(addr.isLinkLocalAddress() || addr.isSiteLocalAddress());
|
||||||
int port = descriptor.getLong(2).intValue();
|
int port = descriptor.getInt(2);
|
||||||
assertTrue(port > 0 && port < 65536);
|
assertTrue(port > 0 && port < 65536);
|
||||||
// The plugin should be listening on the port
|
// The plugin should be listening on the port
|
||||||
InetSocketAddress socketAddr = new InetSocketAddress(addr, port);
|
InetSocketAddress socketAddr = new InetSocketAddress(addr, port);
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
|
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false);
|
||||||
will(returnValue(fooUpdate));
|
will(returnValue(fooUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
fooPropertiesDict);
|
fooPropertiesDict);
|
||||||
@@ -471,7 +471,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
contactGroup2.getId());
|
contactGroup2.getId());
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
|
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId, false);
|
||||||
will(returnValue(fooUpdate));
|
will(returnValue(fooUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
fooPropertiesDict);
|
fooPropertiesDict);
|
||||||
@@ -526,7 +526,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
contactGroup.getId());
|
contactGroup.getId());
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, updateId);
|
oneOf(clientHelper).getMessageAsList(txn, updateId, false);
|
||||||
will(returnValue(update));
|
will(returnValue(update));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
fooPropertiesDict);
|
fooPropertiesDict);
|
||||||
@@ -564,7 +564,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, updateId);
|
oneOf(clientHelper).getMessageAsList(txn, updateId, false);
|
||||||
will(returnValue(update));
|
will(returnValue(update));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
fooPropertiesDict);
|
fooPropertiesDict);
|
||||||
@@ -695,7 +695,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
will(returnValue(localGroupMessageMetadata));
|
will(returnValue(localGroupMessageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
|
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId,
|
||||||
|
false);
|
||||||
will(returnValue(oldUpdate));
|
will(returnValue(oldUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
oldPropertiesDict);
|
oldPropertiesDict);
|
||||||
@@ -760,7 +761,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
will(returnValue(localGroupMessageMetadata));
|
will(returnValue(localGroupMessageMetadata));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
|
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId,
|
||||||
|
false);
|
||||||
will(returnValue(oldUpdate));
|
will(returnValue(oldUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
oldPropertiesDict);
|
oldPropertiesDict);
|
||||||
@@ -819,12 +821,12 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
|||||||
localGroup.getId());
|
localGroup.getId());
|
||||||
will(returnValue(messageMetadata));
|
will(returnValue(messageMetadata));
|
||||||
// Retrieve and parse the latest local properties
|
// Retrieve and parse the latest local properties
|
||||||
oneOf(clientHelper).getMessageAsList(txn, fooVersion999);
|
oneOf(clientHelper).getMessageAsList(txn, fooVersion999, false);
|
||||||
will(returnValue(fooUpdate));
|
will(returnValue(fooUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
fooPropertiesDict);
|
fooPropertiesDict);
|
||||||
will(returnValue(fooProperties));
|
will(returnValue(fooProperties));
|
||||||
oneOf(clientHelper).getMessageAsList(txn, barVersion3);
|
oneOf(clientHelper).getMessageAsList(txn, barVersion3, false);
|
||||||
will(returnValue(barUpdate));
|
will(returnValue(barUpdate));
|
||||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||||
barPropertiesDict);
|
barPropertiesDict);
|
||||||
|
|||||||
@@ -6,13 +6,18 @@ import org.briarproject.bramble.api.UniqueId;
|
|||||||
import org.briarproject.bramble.api.record.Record;
|
import org.briarproject.bramble.api.record.Record;
|
||||||
import org.briarproject.bramble.api.record.RecordReader;
|
import org.briarproject.bramble.api.record.RecordReader;
|
||||||
import org.briarproject.bramble.api.sync.Ack;
|
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.MessageFactory;
|
||||||
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.Offer;
|
import org.briarproject.bramble.api.sync.Offer;
|
||||||
import org.briarproject.bramble.api.sync.Priority;
|
import org.briarproject.bramble.api.sync.Priority;
|
||||||
import org.briarproject.bramble.api.sync.Request;
|
import org.briarproject.bramble.api.sync.Request;
|
||||||
import org.briarproject.bramble.api.sync.SyncRecordReader;
|
import org.briarproject.bramble.api.sync.SyncRecordReader;
|
||||||
import org.briarproject.bramble.api.sync.Versions;
|
import org.briarproject.bramble.api.sync.Versions;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.briarproject.bramble.test.PredicateMatcher;
|
||||||
|
import org.hamcrest.Matcher;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -23,12 +28,15 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
|
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.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.OFFER;
|
||||||
import static org.briarproject.bramble.api.sync.RecordTypes.PRIORITY;
|
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.REQUEST;
|
||||||
import static org.briarproject.bramble.api.sync.RecordTypes.VERSIONS;
|
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_MESSAGE_IDS;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_SUPPORTED_VERSIONS;
|
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.PRIORITY_NONCE_BYTES;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.sync.SyncConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
@@ -46,6 +54,38 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
|
|||||||
private final SyncRecordReader reader =
|
private final SyncRecordReader reader =
|
||||||
new SyncRecordReaderImpl(messageFactory, recordReader);
|
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
|
@Test
|
||||||
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
|
public void testNoFormatExceptionIfAckIsMaximumSize() throws Exception {
|
||||||
expectReadRecord(createAck());
|
expectReadRecord(createAck());
|
||||||
@@ -158,6 +198,20 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
|
|||||||
assertTrue(reader.eof());
|
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 {
|
private void expectReadRecord(@Nullable Record record) throws Exception {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
@@ -167,6 +221,10 @@ public class SyncRecordReaderImplTest extends BrambleMockTestCase {
|
|||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Record createMessage(int payloadLength) {
|
||||||
|
return new Record(PROTOCOL_VERSION, MESSAGE, new byte[payloadLength]);
|
||||||
|
}
|
||||||
|
|
||||||
private Record createAck() throws Exception {
|
private Record createAck() throws Exception {
|
||||||
return new Record(PROTOCOL_VERSION, ACK, createPayload());
|
return new Record(PROTOCOL_VERSION, ACK, createPayload());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,51 +88,58 @@ public class StringUtilsTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8() {
|
public void testFromUtf8AcceptsNullCharacterUsingStandardUtf8()
|
||||||
|
throws Exception {
|
||||||
// The UTF-8 encoding of the null character is valid
|
// The UTF-8 encoding of the null character is valid
|
||||||
assertEquals("\u0000", StringUtils.fromUtf8(new byte[1]));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = FormatException.class)
|
||||||
public void testFromUtf8RemovesNullCharacterUsingModifiedUtf8() {
|
public void testFromUtf8RejectsNullCharacterUsingModifiedUtf8()
|
||||||
|
throws Exception {
|
||||||
// The modified UTF-8 encoding of the null character is not valid
|
// The modified UTF-8 encoding of the null character is not valid
|
||||||
byte[] b = new byte[] {
|
byte[] b = new byte[] {
|
||||||
(byte) 0xC0, (byte) 0x80, // Null character as modified UTF-8
|
(byte) 0xC0, (byte) 0x80, // Null character as modified UTF-8
|
||||||
(byte) 0xC8, (byte) 0x85 // U+0205
|
(byte) 0xC8, (byte) 0x85 // U+0205
|
||||||
};
|
};
|
||||||
// Conversion should ignore the invalid character and return the rest
|
StringUtils.fromUtf8(b);
|
||||||
String expected = "\u0205";
|
|
||||||
assertEquals(expected, StringUtils.fromUtf8(b));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8() {
|
public void testFromUtf8AcceptsSupplementaryCharacterUsingStandardUtf8()
|
||||||
|
throws Exception {
|
||||||
// The UTF-8 encoding of a supplementary character is valid and should
|
// The UTF-8 encoding of a supplementary character is valid and should
|
||||||
// be converted to a surrogate pair
|
// be converted to a surrogate pair
|
||||||
byte[] b = new byte[] {
|
byte[] utf8 = new byte[] {
|
||||||
(byte) 0xF0, (byte) 0x90, (byte) 0x90, (byte) 0x80, // U+10400
|
(byte) 0xF0, (byte) 0x90, (byte) 0x90, (byte) 0x80, // U+10400
|
||||||
(byte) 0xC8, (byte) 0x85 // U+0205
|
(byte) 0xC8, (byte) 0x85 // U+0205
|
||||||
};
|
};
|
||||||
String expected = "\uD801\uDC00\u0205"; // Surrogate pair
|
String expected = "\uD801\uDC00\u0205"; // Surrogate pair
|
||||||
assertEquals(expected, StringUtils.fromUtf8(b));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test(expected = FormatException.class)
|
||||||
public void testFromUtf8RemovesSupplementaryCharacterUsingModifiedUtf8() {
|
public void testFromUtf8RejectsSupplementaryCharacterUsingModifiedUtf8()
|
||||||
|
throws Exception {
|
||||||
// The CESU-8 or modified UTF-8 encoding of a supplementary character
|
// The CESU-8 or modified UTF-8 encoding of a supplementary character
|
||||||
// is not valid
|
// is not valid
|
||||||
byte[] b = new byte[] {
|
byte[] utf8 = new byte[] {
|
||||||
(byte) 0xED, (byte) 0xA0, (byte) 0x81, // U+10400 as CSEU-8
|
(byte) 0xED, (byte) 0xA0, (byte) 0x81, // U+10400 as CSEU-8
|
||||||
(byte) 0xED, (byte) 0xB0, (byte) 0x80,
|
(byte) 0xED, (byte) 0xB0, (byte) 0x80,
|
||||||
(byte) 0xC8, (byte) 0x85 // U+0205
|
(byte) 0xC8, (byte) 0x85 // U+0205
|
||||||
};
|
};
|
||||||
// Conversion should ignore the invalid character and return the rest
|
StringUtils.fromUtf8(utf8);
|
||||||
String expected = "\u0205";
|
|
||||||
assertEquals(expected, StringUtils.fromUtf8(b));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromUtf8EmptyInput() {
|
public void testFromUtf8EmptyInput() throws Exception {
|
||||||
assertEquals("", StringUtils.fromUtf8(new byte[0]));
|
assertEquals("", StringUtils.fromUtf8(new byte[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 10420
|
versionCode 10422
|
||||||
versionName "1.4.20"
|
versionName "1.4.22"
|
||||||
applicationId "org.briarproject.briar.android"
|
applicationId "org.briarproject.briar.android"
|
||||||
buildConfigField "String", "TorVersion", "\"$tor_version\""
|
buildConfigField "String", "TorVersion", "\"$tor_version\""
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,25 @@ import android.os.Bundle;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.activity.BriarActivity;
|
import org.briarproject.briar.android.activity.BriarActivity;
|
||||||
|
import org.briarproject.briar.android.blog.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.BaseFragment.BaseFragmentListener;
|
||||||
|
import org.briarproject.briar.android.fragment.ErrorFragment;
|
||||||
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import static androidx.fragment.app.FragmentManager.POP_BACK_STACK_INCLUSIVE;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class RssFeedActivity extends BriarActivity
|
public class RssFeedActivity extends BriarActivity
|
||||||
@@ -45,21 +54,29 @@ public class RssFeedActivity extends BriarActivity
|
|||||||
viewModel.getImportResult().observeEvent(this, this::onImportResult);
|
viewModel.getImportResult().observeEvent(this, this::onImportResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onImportResult(boolean result) {
|
private void onImportResult(@Nullable RssImportResult result) {
|
||||||
if (result) {
|
FragmentManager fm = getSupportFragmentManager();
|
||||||
FragmentManager fm = getSupportFragmentManager();
|
if (result instanceof UrlImportSuccess) {
|
||||||
if (fm.findFragmentByTag(RssFeedImportFragment.TAG) != null) {
|
if (fm.findFragmentByTag(RssFeedImportFragment.TAG) != null) {
|
||||||
onBackPressed();
|
onBackPressed();
|
||||||
}
|
}
|
||||||
} else {
|
} else if (result instanceof UrlImportError) {
|
||||||
String url = viewModel.getUrlFailedImport();
|
String url = ((UrlImportError) result).url;
|
||||||
if (url == null) {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
RssFeedImportFailedDialogFragment dialog =
|
RssFeedImportFailedDialogFragment dialog =
|
||||||
RssFeedImportFailedDialogFragment.newInstance(url);
|
RssFeedImportFailedDialogFragment.newInstance(url);
|
||||||
dialog.show(getSupportFragmentManager(),
|
dialog.show(fm, RssFeedImportFailedDialogFragment.TAG);
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -13,18 +17,27 @@ import android.widget.ProgressBar;
|
|||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
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.MethodsNotNullByDefault;
|
||||||
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.nullsafety.ParametersNotNullByDefault;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
|
import androidx.annotation.RequiresApi;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
|
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.hideSoftKeyboard;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.launchActivityToOpenFile;
|
||||||
|
import static org.briarproject.briar.android.util.UiUtils.showFragment;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -39,6 +52,15 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
private Button importButton;
|
private Button importButton;
|
||||||
private ProgressBar progressBar;
|
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
|
@Override
|
||||||
public void injectFragment(ActivityComponent component) {
|
public void injectFragment(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
@@ -52,6 +74,7 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
@Nullable ViewGroup container,
|
@Nullable ViewGroup container,
|
||||||
@Nullable Bundle savedInstanceState) {
|
@Nullable Bundle savedInstanceState) {
|
||||||
requireActivity().setTitle(getString(R.string.blogs_rss_feeds_import));
|
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,
|
View v = inflater.inflate(R.layout.fragment_rss_feed_import,
|
||||||
container, false);
|
container, false);
|
||||||
|
|
||||||
@@ -92,11 +115,40 @@ public class RssFeedImportFragment extends BaseFragment {
|
|||||||
return v;
|
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
|
@Override
|
||||||
public String getUniqueTag() {
|
public String getUniqueTag() {
|
||||||
return TAG;
|
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() {
|
private void enableOrDisableImportButton() {
|
||||||
String url = urlInput.getText().toString();
|
String url = urlInput.getText().toString();
|
||||||
importButton.setEnabled(viewModel.validateAndNormaliseUrl(url) != null);
|
importButton.setEnabled(viewModel.validateAndNormaliseUrl(url) != null);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.briarproject.briar.android.blog;
|
package org.briarproject.briar.android.blog;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.net.Uri;
|
||||||
import android.util.Patterns;
|
import android.util.Patterns;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
@@ -11,6 +13,10 @@ import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
|||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
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.DbViewModel;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||||
import org.briarproject.briar.android.viewmodel.LiveResult;
|
import org.briarproject.briar.android.viewmodel.LiveResult;
|
||||||
@@ -20,6 +26,7 @@ import org.briarproject.briar.api.feed.FeedManager;
|
|||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -30,6 +37,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.UiThread;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
@@ -52,11 +60,9 @@ class RssFeedViewModel extends DbViewModel {
|
|||||||
private final MutableLiveData<LiveResult<List<Feed>>> feeds =
|
private final MutableLiveData<LiveResult<List<Feed>>> feeds =
|
||||||
new MutableLiveData<>();
|
new MutableLiveData<>();
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private volatile String urlFailedImport = null;
|
|
||||||
private final MutableLiveData<Boolean> isImporting =
|
private final MutableLiveData<Boolean> isImporting =
|
||||||
new MutableLiveData<>(false);
|
new MutableLiveData<>(false);
|
||||||
private final MutableLiveEvent<Boolean> importResult =
|
private final MutableLiveEvent<RssImportResult> importResult =
|
||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -120,7 +126,7 @@ class RssFeedViewModel extends DbViewModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
LiveEvent<Boolean> getImportResult() {
|
LiveEvent<RssImportResult> getImportResult() {
|
||||||
return importResult;
|
return importResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +136,6 @@ class RssFeedViewModel extends DbViewModel {
|
|||||||
|
|
||||||
void importFeed(String url) {
|
void importFeed(String url) {
|
||||||
isImporting.setValue(true);
|
isImporting.setValue(true);
|
||||||
urlFailedImport = null;
|
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
Feed feed = feedManager.addFeed(url);
|
Feed feed = feedManager.addFeed(url);
|
||||||
@@ -145,19 +150,38 @@ class RssFeedViewModel extends DbViewModel {
|
|||||||
updated = feedList;
|
updated = feedList;
|
||||||
}
|
}
|
||||||
feeds.postValue(new LiveResult<>(updated));
|
feeds.postValue(new LiveResult<>(updated));
|
||||||
importResult.postEvent(true);
|
importResult.postEvent(new UrlImportSuccess());
|
||||||
} catch (DbException | IOException e) {
|
} catch (DbException | IOException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
urlFailedImport = url;
|
importResult.postEvent(new UrlImportError(url));
|
||||||
importResult.postEvent(false);
|
|
||||||
} finally {
|
} finally {
|
||||||
isImporting.postValue(false);
|
isImporting.postValue(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@UiThread
|
||||||
String getUrlFailedImport() {
|
void importFeed(Uri uri) {
|
||||||
return urlFailedImport;
|
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());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
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 {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -145,19 +145,7 @@ public class MailboxStatusFragment extends Fragment {
|
|||||||
@DrawableRes int iconRes;
|
@DrawableRes int iconRes;
|
||||||
String title;
|
String title;
|
||||||
String message = null;
|
String message = null;
|
||||||
if (status.hasProblem(System.currentTimeMillis())) {
|
if (status.getMailboxCompatibility() < 0) {
|
||||||
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;
|
tintRes = R.color.briar_red_500;
|
||||||
if (status.getMailboxCompatibility() == API_CLIENT_TOO_OLD) {
|
if (status.getMailboxCompatibility() == API_CLIENT_TOO_OLD) {
|
||||||
title = getString(R.string.mailbox_status_app_too_old_title);
|
title = getString(R.string.mailbox_status_app_too_old_title);
|
||||||
@@ -172,6 +160,18 @@ public class MailboxStatusFragment extends Fragment {
|
|||||||
iconRes = R.drawable.alerts_and_states_error;
|
iconRes = R.drawable.alerts_and_states_error;
|
||||||
showUnlinkWarning = true;
|
showUnlinkWarning = true;
|
||||||
wizardButton.setVisibility(GONE);
|
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 {
|
} else {
|
||||||
iconRes = R.drawable.ic_check_circle_outline;
|
iconRes = R.drawable.ic_check_circle_outline;
|
||||||
title = getString(R.string.mailbox_status_connected_title);
|
title = getString(R.string.mailbox_status_connected_title);
|
||||||
|
|||||||
43
briar-android/src/main/res/layout/fragment_progress.xml
Normal file
43
briar-android/src/main/res/layout/fragment_progress.xml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?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>
|
||||||
12
briar-android/src/main/res/menu/rss_feed_import_actions.xml
Normal file
12
briar-android/src/main/res/menu/rss_feed_import_actions.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?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>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
<string name="bt_plugin_status_disabled">Briar е настроен да не използва Bluetooth</string>
|
<string name="bt_plugin_status_disabled">Briar е настроен да не използва Bluetooth</string>
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="reminder_notification_title">Отписани сте от Briar</string>
|
<string name="reminder_notification_title">Отписани сте от Briar</string>
|
||||||
<string name="reminder_notification_text">Докоснете за повторно влизане.</string>
|
<string name="reminder_notification_text">За да влезете, докоснете</string>
|
||||||
<string name="reminder_notification_channel_title">Напомняне за вход в Briar</string>
|
<string name="reminder_notification_channel_title">Напомняне за вход в Briar</string>
|
||||||
<string name="reminder_notification_dismiss">Отказ</string>
|
<string name="reminder_notification_dismiss">Отказ</string>
|
||||||
<string name="ongoing_notification_title">Вписани в Briar</string>
|
<string name="ongoing_notification_title">Вписани в Briar</string>
|
||||||
@@ -235,6 +235,8 @@
|
|||||||
<string name="qr_code_invalid">Кодът за QR е недействителен</string>
|
<string name="qr_code_invalid">Кодът за QR е недействителен</string>
|
||||||
<string name="qr_code_too_old_1">Сканираният код за QR е от по-ранно издание на Briar.\n\nНека вашия контакт инсталира последното издание и да пробва отново.</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="qr_code_too_new_1">Сканираният код за QR е от по-ново издание на Briar.\n\nИнсталирайте последното издание и пробвайте отново.</string>
|
||||||
|
<string name="mailbox_qr_code_for_contact">Сканираният код за QR е от Briar Пощенска кутия.\n\nАко искате да свържете Пощенска кутия използвайте Настройки > Пощенска кутия от менюто.</string>
|
||||||
|
<string name="qr_code_format_unknown">Сканираният код за QR не предназначен за добавяне на контакт в Briar.\n\nЗа тази цел използвайте кода, на екрана на контакта ви.</string>
|
||||||
<string name="camera_error">Грешка в камерата</string>
|
<string name="camera_error">Грешка в камерата</string>
|
||||||
<string name="connecting_to_device">Свързване с устройство\u2026</string>
|
<string name="connecting_to_device">Свързване с устройство\u2026</string>
|
||||||
<string name="authenticating_with_device">Удостоверяване с устройство\u2026</string>
|
<string name="authenticating_with_device">Удостоверяване с устройство\u2026</string>
|
||||||
@@ -480,7 +482,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Внасяне</string>
|
<string name="blogs_rss_feeds_import_button">Внасяне</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Aдрес на емисия</string>
|
<string name="blogs_rss_feeds_import_hint">Aдрес на емисия</string>
|
||||||
<string name="blogs_rss_feeds_import_error">Грешка при внасяне на емисията.</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">Емисии на RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Внесена:</string>
|
<string name="blogs_rss_feeds_manage_imported">Внесена:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
||||||
@@ -591,7 +592,9 @@
|
|||||||
<string name="mailbox_setup_download_link">Споделяне на препратка за изтегляне</string>
|
<string name="mailbox_setup_download_link">Споделяне на препратка за изтегляне</string>
|
||||||
<string name="mailbox_setup_button_scan">Сканиране на кода за QR на пощенска кутия</string>
|
<string name="mailbox_setup_button_scan">Сканиране на кода за QR на пощенска кутия</string>
|
||||||
<string name="permission_camera_qr_denied_body">Отказахте достъп до камерата, но достъп е необходим за сканиране на кодове за QR.\n\nОбмислете дали да не дадете разрешение.</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".-->
|
<!--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_title">Пощенската кутия е вече свързана</string>
|
||||||
<string name="mailbox_setup_already_paired_description">Прекъснете връзката с пощенската кутия от другото устройство и опитайте отново.</string>
|
<string name="mailbox_setup_already_paired_description">Прекъснете връзката с пощенската кутия от другото устройство и опитайте отново.</string>
|
||||||
<string name="mailbox_setup_io_error_title">Грешка при свързване</string>
|
<string name="mailbox_setup_io_error_title">Грешка при свързване</string>
|
||||||
|
|||||||
@@ -489,7 +489,6 @@ 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_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_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_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">Canals RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
|
|||||||
@@ -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_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="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="delete_account_button">Konto löschen</string>
|
||||||
<string name="startup_open_database">Datenbank wird entschlüsselt...</string>
|
<string name="startup_open_database">Datenbank wird entschlüsselt…</string>
|
||||||
<string name="startup_migrate_database">Datenbank wird aktualisiert...</string>
|
<string name="startup_migrate_database">Datenbank wird aktualisiert…</string>
|
||||||
<string name="startup_compact_database">Datenbank wird komprimiert…</string>
|
<string name="startup_compact_database">Datenbank wird komprimiert…</string>
|
||||||
<!--Navigation Drawer-->
|
<!--Navigation Drawer-->
|
||||||
<string name="nav_drawer_open_description">Navigationsleiste öffnen</string>
|
<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_snackbar">Es gibt ausstehende Kontaktanfragen</string>
|
||||||
<string name="pending_contact_requests">Ausstehende Kontaktanfragen</string>
|
<string name="pending_contact_requests">Ausstehende Kontaktanfragen</string>
|
||||||
<string name="no_pending_contacts">Keine ausstehenden Kontakte</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="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="adding_contact_failed">Hinzufügen von Kontakt ist fehlgeschlagen</string>
|
||||||
<string name="dialog_title_remove_pending_contact">Entfernung bestätigen</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>
|
<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,8 +487,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">RSS-Feed importieren</string>
|
<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_button">Importieren</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">URL des RSS-Feeds eingeben</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_error">Es tut uns Leid! Es gab einen Fehler beim Importieren deines Feeds.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Dieser Feed ist bereits importiert.</string>
|
<string name="blogs_rss_feeds_import_title">Feed aus Datei importieren</string>
|
||||||
<string name="blogs_rss_feeds">RSS-Feeds</string>
|
<string name="blogs_rss_feeds">RSS-Feeds</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importiert:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importiert:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
@@ -729,7 +730,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_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>
|
<string name="dev_report_error">Fehler: Senden des Reports fehlgeschlagen</string>
|
||||||
<!--Sign Out-->
|
<!--Sign Out-->
|
||||||
<string name="progress_title_logout">Von Briar abmelden...</string>
|
<string name="progress_title_logout">Von Briar abmelden…</string>
|
||||||
<!--Screen Filters & Tapjacking-->
|
<!--Screen Filters & Tapjacking-->
|
||||||
<string name="screen_filter_title">Bildschirmüberlagerung erkannt</string>
|
<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>
|
<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>
|
||||||
|
|||||||
@@ -495,7 +495,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Importar</string>
|
<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_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_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">Canales RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
|
|||||||
@@ -510,7 +510,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">وارد کردن</string>
|
<string name="blogs_rss_feeds_import_button">وارد کردن</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">آدرس خوراک RSS را وارد کنید</string>
|
<string name="blogs_rss_feeds_import_hint">آدرس خوراک RSS را وارد کنید</string>
|
||||||
<string name="blogs_rss_feeds_import_error">متاسفیم! وارد کردن خوراک شما با خطا مواجه شده است.</string>
|
<string name="blogs_rss_feeds_import_error">متاسفیم! وارد کردن خوراک شما با خطا مواجه شده است.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">این خوراک وارد شده است.</string>
|
|
||||||
<string name="blogs_rss_feeds">خوراک های RSS</string>
|
<string name="blogs_rss_feeds">خوراک های RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">وارد شده:</string>
|
<string name="blogs_rss_feeds_manage_imported">وارد شده:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">نویسنده:</string>
|
<string name="blogs_rss_feeds_manage_author">نویسنده:</string>
|
||||||
|
|||||||
@@ -482,7 +482,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Importer</string>
|
<string name="blogs_rss_feeds_import_button">Importer</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Saisir l’URL du fil RSS</string>
|
<string name="blogs_rss_feeds_import_hint">Saisir l’URL du fil RSS</string>
|
||||||
<string name="blogs_rss_feeds_import_error">Nous sommes désolés ! Une erreur est survenue lors de l’importation de votre fil.</string>
|
<string name="blogs_rss_feeds_import_error">Nous sommes désolés ! Une erreur est survenue lors de l’importation 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">Fils RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importés :</string>
|
<string name="blogs_rss_feeds_manage_imported">Importés :</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Auteur :</string>
|
<string name="blogs_rss_feeds_manage_author">Auteur :</string>
|
||||||
|
|||||||
@@ -466,7 +466,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Flytja inn</string>
|
<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_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_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">RSS-fréttastreymi</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Flutt inn:</string>
|
<string name="blogs_rss_feeds_manage_imported">Flutt inn:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Höfundur:</string>
|
<string name="blogs_rss_feeds_manage_author">Höfundur:</string>
|
||||||
|
|||||||
@@ -501,8 +501,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Importa RSS Feed</string>
|
<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_button">Importa</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Inserire l\'URL dell\'RSS feed</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_error">Ci dispiace! C\'è stato un errore nell\'importazione del tuo feed.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Quel flusso è già importato.</string>
|
<string name="blogs_rss_feeds_import_title">Importa feed da file</string>
|
||||||
<string name="blogs_rss_feeds">Flussi RSS</string>
|
<string name="blogs_rss_feeds">Flussi RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importato:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importato:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autore:</string>
|
<string name="blogs_rss_feeds_manage_author">Autore:</string>
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!--Setup-->
|
<!--Setup-->
|
||||||
<string name="setup_title">Briar へようこそ</string>
|
<string name="setup_title">Briarへようこそ</string>
|
||||||
<string name="setup_name_explanation">あなたのニックネームは、常に、あなたが投稿するコンテンツとともに表示されます。プロフィール作成後、編集はできません。</string>
|
<string name="setup_name_explanation">あなたのニックネームは、常に、あなたが投稿するコンテンツとともに表示されます。プロフィール作成後、編集はできません。</string>
|
||||||
<string name="setup_next">次へ</string>
|
<string name="setup_next">次へ</string>
|
||||||
<string name="setup_password_intro">パスワードを選択</string>
|
<string name="setup_password_intro">パスワードを選択</string>
|
||||||
<string name="setup_password_explanation">Briar のアカウント情報はクラウドではなく、暗号化された端末に保存されます。アプリのアンインストールやパスワードを紛失した場合、アカウントへのアクセスとデータを回復する手段はありません。\n\n推測するのが難しい、長いパスワードを設定してください。ランダムな4単語やランダムな10文字と数字と記号を組み合わせたものなどです。</string>
|
<string name="setup_password_explanation">Briarのアカウント情報はクラウドではなく、暗号化された端末に保存されます。アプリのアンインストールやパスワードを紛失した場合、アカウントへのアクセスとデータを回復する手段はありません。\n\n推測するのが難しい、長いパスワードを設定してください。ランダムな4単語やランダムな10文字と数字と記号を組み合わせたものなどです。</string>
|
||||||
<string name="dnkm_doze_intro">メッセージを受信するために、Briar はバックグラウンドで接続を維持する必要があります。</string>
|
<string name="dnkm_doze_intro">メッセージを受信するために、Briarはバックグラウンドで接続を維持する必要があります。</string>
|
||||||
<string name="dnkm_doze_explanation">メッセージを受信するために、Briar はバックグラウンドで接続を維持する必要があります。 Briar が接続を維持できるように、バッテリーの最適化を無効にしてください。</string>
|
<string name="dnkm_doze_explanation">メッセージを受信するために、Briarはバックグラウンドで接続を維持する必要があります。 Briarが接続を維持できるように、バッテリーの最適化を無効にしてください。</string>
|
||||||
<string name="choose_nickname">ニックネームを入力</string>
|
<string name="choose_nickname">ニックネームを入力</string>
|
||||||
<string name="choose_password">パスワードを入力</string>
|
<string name="choose_password">パスワードを入力</string>
|
||||||
<string name="confirm_password">確認のため再度パスワードを入力</string>
|
<string name="confirm_password">確認のため再度パスワードを入力</string>
|
||||||
@@ -17,42 +17,42 @@
|
|||||||
<string name="create_account_button">アカウントを作成</string>
|
<string name="create_account_button">アカウントを作成</string>
|
||||||
<string name="more_info">詳細情報</string>
|
<string name="more_info">詳細情報</string>
|
||||||
<string name="don_t_ask_again">次からは尋ねない</string>
|
<string name="don_t_ask_again">次からは尋ねない</string>
|
||||||
<string name="dnkm_huawei_protected_text">下のボタンをタップして、「保護されたアプリ」画面で Briar が保護されていることを確認してください。</string>
|
<string name="dnkm_huawei_protected_text">下のボタンをタップして、「保護されたアプリ」画面で Briarが保護されていることを確認してください。</string>
|
||||||
<string name="dnkm_huawei_protected_button">Briar を保護する</string>
|
<string name="dnkm_huawei_protected_button">Briarを保護する</string>
|
||||||
<string name="dnkm_huawei_protected_help">Briar が保護されたアプリのリストに追加されていないと、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_text">下のボタンをタップして「アプリの起動」画面を開き、Briarが「手動で管理する」に設定されていることを確認してください。</string>
|
||||||
<string name="dnkm_huawei_app_launch_help">「アプリ起動」画面で Briar を「手動で管理する」に設定していないと、バックグラウンドで動作させることができません。</string>
|
<string name="dnkm_huawei_app_launch_help">「アプリ起動」画面で Briarを「手動で管理する」に設定していないと、バックグラウンドで動作させることができません。</string>
|
||||||
<string name="dnkm_xiaomi_text">バックグラウンドで実行するには、Briar を最近のアプリのリストにロックする必要があります。</string>
|
<string name="dnkm_xiaomi_text">バックグラウンドで実行するには、Briarを最近のアプリのリストにロックする必要があります。</string>
|
||||||
<string name="dnkm_xiaomi_button">Briar を保護する</string>
|
<string name="dnkm_xiaomi_button">Briarを保護する</string>
|
||||||
<string name="dnkm_xiaomi_help">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_xiaomi_dialog_body_old">1. 最近使ったアプリのリスト(アプリスイッチャーともいう)を開いて下さい。\n\n2. Briarの画像を下にスワイプすると、南京錠のアイコンが表示されます。\n\n3. ロックされていない場合は、タップしてロックします。</string>
|
||||||
<string name="dnkm_warning_dozed_1">Briarはバックグラウンドで実行することができませんでした</string>
|
<string name="dnkm_warning_dozed_1">Briarはバックグラウンドで実行できませんでした</string>
|
||||||
<!--Login-->
|
<!--Login-->
|
||||||
<string name="enter_password">パスワード</string>
|
<string name="enter_password">パスワード</string>
|
||||||
<string name="try_again">パスワードが間違っています。もう一度入力してください。</string>
|
<string name="try_again">パスワードが間違っています。もう一度入力してください。</string>
|
||||||
<string name="dialog_title_cannot_check_password">パスワードを確認できません</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="sign_in_button">サインイン</string>
|
||||||
<string name="forgotten_password">パスワードを忘れました</string>
|
<string name="forgotten_password">パスワードを忘れました</string>
|
||||||
<string name="dialog_title_lost_password">パスワードを紛失</string>
|
<string name="dialog_title_lost_password">パスワードを紛失</string>
|
||||||
<string name="dialog_message_lost_password">Briar アカウントはクラウド上ではなく、暗号化さた上であなたの端末に保存さています。したがって、Briar はパスワードをリセットできません。アカウントを削除して、はじめからやり直しますか?\n\n注意:あなたのID、連絡先、メッセージは永久に失われます。</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_activity_title">Briarの起動に失敗</string>
|
||||||
<string name="startup_failed_clock_error">お使いの端末の時計が正しくないため、Briar は起動できませんでした。\n\n端末の時計を正しい時刻に設定してから、もう一度試してください。</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_db_error">Briarは、あなたのアカウント、連絡先、メッセージを含むデータベースを開くことができませんでした。\n\nアプリを最新版にアップグレードしてもう一度お試しいただくか、パスワード入力画面で「パスワードを忘れました」を選択して新しいアカウントを設定してください。</string>
|
||||||
<string name="startup_failed_data_too_old_error">あなたのアカウントは古いバージョンのアプリで作成されたもので、このバージョンでは開くことができません。\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_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">
|
<plurals name="expiry_warning">
|
||||||
<item quantity="other">これは、Briar のテストバージョンです。 アカウントはあと%d日で期限切れになり、更新できません。</item>
|
<item quantity="other">これは、Briarのテストバージョンです。 アカウントはあと%d日で期限切れになり、更新できません。</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<plurals name="old_android_expiry_warning">
|
<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>
|
</plurals>
|
||||||
<string name="expiry_date_reached">このソフトウェアの有効期限が切れました。テストに参加してくださりありがとうございます!</string>
|
<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="create_new_account">新しいアカウントを作成する必要があります。同じニックネームも使用できます。</string>
|
||||||
<string name="download_briar_button">最新リリースをダウンロード</string>
|
<string name="download_briar_button">最新リリースをダウンロード</string>
|
||||||
<string name="old_android_expiry_date_reached">Briar は Android 4 では動作しなくなりました。\n新しい端末にBriarをインストールしてください。</string>
|
<string name="old_android_expiry_date_reached">BriarはAndroid 4では動作しなくなりました。\n新しい端末にBriarをインストールしてください。</string>
|
||||||
<string name="old_android_delete_account">下のボタンをタップして、この端末からあなたのアカウントを削除できます。</string>
|
<string name="old_android_delete_account">下のボタンをタップして、この端末からあなたのアカウントを削除できます。</string>
|
||||||
<string name="delete_account_button">アカウントを削除</string>
|
<string name="delete_account_button">アカウントを削除</string>
|
||||||
<string name="startup_open_database">データベースの復号化中…</string>
|
<string name="startup_open_database">データベースの復号化中…</string>
|
||||||
@@ -69,36 +69,36 @@
|
|||||||
<string name="lock_button">アプリをロック</string>
|
<string name="lock_button">アプリをロック</string>
|
||||||
<string name="settings_button">設定</string>
|
<string name="settings_button">設定</string>
|
||||||
<string name="sign_out_button">サインアウト</string>
|
<string name="sign_out_button">サインアウト</string>
|
||||||
<string name="transports_onboarding_text">ここにタップすると、Briar があなたの連絡先に接続する方法を制御できます。</string>
|
<string name="transports_onboarding_text">ここにタップすると、Briarがあなたの連絡先に接続する方法を制御できます。</string>
|
||||||
<!--Transports: Tor-->
|
<!--Transports: Tor-->
|
||||||
<string name="transport_tor">インターネット</string>
|
<string name="transport_tor">インターネット</string>
|
||||||
<string name="tor_device_status_online_wifi">電話機はWi-Fiでインターネットにアクセスできます</string>
|
<string name="tor_device_status_online_wifi">電話機はWi-Fiでインターネットにアクセスできます</string>
|
||||||
<string name="tor_device_status_online_mobile">電話機はモバイル データでインターネットにアクセスできます</string>
|
<string name="tor_device_status_online_mobile">電話機はモバイル データでインターネットにアクセスできます</string>
|
||||||
<string name="tor_device_status_offline">電話機がインターネットに接続できません</string>
|
<string name="tor_device_status_offline">電話機がインターネットに接続できません</string>
|
||||||
<string name="tor_plugin_status_enabling">Briar はインターネットに接続中です…</string>
|
<string name="tor_plugin_status_enabling">Briarはインターネットに接続中です…</string>
|
||||||
<string name="tor_plugin_status_active">Briar はインターネットに接続されました</string>
|
<string name="tor_plugin_status_active">Briarはインターネットに接続されました</string>
|
||||||
<string name="tor_plugin_status_inactive">Briar はインターネットに接続できません</string>
|
<string name="tor_plugin_status_inactive">Briarはインターネットに接続できません</string>
|
||||||
<string name="tor_plugin_status_disabled">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_mobile_data">Briarはモバイルデータを使用しないように設定されています</string>
|
||||||
<string name="tor_plugin_status_disabled_battery">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_disabled_country_blocked">Briarはこの国でインターネットを使わないように設定されています</string>
|
||||||
<!--Transports: Wi-Fi-->
|
<!--Transports: Wi-Fi-->
|
||||||
<string name="transport_lan">Wi-Fi</string>
|
<string name="transport_lan">Wi-Fi</string>
|
||||||
<string name="transport_lan_long">同じ 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_on">電話機は Wi-Fi に接続されました</string>
|
||||||
<string name="lan_device_status_off">電話機はWi-Fiに接続されていません</string>
|
<string name="lan_device_status_off">電話機はWi-Fiに接続されていません</string>
|
||||||
<string name="lan_plugin_status_enabling">Briar は Wi-Fi ネットワークに接続中です…</string>
|
<string name="lan_plugin_status_enabling">BriarはWi-Fiネットワークに接続中です…</string>
|
||||||
<string name="lan_plugin_status_active">Briar は Wi-Fi ネットワークに接続されました</string>
|
<string name="lan_plugin_status_active">BriarはWi-Fiネットワークに接続されました</string>
|
||||||
<string name="lan_plugin_status_inactive">Briar は Wi-Fi ネットワークに接続できません</string>
|
<string name="lan_plugin_status_inactive">BriarはWi-Fiネットワークに接続できません</string>
|
||||||
<string name="lan_plugin_status_disabled">Briar は Wi-Fi ネットワークを使用しないように設定されています</string>
|
<string name="lan_plugin_status_disabled">BriarはWi-Fiネットワークを使用しないように設定されています</string>
|
||||||
<!--Transports: Bluetooth-->
|
<!--Transports: Bluetooth-->
|
||||||
<string name="transport_bt">Bluetooth</string>
|
<string name="transport_bt">Bluetooth</string>
|
||||||
<string name="bt_device_status_on">携帯電話の Bluetooth はオンになっています</string>
|
<string name="bt_device_status_on">携帯電話の Bluetooth はオンになっています</string>
|
||||||
<string name="bt_device_status_off">携帯電話の Bluetooth はオフにされました</string>
|
<string name="bt_device_status_off">携帯電話の Bluetooth はオフにされました</string>
|
||||||
<string name="bt_plugin_status_enabling">Briar は Bluetooth に接続中です…</string>
|
<string name="bt_plugin_status_enabling">BriarはBluetoothに接続中です…</string>
|
||||||
<string name="bt_plugin_status_active">Briar は Bluetooth に接続しました</string>
|
<string name="bt_plugin_status_active">BriarはBluetoothに接続しました</string>
|
||||||
<string name="bt_plugin_status_inactive">Briar は Bluetooth に接続できません</string>
|
<string name="bt_plugin_status_inactive">BriarはBluetoothに接続できません</string>
|
||||||
<string name="bt_plugin_status_disabled">Briar は Bluetooth を使用しないように設定されています</string>
|
<string name="bt_plugin_status_disabled">BriarはBluetoothを使用しないように設定されています</string>
|
||||||
<!--Notifications-->
|
<!--Notifications-->
|
||||||
<string name="reminder_notification_title">Briarからサインアウト</string>
|
<string name="reminder_notification_title">Briarからサインアウト</string>
|
||||||
<string name="reminder_notification_text">タップして再ログインします。</string>
|
<string name="reminder_notification_text">タップして再ログインします。</string>
|
||||||
@@ -323,6 +323,7 @@
|
|||||||
<string name="connect_via_bluetooth_intro">Bluetooth接続が自動的に行われない場合は、この画面を使って手動で接続することができます。\n\nこの機能を利用するには、あなたの連絡先が近くにある必要があります。\n\nあなたと連絡先が同時に\"開始\"を押してください。</string>
|
<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_already_discovering">既にBluetooth経由での接続を試行中です。すぐに再試行してください。</string>
|
||||||
<string name="connect_via_bluetooth_no_location_permission">位置情報の権限なくして続行不可能</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_start">Bluetooth経由で接続中…</string>
|
||||||
<string name="connect_via_bluetooth_success">Bluetooth経由で接続に成功</string>
|
<string name="connect_via_bluetooth_success">Bluetooth経由で接続に成功</string>
|
||||||
<string name="connect_via_bluetooth_error">Bluetooth経由で接続不可能。</string>
|
<string name="connect_via_bluetooth_error">Bluetooth経由で接続不可能。</string>
|
||||||
@@ -348,9 +349,9 @@
|
|||||||
<string name="groups_member_created">%sがグループを作成しました</string>
|
<string name="groups_member_created">%sがグループを作成しました</string>
|
||||||
<string name="groups_member_joined_you">グループに参加しました</string>
|
<string name="groups_member_joined_you">グループに参加しました</string>
|
||||||
<string name="groups_member_joined">%sがグループに参加しました</string>
|
<string name="groups_member_joined">%sがグループに参加しました</string>
|
||||||
<string name="groups_leave">グループをやめる</string>
|
<string name="groups_leave">グループを脱退</string>
|
||||||
<string name="groups_leave_dialog_title">グループをやめる確認</string>
|
<string name="groups_leave_dialog_title">グループをやめる確認</string>
|
||||||
<string name="groups_leave_dialog_message">このグループをやめてもよろしいですか?</string>
|
<string name="groups_leave_dialog_message">このグループを脱退してもよろしいですか?</string>
|
||||||
<string name="groups_dissolve">グループを削除</string>
|
<string name="groups_dissolve">グループを削除</string>
|
||||||
<string name="groups_dissolve_dialog_title">グループの削除の確認</string>
|
<string name="groups_dissolve_dialog_title">グループの削除の確認</string>
|
||||||
<string name="groups_dissolve_dialog_message">このグループを削除してもよろしいですか?\n\nグループを削除すると、他のすべてのメンバーは会話を続けることができなくなり、最新のメッセージは受信できなくなります。</string>
|
<string name="groups_dissolve_dialog_message">このグループを削除してもよろしいですか?\n\nグループを削除すると、他のすべてのメンバーは会話を続けることができなくなり、最新のメッセージは受信できなくなります。</string>
|
||||||
@@ -394,10 +395,10 @@
|
|||||||
<string name="forum_new_message_hint">新しい投稿</string>
|
<string name="forum_new_message_hint">新しい投稿</string>
|
||||||
<string name="forum_message_reply_hint">新しい返信</string>
|
<string name="forum_message_reply_hint">新しい返信</string>
|
||||||
<string name="btn_reply">返信</string>
|
<string name="btn_reply">返信</string>
|
||||||
<string name="forum_leave">フォーラムをやめる</string>
|
<string name="forum_leave">フォーラムを脱退</string>
|
||||||
<string name="dialog_title_leave_forum">フォーラムをやめる確認</string>
|
<string name="dialog_title_leave_forum">フォーラムをやめる確認</string>
|
||||||
<string name="dialog_message_leave_forum">このフォーラムをやめてもよろしいですか?\n\nこのフォーラムで共有した連絡先は更新の受信を停止します。</string>
|
<string name="dialog_message_leave_forum">このフォーラムを脱退してもよろしいですか?\n\nこのフォーラムで共有した連絡先は更新の受信を停止します。</string>
|
||||||
<string name="dialog_button_leave">脱退する</string>
|
<string name="dialog_button_leave">脱退</string>
|
||||||
<string name="forum_left_toast">フォーラムをやめました</string>
|
<string name="forum_left_toast">フォーラムをやめました</string>
|
||||||
<!--Forum Sharing-->
|
<!--Forum Sharing-->
|
||||||
<string name="forum_share_button">フォーラムを共有</string>
|
<string name="forum_share_button">フォーラムを共有</string>
|
||||||
@@ -416,6 +417,10 @@
|
|||||||
<string name="forum_declined_toast">招待を辞退しました</string>
|
<string name="forum_declined_toast">招待を辞退しました</string>
|
||||||
<string name="shared_by_format">%sによって共有されました。</string>
|
<string name="shared_by_format">%sによって共有されました。</string>
|
||||||
<string name="forum_invitation_already_sharing">既に共有しています</string>
|
<string name="forum_invitation_already_sharing">既に共有しています</string>
|
||||||
|
<string name="forum_invitation_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_accepted_sent">%sからのフォーラムへの招待を受け入れました。</string>
|
||||||
<string name="forum_invitation_response_declined_sent">%sからのフォーラムへの招待を辞退しました。</string>
|
<string name="forum_invitation_response_declined_sent">%sからのフォーラムへの招待を辞退しました。</string>
|
||||||
<string name="forum_invitation_response_declined_auto">%sからのフォーラムへの招待は自動的に辞退されました。</string>
|
<string name="forum_invitation_response_declined_auto">%sからのフォーラムへの招待は自動的に辞退されました。</string>
|
||||||
@@ -465,8 +470,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">RSSフィードをインポート</string>
|
<string name="blogs_rss_feeds_import">RSSフィードをインポート</string>
|
||||||
<string name="blogs_rss_feeds_import_button">インポート</string>
|
<string name="blogs_rss_feeds_import_button">インポート</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">RSSフィードのURLを入力してください</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_error">申し訳ありません! フィードのインポート中にエラーが発生しました。</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">そのフィードは既にインポートされています。</string>
|
<string name="blogs_rss_feeds_import_title">ファイルからフィードをインポート</string>
|
||||||
<string name="blogs_rss_feeds">RSSフィード</string>
|
<string name="blogs_rss_feeds">RSSフィード</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">インポート済み:</string>
|
<string name="blogs_rss_feeds_manage_imported">インポート済み:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">著者:</string>
|
<string name="blogs_rss_feeds_manage_author">著者:</string>
|
||||||
@@ -573,7 +579,7 @@
|
|||||||
<string name="mailbox_setup_title">メールボックスのセットアップ</string>
|
<string name="mailbox_setup_title">メールボックスのセットアップ</string>
|
||||||
<string name="mailbox_setup_intro">メールボックスはあなたがオフラインの間、連絡先があなたにメッセージを送信することを有効にします。メールボックスはあなたがオンラインになるまで、メッセージを受信し保管します。\n
|
<string name="mailbox_setup_intro">メールボックスはあなたがオフラインの間、連絡先があなたにメッセージを送信することを有効にします。メールボックスはあなたがオンラインになるまで、メッセージを受信し保管します。\n
|
||||||
\n予備端末上にBriarのメールボックスアプリをインストールできます。それを電源とWi-Fiに接続し、常時オンラインにしてください。</string>
|
\n予備端末上にBriarのメールボックスアプリをインストールできます。それを電源とWi-Fiに接続し、常時オンラインにしてください。</string>
|
||||||
<string name="mailbox_setup_download">最初に、Google PlayまたはBriarをダウンロードしたどこかで\"Briar Mailbox\"を検索して、他の端末上にメールボックスアプリをインストールします。\n
|
<string name="mailbox_setup_download">最初に、Google PlayまたはBriarをダウンロードしたどこかで\"BriarMailbox\"を検索して、他の端末上にメールボックスアプリをインストールします。\n
|
||||||
\nそして、メールボックスアプリによって表示されるQRコードを読み取って、Briarとあなたのメールボックス結びつけます。</string>
|
\nそして、メールボックスアプリによって表示されるQRコードを読み取って、Briarとあなたのメールボックス結びつけます。</string>
|
||||||
<string name="mailbox_setup_download_link">ダウンロードリンクを共有</string>
|
<string name="mailbox_setup_download_link">ダウンロードリンクを共有</string>
|
||||||
<string name="mailbox_setup_button_scan">メールボックスのQRコードを読み取る</string>
|
<string name="mailbox_setup_button_scan">メールボックスのQRコードを読み取る</string>
|
||||||
@@ -585,15 +591,15 @@
|
|||||||
<string name="mailbox_qr_code_too_new">読み取ったQRコードは、新しいバージョンのBriarメールボックスから生じました。\n\nBriarを最新版にアップグレードしてから、もう一度お試しください。</string>
|
<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="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_qr_code_wrong_description">読み取ったQRコードは、Briarメールボックスから生じたものではありません。メールボックス端末上のBriarメールボックスアプリを開き、提示されたQRコードを読み取ってください。</string>
|
||||||
<string name="mailbox_setup_already_paired_title">メールボックスは既に結びつけられています</string>
|
<string name="mailbox_setup_already_paired_title">メールボックスは既にリンクされています</string>
|
||||||
<string name="mailbox_setup_already_paired_description">あなたの端末上のメールボックスの結びつけを解き、再試行してください。</string>
|
<string name="mailbox_setup_already_paired_description">あなたの端末上のメールボックスのリンクを解き、再試行してください。</string>
|
||||||
<string name="mailbox_setup_io_error_title">接続できません</string>
|
<string name="mailbox_setup_io_error_title">接続できません</string>
|
||||||
<string name="mailbox_setup_io_error_description">双方の端末がインターネットに接続されていることを確かにして、再試行してください。</string>
|
<string name="mailbox_setup_io_error_description">双方の端末がインターネットに接続されていることを確かにして、再試行してください。</string>
|
||||||
<string name="mailbox_setup_assertion_error_title">メールボックスのエラー</string>
|
<string name="mailbox_setup_assertion_error_title">メールボックスのエラー</string>
|
||||||
<string name="mailbox_setup_assertion_error_description">もし問題が続くのであれば、Briarアプリ経由で(匿名データ付きの)フィードバックを送信してください。</string>
|
<string name="mailbox_setup_assertion_error_description">もし問題が続くのであれば、Briarアプリ経由で(匿名データ付きの)フィードバックを送信してください。</string>
|
||||||
<string name="mailbox_setup_camera_error_description">カメラにアクセスできません。端末を再起動してから、もう一度試してみてください。</string>
|
<string name="mailbox_setup_camera_error_description">カメラにアクセスできません。端末を再起動してから、もう一度試してみてください。</string>
|
||||||
<string name="mailbox_setup_paired_title">接続済み</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>
|
メールボックスを電源とW-Fiに接続して、常時オンラインにしてください。</string>
|
||||||
<string name="tor_offline_title">オフライン</string>
|
<string name="tor_offline_title">オフライン</string>
|
||||||
<string name="tor_offline_description">この端末がオンラインかつインターネットへの接続が許可されていること確かにしてください。\n
|
<string name="tor_offline_description">この端末がオンラインかつインターネットへの接続が許可されていること確かにしてください。\n
|
||||||
@@ -633,7 +639,7 @@
|
|||||||
<string name="mailbox_error_wizard_answer1_1">メールボックスの設定方法が表示される</string>
|
<string name="mailbox_error_wizard_answer1_1">メールボックスの設定方法が表示される</string>
|
||||||
<string name="mailbox_error_wizard_answer1_2">QRコードが表示される</string>
|
<string name="mailbox_error_wizard_answer1_2">QRコードが表示される</string>
|
||||||
<string name="mailbox_error_wizard_answer1_3">「メールボックスは実行中」と表示される</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_info1_1_1">以下のボタンでメールボックスのリンクを解除し、メールボックスの端末の指示に従って再度リンクしてください。</string>
|
||||||
<string name="mailbox_error_wizard_info_1_1_2">以下のボタンでメールボックスのリンクを解除し、QRコードを読み取って再度リンクしてください。</string>
|
<string name="mailbox_error_wizard_info_1_1_2">以下のボタンでメールボックスのリンクを解除し、QRコードを読み取って再度リンクしてください。</string>
|
||||||
<string name="mailbox_error_wizard_info1_1_3">以下のボタンを使用して、Briarとメールボックスの間での接続を確認してください。\n\n
|
<string name="mailbox_error_wizard_info1_1_3">以下のボタンを使用して、Briarとメールボックスの間での接続を確認してください。\n\n
|
||||||
@@ -645,7 +651,7 @@
|
|||||||
<string name="mailbox_error_wizard_info3">以下のボタンを使用してメールボックスをリンク解除してください。\n\n古いメールボックスをリンク解除した後、いつでも新しいメールボックスをセットアップできます。</string>
|
<string name="mailbox_error_wizard_info3">以下のボタンを使用してメールボックスをリンク解除してください。\n\n古いメールボックスをリンク解除した後、いつでも新しいメールボックスをセットアップできます。</string>
|
||||||
<!--About-->
|
<!--About-->
|
||||||
<string name="about_title">Tor Project について</string>
|
<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="tor_version">Tor バージョン: %s</string>
|
||||||
<string name="links">リンク</string>
|
<string name="links">リンク</string>
|
||||||
<string name="briar_website">\u2022 <a href="">ウェブサイト</a></string>
|
<string name="briar_website">\u2022 <a href="">ウェブサイト</a></string>
|
||||||
@@ -777,7 +783,7 @@
|
|||||||
<string name="hotspot_manual_site_address">アドレス(URL)</string>
|
<string name="hotspot_manual_site_address">アドレス(URL)</string>
|
||||||
<string name="hotspot_qr_site">あなたの電話機はWi-Fiホットスポットを提供しています。ホットスポットに接続された人は、このQRコードを読み取って、Briarをダウンロードできます。</string>
|
<string name="hotspot_qr_site">あなたの電話機はWi-Fiホットスポットを提供しています。ホットスポットに接続された人は、このQRコードを読み取って、Briarをダウンロードできます。</string>
|
||||||
<!--e.g. Download Briar 1.2.20-->
|
<!--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_intro_1">近くの誰かが、あなたとBriarを共有しました。</string>
|
||||||
<string name="website_download_button">Briarをダウンロード</string>
|
<string name="website_download_button">Briarをダウンロード</string>
|
||||||
<string name="website_download_outro">ダウンロードが完了した後に、ダウンロードしたファイルを開いて、インストールしてください。</string>
|
<string name="website_download_outro">ダウンロードが完了した後に、ダウンロードしたファイルを開いて、インストールしてください。</string>
|
||||||
|
|||||||
@@ -477,7 +477,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">იმპორტი</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_hint">შეიყვანეთ RSS არხის URL</string>
|
||||||
<string name="blogs_rss_feeds_import_error">ვწუხვართ! არხის იმპორტირებისას შეცდომა წარმოიშვა.</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">RSS არხები</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">იმპორტირებული:</string>
|
<string name="blogs_rss_feeds_manage_imported">იმპორტირებული:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">ავტორი:</string>
|
<string name="blogs_rss_feeds_manage_author">ავტორი:</string>
|
||||||
|
|||||||
@@ -313,6 +313,8 @@
|
|||||||
<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="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>
|
<string name="pending_contact_updated_toast">Laukiantis adresatas atnaujintas</string>
|
||||||
<!--Peer trust levels-->
|
<!--Peer trust levels-->
|
||||||
|
<string name="peer_trust_level_ourselves">Aš</string>
|
||||||
|
<string name="peer_trust_level_stranger">Nepažįstamasis</string>
|
||||||
<!--Introductions-->
|
<!--Introductions-->
|
||||||
<string name="introduction_onboarding_title">Supažindinkite savo adresatus</string>
|
<string name="introduction_onboarding_title">Supažindinkite savo adresatus</string>
|
||||||
<string name="introduction_menu_item">Supažindinti</string>
|
<string name="introduction_menu_item">Supažindinti</string>
|
||||||
@@ -442,6 +444,9 @@
|
|||||||
<string name="forum_declined_toast">Pakvietimas atmestas</string>
|
<string name="forum_declined_toast">Pakvietimas atmestas</string>
|
||||||
<string name="shared_by_format">Bendrina %s</string>
|
<string name="shared_by_format">Bendrina %s</string>
|
||||||
<string name="forum_invitation_already_sharing">Jau bendrinama</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_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_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>
|
<string name="forum_invitation_response_declined_auto">Pakvietimas į forumą nuo %s buvo automatiškai atmestas.</string>
|
||||||
@@ -494,8 +499,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Importuoti RSS kanalą</string>
|
<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_button">Importuoti</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Įveskite RSS kanalo URL</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_error">Atleiskite! Importuojant jūsų kanalą, įvyko klaida.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Tas kanalas jau yra importuotas.</string>
|
<string name="blogs_rss_feeds_import_title">Importuoti kanalą iš failo</string>
|
||||||
<string name="blogs_rss_feeds">RSS kanalai</string>
|
<string name="blogs_rss_feeds">RSS kanalai</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importuota:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importuota:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autorius:</string>
|
<string name="blogs_rss_feeds_manage_author">Autorius:</string>
|
||||||
@@ -605,6 +611,7 @@
|
|||||||
<string name="mailbox_setup_download_link">Bendrinti atsisiuntimo nuorodą</string>
|
<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>
|
<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".-->
|
<!--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_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_title">Nepavyko prisijungti</string>
|
||||||
<string name="mailbox_setup_io_error_description">Įsitikinkite, kad abu įrenginiai yra prisijungę prie interneto ir bandykite dar kartą.</string>
|
<string name="mailbox_setup_io_error_description">Įsitikinkite, kad abu įrenginiai yra prisijungę prie interneto ir bandykite dar kartą.</string>
|
||||||
@@ -641,6 +648,7 @@
|
|||||||
<string name="briar_changelog">\u2022 <a href="">Keitinių žurnalas</a></string>
|
<string name="briar_changelog">\u2022 <a href="">Keitinių žurnalas</a></string>
|
||||||
<string name="briar_privacy_policy">\u2022 <a href="">Privatumo politika</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")-->
|
<!--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-->
|
<!--Conversation Settings-->
|
||||||
<string name="disappearing_messages_title">Išnykstančios žinutės</string>
|
<string name="disappearing_messages_title">Išnykstančios žinutės</string>
|
||||||
<string name="disappearing_messages_explanation_long">Įjungus šį nustatymą, naujos žinutės
|
<string name="disappearing_messages_explanation_long">Įjungus šį nustatymą, naujos žinutės
|
||||||
|
|||||||
@@ -460,7 +460,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">တင်သွင်းမည်</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_hint">RSS သတင်းပို့စ်အလွှာ၏ URL ရိုက်ထည့်ပေးပါ</string>
|
||||||
<string name="blogs_rss_feeds_import_error">ဝမ်းနည်းပါသည်! သင့် သတင်းပို့စ်အလွှာအား တင်သွင်းရာတွင် ပျက်ကွက်မှု ဖြစ်ခဲ့ပါသည်။</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">RSS သတင်းလွှာများ</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">တင်သွင်းထားသော</string>
|
<string name="blogs_rss_feeds_manage_imported">တင်သွင်းထားသော</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">စာရေးဆရာ -</string>
|
<string name="blogs_rss_feeds_manage_author">စာရေးဆရာ -</string>
|
||||||
|
|||||||
@@ -477,7 +477,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Importer</string>
|
<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_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_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">RSS-feed\'er</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importert:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importert:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Forfatter:</string>
|
<string name="blogs_rss_feeds_manage_author">Forfatter:</string>
|
||||||
|
|||||||
@@ -244,6 +244,7 @@
|
|||||||
<string name="menu_contact">Kontakt</string>
|
<string name="menu_contact">Kontakt</string>
|
||||||
<!--Adding Contacts-->
|
<!--Adding Contacts-->
|
||||||
<string name="add_contact_title">Dodaj kontakt w pobliżu</string>
|
<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="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="continue_button">Kontynuuj</string>
|
||||||
<string name="try_again_button">Spróbuj ponownie</string>
|
<string name="try_again_button">Spróbuj ponownie</string>
|
||||||
@@ -259,6 +260,7 @@
|
|||||||
<string name="authenticating_with_device">Autoryzowanie z urządzeniem\u2026</string>
|
<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_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="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-->
|
<!--Adding Contacts Remotely-->
|
||||||
<string name="add_contact_remotely_title_case">Dodaj Kontakt na odległość</string>
|
<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>
|
<string name="add_contact_nearby_title">Dodaj kontakt w pobliżu</string>
|
||||||
@@ -318,6 +320,7 @@
|
|||||||
<string name="different_person_button">Inna osoba</string>
|
<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="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="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-->
|
<!--Peer trust levels-->
|
||||||
<string name="peer_trust_level_unverified">Niezweryfikowane kontakty</string>
|
<string name="peer_trust_level_unverified">Niezweryfikowane kontakty</string>
|
||||||
<string name="peer_trust_level_verified">Zweryfikowane kontakty</string>
|
<string name="peer_trust_level_verified">Zweryfikowane kontakty</string>
|
||||||
@@ -351,6 +354,7 @@
|
|||||||
<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_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_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_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_start">Łączenie przez Bluetooth...</string>
|
||||||
<string name="connect_via_bluetooth_success">Udało się połączyć 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>
|
<string name="connect_via_bluetooth_error">Nie można się połączyć przez Bluetooth.</string>
|
||||||
@@ -453,6 +457,10 @@
|
|||||||
<string name="forum_declined_toast">Zaproszenie odrzucone</string>
|
<string name="forum_declined_toast">Zaproszenie odrzucone</string>
|
||||||
<string name="shared_by_format">Udostępnione przez %s</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_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_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_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>
|
<string name="forum_invitation_response_declined_auto">Zaproszenie do forum od %s zostało automatycznie odrzucone.</string>
|
||||||
@@ -505,8 +513,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Zaimportuj kanał RSS</string>
|
<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_button">Zaimportuj</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Wprowadź adres URL do kanału RSS</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_error">Przepraszamy! Wystąpił błąd podczas importowania twojego kanału RSS</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Ten feed został już zaimportowany.</string>
|
<string name="blogs_rss_feeds_import_title">Importuj kanał z pliku</string>
|
||||||
<string name="blogs_rss_feeds">Feedy RSS</string>
|
<string name="blogs_rss_feeds">Feedy RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Zaimportowane:</string>
|
<string name="blogs_rss_feeds_manage_imported">Zaimportowane:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
@@ -618,7 +627,9 @@
|
|||||||
<string name="mailbox_setup_download_link">Udostępnij łącze pobierania</string>
|
<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="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="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".-->
|
<!--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_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_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>
|
<string name="mailbox_setup_io_error_title">Nie udało się połączyć</string>
|
||||||
@@ -756,11 +767,15 @@ 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_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_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_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_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_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_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_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_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="qr_code">Kod QR</string>
|
||||||
<string name="show_qr_code_fullscreen">Pokaż QR na pełnym ekranie</string>
|
<string name="show_qr_code_fullscreen">Pokaż QR na pełnym ekranie</string>
|
||||||
<!--App Locking-->
|
<!--App Locking-->
|
||||||
|
|||||||
@@ -488,7 +488,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Importar</string>
|
<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_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_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">Feeds RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importado:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
|
|||||||
@@ -446,6 +446,10 @@
|
|||||||
<string name="forum_declined_toast">Invitația a fost refuzată</string>
|
<string name="forum_declined_toast">Invitația a fost refuzată</string>
|
||||||
<string name="shared_by_format">Partajat de %s</string>
|
<string name="shared_by_format">Partajat de %s</string>
|
||||||
<string name="forum_invitation_already_sharing">Deja partajat</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_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_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>
|
<string name="forum_invitation_response_declined_auto">Invitația la forumu de la %s a fost refuzată automat.</string>
|
||||||
@@ -497,8 +501,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Importați flux RSS</string>
|
<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_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_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_error">Ne pare rău, dar a apărut o eroare la importarea fluxului dvs.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Fluxul respectiv este deja importat.</string>
|
<string name="blogs_rss_feeds_import_title">Importați feed din fișier</string>
|
||||||
<string name="blogs_rss_feeds">Fluxuri RSS</string>
|
<string name="blogs_rss_feeds">Fluxuri RSS</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importat:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
|
|||||||
@@ -462,7 +462,7 @@
|
|||||||
<string name="forum_invitation_already_invited">Приглашение уже отправлено</string>
|
<string name="forum_invitation_already_invited">Приглашение уже отправлено</string>
|
||||||
<string name="forum_invitation_invite_received">Приглашение уже получено</string>
|
<string name="forum_invitation_invite_received">Приглашение уже получено</string>
|
||||||
<string name="forum_invitation_not_supported">Не поддерживается этим контактом</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_accepted_sent">Вы приняли приглашение на форум от %s.</string>
|
||||||
<string name="forum_invitation_response_declined_sent">Вы отклонили приглашение на форум от %s.</string>
|
<string name="forum_invitation_response_declined_sent">Вы отклонили приглашение на форум от %s.</string>
|
||||||
<string name="forum_invitation_response_declined_auto">Приглашение на форум от %s было отклонено автоматически.</string>
|
<string name="forum_invitation_response_declined_auto">Приглашение на форум от %s было отклонено автоматически.</string>
|
||||||
@@ -515,8 +515,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Импорт RSS-ленты</string>
|
<string name="blogs_rss_feeds_import">Импорт RSS-ленты</string>
|
||||||
<string name="blogs_rss_feeds_import_button">Импорт</string>
|
<string name="blogs_rss_feeds_import_button">Импорт</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Введите URL-адрес RSS-ленты</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_error">Мы сожалеем! Произошла ошибка при импорте ленты.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Эта лента уже импортирована.</string>
|
<string name="blogs_rss_feeds_import_title">Импорт ленты из файла</string>
|
||||||
<string name="blogs_rss_feeds">RSS-ленты</string>
|
<string name="blogs_rss_feeds">RSS-ленты</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Импортирован:</string>
|
<string name="blogs_rss_feeds_manage_imported">Импортирован:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
||||||
|
|||||||
@@ -488,8 +488,9 @@ dhe s’mund 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">Importoni Prurje RSS</string>
|
||||||
<string name="blogs_rss_feeds_import_button">Importo</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_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_error">Na ndjeni! Pati një gabim me importimin e prurjes tuaj.</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">Ajo prurje është importuar tashmë.</string>
|
<string name="blogs_rss_feeds_import_title">Importo prurje nga kartelë</string>
|
||||||
<string name="blogs_rss_feeds">Prurje RSS</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_imported">Të importuara:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
<string name="blogs_rss_feeds_manage_author">Autor:</string>
|
||||||
|
|||||||
@@ -478,7 +478,6 @@ Vänlige installera Briar på en nyare enhet.</string>
|
|||||||
<string name="blogs_rss_feeds_import_button">Importera</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_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_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">RSS-flöden</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Importerade:</string>
|
<string name="blogs_rss_feeds_manage_imported">Importerade:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Författare:</string>
|
<string name="blogs_rss_feeds_manage_author">Författare:</string>
|
||||||
|
|||||||
@@ -482,7 +482,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">İçe Aktar</string>
|
<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_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_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">RSS beslemeleri</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">İçe Aktarıldı:</string>
|
<string name="blogs_rss_feeds_manage_imported">İçe Aktarıldı:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Yazar:</string>
|
<string name="blogs_rss_feeds_manage_author">Yazar:</string>
|
||||||
@@ -594,9 +593,7 @@
|
|||||||
<string name="mailbox_setup_download_link">İndirme Bağlantısını Paylaş</string>
|
<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="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>
|
<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>
|
||||||
<string name="mailbox_setup_connecting">Bağlantı kuruluyor…</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_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_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_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>
|
<string name="mailbox_setup_io_error_title">Bağlantı kurulamıyor</string>
|
||||||
|
|||||||
@@ -505,7 +505,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">Імпортувати</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_hint">Введіть URL-посилання RSS-стрічки</string>
|
||||||
<string name="blogs_rss_feeds_import_error">Нам шкода! Виникла помилка під час імпорту вашої стрічки.</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">RSS-стрічки</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Імпортовано:</string>
|
<string name="blogs_rss_feeds_manage_imported">Імпортовано:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
<string name="blogs_rss_feeds_manage_author">Автор:</string>
|
||||||
|
|||||||
@@ -473,8 +473,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">导入 RSS 订阅源</string>
|
<string name="blogs_rss_feeds_import">导入 RSS 订阅源</string>
|
||||||
<string name="blogs_rss_feeds_import_button">导入</string>
|
<string name="blogs_rss_feeds_import_button">导入</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">输入 RSS 订阅源链接</string>
|
<string name="blogs_rss_feeds_import_hint">输入 RSS 订阅源链接</string>
|
||||||
|
<string name="blogs_rss_feeds_import_progress">导入 RSS 订阅源中…</string>
|
||||||
<string name="blogs_rss_feeds_import_error">抱歉!导入订阅源时发生错误。</string>
|
<string name="blogs_rss_feeds_import_error">抱歉!导入订阅源时发生错误。</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">已经导入那个源</string>
|
<string name="blogs_rss_feeds_import_title">从文件导入源</string>
|
||||||
<string name="blogs_rss_feeds">RSS源 </string>
|
<string name="blogs_rss_feeds">RSS源 </string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">已导入:</string>
|
<string name="blogs_rss_feeds_manage_imported">已导入:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">作者:</string>
|
<string name="blogs_rss_feeds_manage_author">作者:</string>
|
||||||
|
|||||||
@@ -423,6 +423,10 @@
|
|||||||
<string name="forum_declined_toast">邀請已謝絕</string>
|
<string name="forum_declined_toast">邀請已謝絕</string>
|
||||||
<string name="shared_by_format">由 %s 分享</string>
|
<string name="shared_by_format">由 %s 分享</string>
|
||||||
<string name="forum_invitation_already_sharing">已在分享</string>
|
<string name="forum_invitation_already_sharing">已在分享</string>
|
||||||
|
<string name="forum_invitation_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_accepted_sent">您接受了來自 %s的論壇邀請</string>
|
||||||
<string name="forum_invitation_response_declined_sent">您謝絕了來自 %s的論壇邀請</string>
|
<string name="forum_invitation_response_declined_sent">您謝絕了來自 %s的論壇邀請</string>
|
||||||
<string name="forum_invitation_response_declined_auto">來自%s論壇的邀請已自動拒絕</string>
|
<string name="forum_invitation_response_declined_auto">來自%s論壇的邀請已自動拒絕</string>
|
||||||
@@ -473,7 +477,6 @@
|
|||||||
<string name="blogs_rss_feeds_import_button">導入</string>
|
<string name="blogs_rss_feeds_import_button">導入</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">輸入 RSS 訂閱源鏈接</string>
|
<string name="blogs_rss_feeds_import_hint">輸入 RSS 訂閱源鏈接</string>
|
||||||
<string name="blogs_rss_feeds_import_error">抱歉!導入訂閱源時發生錯誤。</string>
|
<string name="blogs_rss_feeds_import_error">抱歉!導入訂閱源時發生錯誤。</string>
|
||||||
<string name="blogs_rss_feeds_import_exists">此來源已滙入</string>
|
|
||||||
<string name="blogs_rss_feeds">RSS 消息源</string>
|
<string name="blogs_rss_feeds">RSS 消息源</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">已導入:</string>
|
<string name="blogs_rss_feeds_manage_imported">已導入:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">作者:</string>
|
<string name="blogs_rss_feeds_manage_author">作者:</string>
|
||||||
|
|||||||
@@ -519,7 +519,9 @@
|
|||||||
<string name="blogs_rss_feeds_import">Import RSS Feed</string>
|
<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_button">Import</string>
|
||||||
<string name="blogs_rss_feeds_import_hint">Enter the URL of the RSS feed</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_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">RSS Feeds</string>
|
||||||
<string name="blogs_rss_feeds_manage_imported">Imported:</string>
|
<string name="blogs_rss_feeds_manage_imported">Imported:</string>
|
||||||
<string name="blogs_rss_feeds_manage_author">Author:</string>
|
<string name="blogs_rss_feeds_manage_author">Author:</string>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class AttachmentReaderImpl implements AttachmentReader {
|
|||||||
String contentType = meta.getString(MSG_KEY_CONTENT_TYPE);
|
String contentType = meta.getString(MSG_KEY_CONTENT_TYPE);
|
||||||
if (!contentType.equals(h.getContentType()))
|
if (!contentType.equals(h.getContentType()))
|
||||||
throw new NoSuchMessageException();
|
throw new NoSuchMessageException();
|
||||||
int offset = meta.getLong(MSG_KEY_DESCRIPTOR_LENGTH).intValue();
|
int offset = meta.getInt(MSG_KEY_DESCRIPTOR_LENGTH);
|
||||||
InputStream stream = new ByteArrayInputStream(body, offset,
|
InputStream stream = new ByteArrayInputStream(body, offset,
|
||||||
body.length - offset);
|
body.length - offset);
|
||||||
return new Attachment(h, stream);
|
return new Attachment(h, stream);
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
|
|||||||
try {
|
try {
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
clientHelper.getGroupMetadataAsDictionary(txn, g);
|
clientHelper.getGroupMetadataAsDictionary(txn, g);
|
||||||
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ class AvatarValidator implements MessageValidator {
|
|||||||
// 0.0: Message Type, Version, Content-Type
|
// 0.0: Message Type, Version, Content-Type
|
||||||
checkSize(body, 3);
|
checkSize(body, 3);
|
||||||
// Message Type
|
// Message Type
|
||||||
long messageType = body.getLong(0);
|
int messageType = body.getInt(0);
|
||||||
if (messageType != MSG_TYPE_UPDATE) throw new FormatException();
|
if (messageType != MSG_TYPE_UPDATE) throw new FormatException();
|
||||||
// Version
|
// Version
|
||||||
long version = body.getLong(1);
|
long version = body.getLong(1);
|
||||||
|
|||||||
@@ -487,7 +487,7 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getPostText(BdfList message) throws FormatException {
|
private String getPostText(BdfList message) throws FormatException {
|
||||||
MessageType type = MessageType.valueOf(message.getLong(0).intValue());
|
MessageType type = MessageType.valueOf(message.getInt(0));
|
||||||
if (type == POST) {
|
if (type == POST) {
|
||||||
// Type, text, signature
|
// Type, text, signature
|
||||||
return message.getString(1);
|
return message.getString(1);
|
||||||
@@ -621,7 +621,6 @@ class BlogManagerImpl extends BdfIncomingMessageHook implements BlogManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MessageType getMessageType(BdfDictionary d) throws FormatException {
|
private MessageType getMessageType(BdfDictionary d) throws FormatException {
|
||||||
Long longType = d.getLong(KEY_TYPE);
|
return MessageType.valueOf(d.getInt(KEY_TYPE));
|
||||||
return MessageType.valueOf(longType.intValue());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,6 +167,6 @@ class BlogPostFactoryImpl implements BlogPostFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MessageType getType(BdfList body) throws FormatException {
|
private MessageType getType(BdfList body) throws FormatException {
|
||||||
return MessageType.valueOf(body.getLong(0).intValue());
|
return MessageType.valueOf(body.getInt(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class BlogPostValidator extends BdfMessageValidator {
|
|||||||
|
|
||||||
BdfMessageContext c;
|
BdfMessageContext c;
|
||||||
|
|
||||||
int type = body.getLong(0).intValue();
|
int type = body.getInt(0);
|
||||||
body.remove(0);
|
body.remove(0);
|
||||||
switch (MessageType.valueOf(type)) {
|
switch (MessageType.valueOf(type)) {
|
||||||
case POST:
|
case POST:
|
||||||
|
|||||||
@@ -114,8 +114,8 @@ class MessageTrackerImpl implements MessageTracker {
|
|||||||
try {
|
try {
|
||||||
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
|
BdfDictionary d = clientHelper.getGroupMetadataAsDictionary(txn, g);
|
||||||
return new GroupCount(
|
return new GroupCount(
|
||||||
d.getLong(GROUP_KEY_MSG_COUNT, 0L).intValue(),
|
d.getInt(GROUP_KEY_MSG_COUNT, 0),
|
||||||
d.getLong(GROUP_KEY_UNREAD_COUNT, 0L).intValue(),
|
d.getInt(GROUP_KEY_UNREAD_COUNT, 0),
|
||||||
d.getLong(GROUP_KEY_LATEST_MSG, 0L)
|
d.getLong(GROUP_KEY_LATEST_MSG, 0L)
|
||||||
);
|
);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class IntroductionValidator extends BdfMessageValidator {
|
|||||||
@Override
|
@Override
|
||||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||||
BdfList body) throws FormatException {
|
BdfList body) throws FormatException {
|
||||||
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
|
MessageType type = MessageType.fromValue(body.getInt(0));
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case REQUEST:
|
case REQUEST:
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ class MessageParserImpl implements MessageParser {
|
|||||||
@Override
|
@Override
|
||||||
public MessageMetadata parseMetadata(BdfDictionary d)
|
public MessageMetadata parseMetadata(BdfDictionary d)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
MessageType type = MessageType
|
MessageType type =
|
||||||
.fromValue(d.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
|
MessageType.fromValue(d.getInt(MSG_KEY_MESSAGE_TYPE));
|
||||||
byte[] sessionIdBytes = d.getOptionalRaw(MSG_KEY_SESSION_ID);
|
byte[] sessionIdBytes = d.getOptionalRaw(MSG_KEY_SESSION_ID);
|
||||||
SessionId sessionId =
|
SessionId sessionId =
|
||||||
sessionIdBytes == null ? null : new SessionId(sessionIdBytes);
|
sessionIdBytes == null ? null : new SessionId(sessionIdBytes);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Role getRole(BdfDictionary d) throws FormatException {
|
public Role getRole(BdfDictionary d) throws FormatException {
|
||||||
return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue());
|
return Role.fromValue(d.getInt(SESSION_KEY_ROLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -97,7 +97,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
MessageId lastRemoteMessageId =
|
MessageId lastRemoteMessageId =
|
||||||
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
|
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
|
||||||
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
||||||
GroupId groupId = getGroupId(d, SESSION_KEY_GROUP_ID);
|
GroupId groupId = getGroupId(d);
|
||||||
Author author = getAuthor(d, SESSION_KEY_AUTHOR);
|
Author author = getAuthor(d, SESSION_KEY_AUTHOR);
|
||||||
return new Introducee(sessionId, groupId, author, localTimestamp,
|
return new Introducee(sessionId, groupId, author, localTimestamp,
|
||||||
lastLocalMessageId, lastRemoteMessageId);
|
lastLocalMessageId, lastRemoteMessageId);
|
||||||
@@ -126,12 +126,10 @@ class SessionParserImpl implements SessionParser {
|
|||||||
MessageId lastLocalMessageId =
|
MessageId lastLocalMessageId =
|
||||||
getMessageId(d, SESSION_KEY_LAST_LOCAL_MESSAGE_ID);
|
getMessageId(d, SESSION_KEY_LAST_LOCAL_MESSAGE_ID);
|
||||||
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
long localTimestamp = d.getLong(SESSION_KEY_LOCAL_TIMESTAMP);
|
||||||
PublicKey ephemeralPublicKey =
|
PublicKey ephemeralPublicKey = getEphemeralPublicKey(d);
|
||||||
getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
|
|
||||||
BdfDictionary tpDict =
|
BdfDictionary tpDict =
|
||||||
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
|
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
|
||||||
PrivateKey ephemeralPrivateKey =
|
PrivateKey ephemeralPrivateKey = getEphemeralPrivateKey(d);
|
||||||
getEphemeralPrivateKey(d, SESSION_KEY_EPHEMERAL_PRIVATE_KEY);
|
|
||||||
Map<TransportId, TransportProperties> transportProperties =
|
Map<TransportId, TransportProperties> transportProperties =
|
||||||
tpDict == null ? null : clientHelper
|
tpDict == null ? null : clientHelper
|
||||||
.parseAndValidateTransportPropertiesMap(tpDict);
|
.parseAndValidateTransportPropertiesMap(tpDict);
|
||||||
@@ -147,8 +145,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
Author remoteAuthor = getAuthor(d, SESSION_KEY_REMOTE_AUTHOR);
|
Author remoteAuthor = getAuthor(d, SESSION_KEY_REMOTE_AUTHOR);
|
||||||
MessageId lastRemoteMessageId =
|
MessageId lastRemoteMessageId =
|
||||||
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
|
getMessageId(d, SESSION_KEY_LAST_REMOTE_MESSAGE_ID);
|
||||||
PublicKey ephemeralPublicKey =
|
PublicKey ephemeralPublicKey = getEphemeralPublicKey(d);
|
||||||
getEphemeralPublicKey(d, SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
|
|
||||||
BdfDictionary tpDict =
|
BdfDictionary tpDict =
|
||||||
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
|
d.getOptionalDictionary(SESSION_KEY_TRANSPORT_PROPERTIES);
|
||||||
Map<TransportId, TransportProperties> transportProperties =
|
Map<TransportId, TransportProperties> transportProperties =
|
||||||
@@ -162,7 +159,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getState(BdfDictionary d) throws FormatException {
|
private int getState(BdfDictionary d) throws FormatException {
|
||||||
return d.getLong(SESSION_KEY_STATE).intValue();
|
return d.getInt(SESSION_KEY_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SessionId getSessionId(BdfDictionary d) throws FormatException {
|
private SessionId getSessionId(BdfDictionary d) throws FormatException {
|
||||||
@@ -177,9 +174,8 @@ class SessionParserImpl implements SessionParser {
|
|||||||
return b == null ? null : new MessageId(b);
|
return b == null ? null : new MessageId(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupId getGroupId(BdfDictionary d, String key)
|
private GroupId getGroupId(BdfDictionary d) throws FormatException {
|
||||||
throws FormatException {
|
return new GroupId(d.getRaw(SESSION_KEY_GROUP_ID));
|
||||||
return new GroupId(d.getRaw(key));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Author getAuthor(BdfDictionary d, String key)
|
private Author getAuthor(BdfDictionary d, String key)
|
||||||
@@ -193,23 +189,22 @@ class SessionParserImpl implements SessionParser {
|
|||||||
if (d == null) return null;
|
if (d == null) return null;
|
||||||
Map<TransportId, KeySetId> map = new HashMap<>(d.size());
|
Map<TransportId, KeySetId> map = new HashMap<>(d.size());
|
||||||
for (String key : d.keySet()) {
|
for (String key : d.keySet()) {
|
||||||
map.put(new TransportId(key),
|
map.put(new TransportId(key), new KeySetId(d.getInt(key)));
|
||||||
new KeySetId(d.getLong(key).intValue()));
|
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PublicKey getEphemeralPublicKey(BdfDictionary d, String key)
|
private PublicKey getEphemeralPublicKey(BdfDictionary d)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
byte[] keyBytes = d.getOptionalRaw(key);
|
byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PUBLIC_KEY);
|
||||||
return keyBytes == null ? null : new AgreementPublicKey(keyBytes);
|
return keyBytes == null ? null : new AgreementPublicKey(keyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private PrivateKey getEphemeralPrivateKey(BdfDictionary d, String key)
|
private PrivateKey getEphemeralPrivateKey(BdfDictionary d)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
byte[] keyBytes = d.getOptionalRaw(key);
|
byte[] keyBytes = d.getOptionalRaw(SESSION_KEY_EPHEMERAL_PRIVATE_KEY);
|
||||||
return keyBytes == null ? null : new AgreementPrivateKey(keyBytes);
|
return keyBytes == null ? null : new AgreementPrivateKey(keyBytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
try {
|
try {
|
||||||
BdfDictionary metaDict = metadataParser.parse(meta);
|
BdfDictionary metaDict = metadataParser.parse(meta);
|
||||||
// Message type is null for version 0.0 private messages
|
// Message type is null for version 0.0 private messages
|
||||||
Long messageType = metaDict.getOptionalLong(MSG_KEY_MSG_TYPE);
|
Integer messageType = metaDict.getOptionalInt(MSG_KEY_MSG_TYPE);
|
||||||
if (messageType == null) {
|
if (messageType == null) {
|
||||||
incomingPrivateMessage(txn, m, metaDict, true, emptyList());
|
incomingPrivateMessage(txn, m, metaDict, true, emptyList());
|
||||||
} else if (messageType == PRIVATE_MESSAGE) {
|
} else if (messageType == PRIVATE_MESSAGE) {
|
||||||
@@ -371,7 +371,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
try {
|
try {
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
clientHelper.getGroupMetadataAsDictionary(txn, g);
|
clientHelper.getGroupMetadataAsDictionary(txn, g);
|
||||||
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
@@ -381,7 +381,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
public ContactId getContactId(GroupId g) throws DbException {
|
public ContactId getContactId(GroupId g) throws DbException {
|
||||||
try {
|
try {
|
||||||
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g);
|
BdfDictionary meta = clientHelper.getGroupMetadataAsDictionary(g);
|
||||||
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
|
return new ContactId(meta.getInt(GROUP_KEY_CONTACT_ID));
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
@@ -419,7 +419,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
if (meta == null) continue;
|
if (meta == null) continue;
|
||||||
try {
|
try {
|
||||||
// Message type is null for version 0.0 private messages
|
// Message type is null for version 0.0 private messages
|
||||||
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
|
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
|
||||||
if (messageType != null && messageType != PRIVATE_MESSAGE)
|
if (messageType != null && messageType != PRIVATE_MESSAGE)
|
||||||
continue;
|
continue;
|
||||||
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
||||||
@@ -453,7 +453,8 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
Map<MessageId, BdfDictionary> messages =
|
Map<MessageId, BdfDictionary> messages =
|
||||||
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
||||||
for (Entry<MessageId, BdfDictionary> entry : messages.entrySet()) {
|
for (Entry<MessageId, BdfDictionary> entry : messages.entrySet()) {
|
||||||
Long type = entry.getValue().getOptionalLong(MSG_KEY_MSG_TYPE);
|
Integer type =
|
||||||
|
entry.getValue().getOptionalInt(MSG_KEY_MSG_TYPE);
|
||||||
if (type == null || type == PRIVATE_MESSAGE)
|
if (type == null || type == PRIVATE_MESSAGE)
|
||||||
result.add(entry.getKey());
|
result.add(entry.getKey());
|
||||||
}
|
}
|
||||||
@@ -527,7 +528,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
try {
|
try {
|
||||||
BdfDictionary meta =
|
BdfDictionary meta =
|
||||||
clientHelper.getMessageMetadataAsDictionary(txn, m);
|
clientHelper.getMessageMetadataAsDictionary(txn, m);
|
||||||
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
|
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
|
||||||
if (messageType != null && messageType == PRIVATE_MESSAGE) {
|
if (messageType != null && messageType == PRIVATE_MESSAGE) {
|
||||||
for (AttachmentHeader h : parseAttachmentHeaders(g, meta)) {
|
for (AttachmentHeader h : parseAttachmentHeaders(g, meta)) {
|
||||||
try {
|
try {
|
||||||
@@ -554,7 +555,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
|||||||
int unreadCount = 0;
|
int unreadCount = 0;
|
||||||
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
||||||
BdfDictionary meta = entry.getValue();
|
BdfDictionary meta = entry.getValue();
|
||||||
Long messageType = meta.getOptionalLong(MSG_KEY_MSG_TYPE);
|
Integer messageType = meta.getOptionalInt(MSG_KEY_MSG_TYPE);
|
||||||
if (messageType == null || messageType == PRIVATE_MESSAGE) {
|
if (messageType == null || messageType == PRIVATE_MESSAGE) {
|
||||||
msgCount++;
|
msgCount++;
|
||||||
if (!meta.getBoolean(MSG_KEY_READ)) unreadCount++;
|
if (!meta.getBoolean(MSG_KEY_READ)) unreadCount++;
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class PrivateMessageValidator implements MessageValidator {
|
|||||||
context = validateLegacyPrivateMessage(m, list);
|
context = validateLegacyPrivateMessage(m, list);
|
||||||
} else {
|
} else {
|
||||||
// Private message or attachment
|
// Private message or attachment
|
||||||
int messageType = list.getLong(0).intValue();
|
int messageType = list.getInt(0);
|
||||||
if (messageType == PRIVATE_MESSAGE) {
|
if (messageType == PRIVATE_MESSAGE) {
|
||||||
if (!reader.eof()) throw new FormatException();
|
if (!reader.eof()) throw new FormatException();
|
||||||
context = validatePrivateMessage(m, list);
|
context = validatePrivateMessage(m, list);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
checkSize(body, 4, 6);
|
checkSize(body, 4, 6);
|
||||||
|
|
||||||
// Message type (int)
|
// Message type (int)
|
||||||
int type = body.getLong(0).intValue();
|
int type = body.getInt(0);
|
||||||
|
|
||||||
// Member (author)
|
// Member (author)
|
||||||
BdfList memberList = body.getList(1);
|
BdfList memberList = body.getList(1);
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
|
|||||||
// parse the metadata
|
// parse the metadata
|
||||||
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
||||||
BdfDictionary meta = entry.getValue();
|
BdfDictionary meta = entry.getValue();
|
||||||
if (meta.getLong(KEY_TYPE) == JOIN.getInt()) {
|
if (meta.getInt(KEY_TYPE) == JOIN.getInt()) {
|
||||||
headers.add(getJoinMessageHeader(txn, g, entry.getKey(),
|
headers.add(getJoinMessageHeader(txn, g, entry.getKey(),
|
||||||
meta, authorInfos));
|
meta, authorInfos));
|
||||||
} else {
|
} else {
|
||||||
@@ -530,8 +530,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
|
|||||||
BdfList body, BdfDictionary meta)
|
BdfList body, BdfDictionary meta)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
|
|
||||||
MessageType type =
|
MessageType type = MessageType.valueOf(meta.getInt(KEY_TYPE));
|
||||||
MessageType.valueOf(meta.getLong(KEY_TYPE).intValue());
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case JOIN:
|
case JOIN:
|
||||||
handleJoinMessage(txn, m, meta);
|
handleJoinMessage(txn, m, meta);
|
||||||
@@ -576,8 +575,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
|
|||||||
.getMessageMetadataAsDictionary(txn, parentId);
|
.getMessageMetadataAsDictionary(txn, parentId);
|
||||||
if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP))
|
if (timestamp <= parentMeta.getLong(KEY_TIMESTAMP))
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
MessageType parentType = MessageType
|
MessageType parentType =
|
||||||
.valueOf(parentMeta.getLong(KEY_TYPE).intValue());
|
MessageType.valueOf(parentMeta.getInt(KEY_TYPE));
|
||||||
if (parentType != POST)
|
if (parentType != POST)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
}
|
}
|
||||||
@@ -592,8 +591,8 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
|
|||||||
if (!getAuthor(meta).equals(getAuthor(previousMeta)))
|
if (!getAuthor(meta).equals(getAuthor(previousMeta)))
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
// previous message must be a POST or JOIN
|
// previous message must be a POST or JOIN
|
||||||
MessageType previousType = MessageType
|
MessageType previousType =
|
||||||
.valueOf(previousMeta.getLong(KEY_TYPE).intValue());
|
MessageType.valueOf(previousMeta.getInt(KEY_TYPE));
|
||||||
if (previousType != JOIN && previousType != POST)
|
if (previousType != JOIN && previousType != POST)
|
||||||
throw new FormatException();
|
throw new FormatException();
|
||||||
// track message and broadcast event
|
// track message and broadcast event
|
||||||
@@ -641,8 +640,7 @@ class PrivateGroupManagerImpl extends BdfIncomingMessageHook
|
|||||||
|
|
||||||
private Visibility getVisibility(BdfDictionary meta)
|
private Visibility getVisibility(BdfDictionary meta)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
return Visibility
|
return Visibility.valueOf(meta.getInt(GROUP_KEY_VISIBILITY));
|
||||||
.valueOf(meta.getLong(GROUP_KEY_VISIBILITY).intValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,6 @@ package org.briarproject.briar.privategroup.invitation;
|
|||||||
|
|
||||||
interface GroupInvitationConstants {
|
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
|
// Message metadata keys
|
||||||
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
||||||
String MSG_KEY_PRIVATE_GROUP_ID = "privateGroupId";
|
String MSG_KEY_PRIVATE_GROUP_ID = "privateGroupId";
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.contact.Contact;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
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.BdfList;
|
||||||
import org.briarproject.bramble.api.data.MetadataParser;
|
import org.briarproject.bramble.api.data.MetadataParser;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
@@ -64,7 +63,6 @@ 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.INVITED;
|
||||||
import static org.briarproject.briar.privategroup.invitation.CreatorState.JOINED;
|
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.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.ABORT;
|
||||||
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
|
import static org.briarproject.briar.privategroup.invitation.MessageType.INVITE;
|
||||||
import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
|
import static org.briarproject.briar.privategroup.invitation.MessageType.JOIN;
|
||||||
@@ -116,35 +114,13 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDatabaseOpened(Transaction txn) throws DbException {
|
public void onDatabaseOpened(Transaction txn) throws DbException {
|
||||||
// If the feature flag for this client was set and then cleared, we may
|
// Create a local group to indicate that we've set this client up
|
||||||
// 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,
|
Group localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
|
||||||
MAJOR_VERSION);
|
MAJOR_VERSION);
|
||||||
try {
|
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||||
if (db.containsGroup(txn, localGroup.getId())) {
|
db.addGroup(txn, localGroup);
|
||||||
// If GROUP_KEY_SETUP == true then we're done
|
// Set things up for any pre-existing contacts
|
||||||
BdfDictionary meta = clientHelper
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
.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
|
@Override
|
||||||
@@ -736,9 +712,9 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
|||||||
// get all sessions and their states
|
// get all sessions and their states
|
||||||
Map<GroupId, DeletableSession> sessions = new HashMap<>();
|
Map<GroupId, DeletableSession> sessions = new HashMap<>();
|
||||||
for (BdfDictionary d : metadata.values()) {
|
for (BdfDictionary d : metadata.values()) {
|
||||||
if (!sessionParser.isSession(d)) continue;
|
|
||||||
Session<?> session;
|
Session<?> session;
|
||||||
try {
|
try {
|
||||||
|
if (!sessionParser.isSession(d)) continue;
|
||||||
session = sessionParser.parseSession(g, d);
|
session = sessionParser.parseSession(g, d);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
@@ -800,13 +776,12 @@ class GroupInvitationManagerImpl extends ConversationClientImpl
|
|||||||
|
|
||||||
// assign protocol messages to their sessions
|
// assign protocol messages to their sessions
|
||||||
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
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
|
// parse message metadata and skip messages not visible in UI
|
||||||
MessageMetadata m;
|
MessageMetadata m;
|
||||||
try {
|
try {
|
||||||
|
// skip all sessions, we are only interested in messages
|
||||||
|
BdfDictionary d = entry.getValue();
|
||||||
|
if (sessionParser.isSession(d)) continue;
|
||||||
m = messageParser.parseMetadata(d);
|
m = messageParser.parseMetadata(d);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class GroupInvitationValidator extends BdfMessageValidator {
|
|||||||
@Override
|
@Override
|
||||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||||
BdfList body) throws FormatException {
|
BdfList body) throws FormatException {
|
||||||
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
|
MessageType type = MessageType.fromValue(body.getInt(0));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INVITE:
|
case INVITE:
|
||||||
return validateInviteMessage(m, body);
|
return validateInviteMessage(m, body);
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ class MessageParserImpl implements MessageParser {
|
|||||||
@Override
|
@Override
|
||||||
public MessageMetadata parseMetadata(BdfDictionary meta)
|
public MessageMetadata parseMetadata(BdfDictionary meta)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
MessageType type = MessageType.fromValue(
|
MessageType type =
|
||||||
meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
|
MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE));
|
||||||
GroupId privateGroupId =
|
GroupId privateGroupId =
|
||||||
new GroupId(meta.getRaw(MSG_KEY_PRIVATE_GROUP_ID));
|
new GroupId(meta.getRaw(MSG_KEY_PRIVATE_GROUP_ID));
|
||||||
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ interface SessionParser {
|
|||||||
|
|
||||||
Role getRole(BdfDictionary d) throws FormatException;
|
Role getRole(BdfDictionary d) throws FormatException;
|
||||||
|
|
||||||
boolean isSession(BdfDictionary d);
|
boolean isSession(BdfDictionary d) throws FormatException;
|
||||||
|
|
||||||
Session parseSession(GroupId contactGroupId, BdfDictionary d)
|
Session parseSession(GroupId contactGroupId, BdfDictionary d)
|
||||||
throws FormatException;
|
throws FormatException;
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ class SessionParserImpl implements SessionParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Role getRole(BdfDictionary d) throws FormatException {
|
public Role getRole(BdfDictionary d) throws FormatException {
|
||||||
return Role.fromValue(d.getLong(SESSION_KEY_ROLE).intValue());
|
return Role.fromValue(d.getInt(SESSION_KEY_ROLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSession(BdfDictionary d) {
|
public boolean isSession(BdfDictionary d) throws FormatException {
|
||||||
return d.getBoolean(SESSION_KEY_IS_SESSION, false);
|
return d.getBoolean(SESSION_KEY_IS_SESSION, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getState(BdfDictionary d) throws FormatException {
|
private int getState(BdfDictionary d) throws FormatException {
|
||||||
return d.getLong(SESSION_KEY_STATE).intValue();
|
return d.getInt(SESSION_KEY_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupId getPrivateGroupId(BdfDictionary d) throws FormatException {
|
private GroupId getPrivateGroupId(BdfDictionary d) throws FormatException {
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ abstract class MessageParserImpl<S extends Shareable>
|
|||||||
@Override
|
@Override
|
||||||
public MessageMetadata parseMetadata(BdfDictionary meta)
|
public MessageMetadata parseMetadata(BdfDictionary meta)
|
||||||
throws FormatException {
|
throws FormatException {
|
||||||
MessageType type = MessageType
|
MessageType type =
|
||||||
.fromValue(meta.getLong(MSG_KEY_MESSAGE_TYPE).intValue());
|
MessageType.fromValue(meta.getInt(MSG_KEY_MESSAGE_TYPE));
|
||||||
GroupId shareableId = new GroupId(meta.getRaw(MSG_KEY_SHAREABLE_ID));
|
GroupId shareableId = new GroupId(meta.getRaw(MSG_KEY_SHAREABLE_ID));
|
||||||
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
long timestamp = meta.getLong(MSG_KEY_TIMESTAMP);
|
||||||
boolean local = meta.getBoolean(MSG_KEY_LOCAL);
|
boolean local = meta.getBoolean(MSG_KEY_LOCAL);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ interface SessionParser {
|
|||||||
|
|
||||||
BdfDictionary getAllSessionsQuery();
|
BdfDictionary getAllSessionsQuery();
|
||||||
|
|
||||||
boolean isSession(BdfDictionary d);
|
boolean isSession(BdfDictionary d) throws FormatException;
|
||||||
|
|
||||||
Session parseSession(GroupId contactGroupId, BdfDictionary d)
|
Session parseSession(GroupId contactGroupId, BdfDictionary d)
|
||||||
throws FormatException;
|
throws FormatException;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSession(BdfDictionary d) {
|
public boolean isSession(BdfDictionary d) throws FormatException {
|
||||||
return d.getBoolean(SESSION_KEY_IS_SESSION, false);
|
return d.getBoolean(SESSION_KEY_IS_SESSION, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class SessionParserImpl implements SessionParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getState(BdfDictionary d) throws FormatException {
|
private int getState(BdfDictionary d) throws FormatException {
|
||||||
return d.getLong(SESSION_KEY_STATE).intValue();
|
return d.getInt(SESSION_KEY_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupId getShareableId(BdfDictionary d) throws FormatException {
|
private GroupId getShareableId(BdfDictionary d) throws FormatException {
|
||||||
|
|||||||
@@ -4,12 +4,6 @@ import org.briarproject.briar.client.MessageTrackerConstants;
|
|||||||
|
|
||||||
interface SharingConstants {
|
interface SharingConstants {
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
// Message metadata keys
|
||||||
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
String MSG_KEY_MESSAGE_TYPE = "messageType";
|
||||||
String MSG_KEY_SHAREABLE_ID = "shareableId";
|
String MSG_KEY_SHAREABLE_ID = "shareableId";
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.contact.Contact;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
import org.briarproject.bramble.api.contact.ContactManager.ContactHook;
|
||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
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.BdfList;
|
||||||
import org.briarproject.bramble.api.data.MetadataParser;
|
import org.briarproject.bramble.api.data.MetadataParser;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
@@ -59,7 +58,6 @@ import static org.briarproject.briar.sharing.MessageType.ACCEPT;
|
|||||||
import static org.briarproject.briar.sharing.MessageType.DECLINE;
|
import static org.briarproject.briar.sharing.MessageType.DECLINE;
|
||||||
import static org.briarproject.briar.sharing.MessageType.INVITE;
|
import static org.briarproject.briar.sharing.MessageType.INVITE;
|
||||||
import static org.briarproject.briar.sharing.MessageType.LEAVE;
|
import static org.briarproject.briar.sharing.MessageType.LEAVE;
|
||||||
import static org.briarproject.briar.sharing.SharingConstants.GROUP_KEY_SETUP;
|
|
||||||
import static org.briarproject.briar.sharing.State.LOCAL_INVITED;
|
import static org.briarproject.briar.sharing.State.LOCAL_INVITED;
|
||||||
import static org.briarproject.briar.sharing.State.LOCAL_LEFT;
|
import static org.briarproject.briar.sharing.State.LOCAL_LEFT;
|
||||||
import static org.briarproject.briar.sharing.State.REMOTE_HANGING;
|
import static org.briarproject.briar.sharing.State.REMOTE_HANGING;
|
||||||
@@ -108,35 +106,13 @@ abstract class SharingManagerImpl<S extends Shareable>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDatabaseOpened(Transaction txn) throws DbException {
|
public void onDatabaseOpened(Transaction txn) throws DbException {
|
||||||
// If the feature flag for this client was set and then cleared, we may
|
// Create a local group to indicate that we've set this client up
|
||||||
// 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(getClientId(),
|
Group localGroup = contactGroupFactory.createLocalGroup(getClientId(),
|
||||||
getMajorVersion());
|
getMajorVersion());
|
||||||
try {
|
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||||
if (db.containsGroup(txn, localGroup.getId())) {
|
db.addGroup(txn, localGroup);
|
||||||
// If GROUP_KEY_SETUP == true then we're done
|
// Set things up for any pre-existing contacts
|
||||||
BdfDictionary meta = clientHelper
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
.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
|
@Override
|
||||||
@@ -628,9 +604,9 @@ abstract class SharingManagerImpl<S extends Shareable>
|
|||||||
// get all sessions and their states
|
// get all sessions and their states
|
||||||
Map<GroupId, DeletableSession> sessions = new HashMap<>();
|
Map<GroupId, DeletableSession> sessions = new HashMap<>();
|
||||||
for (BdfDictionary d : metadata.values()) {
|
for (BdfDictionary d : metadata.values()) {
|
||||||
if (!sessionParser.isSession(d)) continue;
|
|
||||||
Session session;
|
Session session;
|
||||||
try {
|
try {
|
||||||
|
if (!sessionParser.isSession(d)) continue;
|
||||||
session = sessionParser.parseSession(contactGroup, d);
|
session = sessionParser.parseSession(contactGroup, d);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
@@ -692,13 +668,12 @@ abstract class SharingManagerImpl<S extends Shareable>
|
|||||||
|
|
||||||
// assign protocol messages to their sessions
|
// assign protocol messages to their sessions
|
||||||
for (Entry<MessageId, BdfDictionary> entry : metadata.entrySet()) {
|
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
|
// parse message metadata and skip messages not visible in UI
|
||||||
MessageMetadata m;
|
MessageMetadata m;
|
||||||
try {
|
try {
|
||||||
|
// skip all sessions, we are only interested in messages
|
||||||
|
BdfDictionary d = entry.getValue();
|
||||||
|
if (sessionParser.isSession(d)) continue;
|
||||||
m = messageParser.parseMetadata(d);
|
m = messageParser.parseMetadata(d);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ abstract class SharingValidator extends BdfMessageValidator {
|
|||||||
@Override
|
@Override
|
||||||
protected BdfMessageContext validateMessage(Message m, Group g,
|
protected BdfMessageContext validateMessage(Message m, Group g,
|
||||||
BdfList body) throws FormatException {
|
BdfList body) throws FormatException {
|
||||||
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
|
MessageType type = MessageType.fromValue(body.getInt(0));
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INVITE:
|
case INVITE:
|
||||||
return validateInviteMessage(m, body);
|
return validateInviteMessage(m, body);
|
||||||
|
|||||||
@@ -651,7 +651,7 @@ public class GroupMessageValidatorTest extends ValidatorTestCase {
|
|||||||
MessageType type, BdfList member,
|
MessageType type, BdfList member,
|
||||||
Collection<MessageId> dependencies) throws FormatException {
|
Collection<MessageId> dependencies) throws FormatException {
|
||||||
BdfDictionary d = c.getDictionary();
|
BdfDictionary d = c.getDictionary();
|
||||||
assertEquals(type.getInt(), d.getLong(KEY_TYPE).intValue());
|
assertEquals(type.getInt(), d.getInt(KEY_TYPE).intValue());
|
||||||
assertEquals(message.getTimestamp(),
|
assertEquals(message.getTimestamp(),
|
||||||
d.getLong(KEY_TIMESTAMP).longValue());
|
d.getLong(KEY_TIMESTAMP).longValue());
|
||||||
assertFalse(d.getBoolean(KEY_READ));
|
assertFalse(d.getBoolean(KEY_READ));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user