mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Removed restricted groups (may be restored after beta testing).
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 948 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 558 B |
Binary file not shown.
|
Before Width: | Height: | Size: 752 B |
Binary file not shown.
|
Before Width: | Height: | Size: 918 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -140,7 +140,6 @@ OnItemClickListener {
|
|||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
for(GroupStatus s : db.getAvailableGroups()) {
|
for(GroupStatus s : db.getAvailableGroups()) {
|
||||||
Group g = s.getGroup();
|
Group g = s.getGroup();
|
||||||
if(g.isRestricted()) continue;
|
|
||||||
if(s.isSubscribed()) {
|
if(s.isSubscribed()) {
|
||||||
try {
|
try {
|
||||||
Collection<GroupMessageHeader> headers =
|
Collection<GroupMessageHeader> headers =
|
||||||
@@ -242,11 +241,8 @@ OnItemClickListener {
|
|||||||
|
|
||||||
public void eventOccurred(DatabaseEvent e) {
|
public void eventOccurred(DatabaseEvent e) {
|
||||||
if(e instanceof GroupMessageAddedEvent) {
|
if(e instanceof GroupMessageAddedEvent) {
|
||||||
Group g = ((GroupMessageAddedEvent) e).getGroup();
|
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
|
||||||
if(!g.isRestricted()) {
|
loadHeaders(((GroupMessageAddedEvent) e).getGroup());
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
|
|
||||||
loadHeaders(g);
|
|
||||||
}
|
|
||||||
} else if(e instanceof MessageExpiredEvent) {
|
} else if(e instanceof MessageExpiredEvent) {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Message expired, reloading");
|
if(LOG.isLoggable(INFO)) LOG.info("Message expired, reloading");
|
||||||
loadHeaders();
|
loadHeaders();
|
||||||
@@ -255,18 +251,12 @@ OnItemClickListener {
|
|||||||
LOG.info("Remote subscriptions changed, reloading");
|
LOG.info("Remote subscriptions changed, reloading");
|
||||||
loadAvailable();
|
loadAvailable();
|
||||||
} else if(e instanceof SubscriptionAddedEvent) {
|
} else if(e instanceof SubscriptionAddedEvent) {
|
||||||
Group g = ((SubscriptionAddedEvent) e).getGroup();
|
if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading");
|
||||||
if(!g.isRestricted()) {
|
loadHeaders();
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading");
|
|
||||||
loadHeaders();
|
|
||||||
}
|
|
||||||
} else if(e instanceof SubscriptionRemovedEvent) {
|
} else if(e instanceof SubscriptionRemovedEvent) {
|
||||||
Group g = ((SubscriptionRemovedEvent) e).getGroup();
|
// Reload the group, expecting NoSuchSubscriptionException
|
||||||
if(!g.isRestricted()) {
|
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
||||||
// Reload the group, expecting NoSuchSubscriptionException
|
loadHeaders(((SubscriptionRemovedEvent) e).getGroup());
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
|
||||||
loadHeaders(g);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,10 +307,8 @@ OnItemClickListener {
|
|||||||
lifecycleManager.waitForDatabase();
|
lifecycleManager.waitForDatabase();
|
||||||
int available = 0;
|
int available = 0;
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
for(GroupStatus s : db.getAvailableGroups()) {
|
for(GroupStatus s : db.getAvailableGroups())
|
||||||
if(!s.getGroup().isRestricted() && !s.isSubscribed())
|
if(!s.isSubscribed()) available++;
|
||||||
available++;
|
|
||||||
}
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Loading available took " + duration + " ms");
|
LOG.info("Loading available took " + duration + " ms");
|
||||||
|
|||||||
@@ -5,11 +5,8 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static net.sf.briar.android.groups.ManageGroupsItem.NONE;
|
import static net.sf.briar.android.groups.ManageGroupsItem.NONE;
|
||||||
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -78,13 +75,10 @@ implements DatabaseListener, OnItemClickListener {
|
|||||||
try {
|
try {
|
||||||
lifecycleManager.waitForDatabase();
|
lifecycleManager.waitForDatabase();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
List<GroupStatus> available = new ArrayList<GroupStatus>();
|
Collection<GroupStatus> available = db.getAvailableGroups();
|
||||||
for(GroupStatus s : db.getAvailableGroups())
|
|
||||||
if(!s.getGroup().isRestricted()) available.add(s);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Load took " + duration + " ms");
|
LOG.info("Load took " + duration + " ms");
|
||||||
available = Collections.unmodifiableList(available);
|
|
||||||
displayAvailableGroups(available);
|
displayAvailableGroups(available);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
if(LOG.isLoggable(WARNING))
|
if(LOG.isLoggable(WARNING))
|
||||||
@@ -124,17 +118,11 @@ implements DatabaseListener, OnItemClickListener {
|
|||||||
LOG.info("Remote subscriptions changed, reloading");
|
LOG.info("Remote subscriptions changed, reloading");
|
||||||
loadAvailableGroups();
|
loadAvailableGroups();
|
||||||
} else if(e instanceof SubscriptionAddedEvent) {
|
} else if(e instanceof SubscriptionAddedEvent) {
|
||||||
Group g = ((SubscriptionAddedEvent) e).getGroup();
|
if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading");
|
||||||
if(g.isRestricted()) {
|
loadAvailableGroups();
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading");
|
|
||||||
loadAvailableGroups();
|
|
||||||
}
|
|
||||||
} else if(e instanceof SubscriptionRemovedEvent) {
|
} else if(e instanceof SubscriptionRemovedEvent) {
|
||||||
Group g = ((SubscriptionRemovedEvent) e).getGroup();
|
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
||||||
if(g.isRestricted()) {
|
loadAvailableGroups();
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
|
||||||
loadAvailableGroups();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,10 +11,7 @@ import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
@@ -213,14 +210,12 @@ implements OnItemSelectedListener, OnClickListener {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
lifecycleManager.waitForDatabase();
|
lifecycleManager.waitForDatabase();
|
||||||
List<Group> groups = new ArrayList<Group>();
|
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
for(Group g : db.getSubscriptions())
|
Collection<Group> groups = db.getSubscriptions();
|
||||||
if(!g.isRestricted()) groups.add(g);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
long duration = System.currentTimeMillis() - now;
|
||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Loading groups took " + duration + " ms");
|
LOG.info("Loading groups took " + duration + " ms");
|
||||||
displayGroups(Collections.unmodifiableList(groups));
|
displayGroups(groups);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
if(LOG.isLoggable(WARNING))
|
if(LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import net.sf.briar.api.messaging.Ack;
|
|||||||
import net.sf.briar.api.messaging.Group;
|
import net.sf.briar.api.messaging.Group;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.GroupStatus;
|
import net.sf.briar.api.messaging.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.LocalGroup;
|
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Offer;
|
import net.sf.briar.api.messaging.Offer;
|
||||||
@@ -62,12 +61,6 @@ public interface DatabaseComponent {
|
|||||||
/** Stores a pseudonym that the user can use to sign messages. */
|
/** Stores a pseudonym that the user can use to sign messages. */
|
||||||
void addLocalAuthor(LocalAuthor a) throws DbException;
|
void addLocalAuthor(LocalAuthor a) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a restricted group to which the user can post messages. Storing
|
|
||||||
* a group does not create a subscription to it.
|
|
||||||
*/
|
|
||||||
void addLocalGroup(LocalGroup g) throws DbException;
|
|
||||||
|
|
||||||
/** Stores a locally generated group message. */
|
/** Stores a locally generated group message. */
|
||||||
void addLocalGroupMessage(Message m) throws DbException;
|
void addLocalGroupMessage(Message m) throws DbException;
|
||||||
|
|
||||||
@@ -194,9 +187,6 @@ public interface DatabaseComponent {
|
|||||||
/** Returns all pseudonyms that the user can use to sign messages. */
|
/** Returns all pseudonyms that the user can use to sign messages. */
|
||||||
Collection<LocalAuthor> getLocalAuthors() throws DbException;
|
Collection<LocalAuthor> getLocalAuthors() throws DbException;
|
||||||
|
|
||||||
/** Returns all restricted groups to which the user can post messages. */
|
|
||||||
Collection<LocalGroup> getLocalGroups() throws DbException;
|
|
||||||
|
|
||||||
/** Returns the local transport properties for all transports. */
|
/** Returns the local transport properties for all transports. */
|
||||||
Map<TransportId, TransportProperties> getLocalProperties()
|
Map<TransportId, TransportProperties> getLocalProperties()
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ public class Group {
|
|||||||
|
|
||||||
private final GroupId id;
|
private final GroupId id;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final byte[] publicKey;
|
private final byte[] salt;
|
||||||
|
|
||||||
public Group(GroupId id, String name, byte[] publicKey) {
|
public Group(GroupId id, String name, byte[] salt) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.publicKey = publicKey;
|
this.salt = salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the group's unique identifier. */
|
/** Returns the group's unique identifier. */
|
||||||
@@ -23,18 +23,12 @@ public class Group {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns true if the group is restricted. */
|
|
||||||
public boolean isRestricted() {
|
|
||||||
return publicKey != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the group is restricted, returns the public key used to verify the
|
* Returns the salt used to distinguish the group from other groups with
|
||||||
* signatures on all messages sent to the group. If the group is
|
* the same name.
|
||||||
* unrestricted, returns null.
|
|
||||||
*/
|
*/
|
||||||
public byte[] getPublicKey() {
|
public byte[] getSalt() {
|
||||||
return publicKey;
|
return salt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,13 +4,9 @@ import java.io.IOException;
|
|||||||
|
|
||||||
public interface GroupFactory {
|
public interface GroupFactory {
|
||||||
|
|
||||||
/** Creates an unrestricted group. */
|
/** Creates a group with the given name and a random salt. */
|
||||||
Group createGroup(String name) throws IOException;
|
Group createGroup(String name) throws IOException;
|
||||||
|
|
||||||
/** Creates a restricted group. */
|
/** Creates a group with the given name and salt. */
|
||||||
Group createGroup(String name, byte[] publicKey) throws IOException;
|
Group createGroup(String name, byte[] salt) throws IOException;
|
||||||
|
|
||||||
/** Creates a restricted group to which the local user can post messages. */
|
|
||||||
LocalGroup createLocalGroup(String name, byte[] publicKey,
|
|
||||||
byte[] privateKey) throws IOException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package net.sf.briar.api.messaging;
|
|
||||||
|
|
||||||
/** A restricted group to which the local user can post messages. */
|
|
||||||
public class LocalGroup extends Group {
|
|
||||||
|
|
||||||
private final byte[] privateKey;
|
|
||||||
|
|
||||||
public LocalGroup(GroupId id, String name, byte[] publicKey,
|
|
||||||
byte[] privateKey) {
|
|
||||||
super(id, name, publicKey);
|
|
||||||
this.privateKey = privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the private key used to sign all messages sent to the group. */
|
|
||||||
public byte[] getPrivateKey() {
|
|
||||||
return privateKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,24 +12,13 @@ public interface MessageFactory {
|
|||||||
Message createPrivateMessage(MessageId parent, String contentType,
|
Message createPrivateMessage(MessageId parent, String contentType,
|
||||||
byte[] body) throws IOException, GeneralSecurityException;
|
byte[] body) throws IOException, GeneralSecurityException;
|
||||||
|
|
||||||
/** Creates an anonymous message to an unrestricted group. */
|
/** Creates an anonymous group message. */
|
||||||
Message createAnonymousMessage(MessageId parent, Group group,
|
Message createAnonymousMessage(MessageId parent, Group group,
|
||||||
String contentType, byte[] body) throws IOException,
|
String contentType, byte[] body) throws IOException,
|
||||||
GeneralSecurityException;
|
GeneralSecurityException;
|
||||||
|
|
||||||
/** Creates an anonymous message to a restricted group. */
|
/** Creates a pseudonymous group message. */
|
||||||
Message createAnonymousMessage(MessageId parent, Group group,
|
|
||||||
PrivateKey groupKey, String contentType, byte[] body)
|
|
||||||
throws IOException, GeneralSecurityException;
|
|
||||||
|
|
||||||
/** Creates a pseudonymous message to an unrestricted group. */
|
|
||||||
Message createPseudonymousMessage(MessageId parent, Group group,
|
Message createPseudonymousMessage(MessageId parent, Group group,
|
||||||
Author author, PrivateKey authorKey, String contentType,
|
Author author, PrivateKey privateKey, String contentType,
|
||||||
byte[] body) throws IOException, GeneralSecurityException;
|
byte[] body) throws IOException, GeneralSecurityException;
|
||||||
|
|
||||||
/** Creates a pseudonymous message to a restricted group. */
|
|
||||||
Message createPseudonymousMessage(MessageId parent, Group group,
|
|
||||||
PrivateKey groupKey, Author author, PrivateKey authorKey,
|
|
||||||
String contentType, byte[] body) throws IOException,
|
|
||||||
GeneralSecurityException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ public interface MessagingConstants {
|
|||||||
/** The maximum length of a group's name in UTF-8 bytes. */
|
/** The maximum length of a group's name in UTF-8 bytes. */
|
||||||
int MAX_GROUP_NAME_LENGTH = 50;
|
int MAX_GROUP_NAME_LENGTH = 50;
|
||||||
|
|
||||||
|
/** The length of a group's random salt in bytes. */
|
||||||
|
int GROUP_SALT_LENGTH = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum length of a message body in bytes. To allow for future
|
* The maximum length of a message body in bytes. To allow for future
|
||||||
* changes in the protocol, this is smaller than the maximum packet length
|
* changes in the protocol, this is smaller than the maximum packet length
|
||||||
@@ -31,7 +34,7 @@ public interface MessagingConstants {
|
|||||||
int MAX_SUBJECT_LENGTH = 100;
|
int MAX_SUBJECT_LENGTH = 100;
|
||||||
|
|
||||||
/** The length of a message's random salt in bytes. */
|
/** The length of a message's random salt in bytes. */
|
||||||
int SALT_LENGTH = 8;
|
int MESSAGE_SALT_LENGTH = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The timestamp of the oldest message in the database is rounded using
|
* The timestamp of the oldest message in the database is rounded using
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ public class UnverifiedMessage {
|
|||||||
private final Author author;
|
private final Author author;
|
||||||
private final String contentType, subject;
|
private final String contentType, subject;
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
private final byte[] raw, authorSig, groupSig;
|
private final byte[] raw, signature;
|
||||||
private final int bodyStart, bodyLength, signedByAuthor, signedByGroup;
|
private final int bodyStart, bodyLength, signedLength;
|
||||||
|
|
||||||
public UnverifiedMessage(MessageId parent, Group group, Author author,
|
public UnverifiedMessage(MessageId parent, Group group, Author author,
|
||||||
String contentType, String subject, long timestamp, byte[] raw,
|
String contentType, String subject, long timestamp, byte[] raw,
|
||||||
byte[] authorSig, byte[] groupSig, int bodyStart, int bodyLength,
|
byte[] signature, int bodyStart, int bodyLength, int signedLength) {
|
||||||
int signedByAuthor, int signedByGroup) {
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.group = group;
|
this.group = group;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
@@ -24,12 +23,10 @@ public class UnverifiedMessage {
|
|||||||
this.subject = subject;
|
this.subject = subject;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
this.raw = raw;
|
this.raw = raw;
|
||||||
this.authorSig = authorSig;
|
this.signature = signature;
|
||||||
this.groupSig = groupSig;
|
|
||||||
this.bodyStart = bodyStart;
|
this.bodyStart = bodyStart;
|
||||||
this.bodyLength = bodyLength;
|
this.bodyLength = bodyLength;
|
||||||
this.signedByAuthor = signedByAuthor;
|
this.signedLength = signedLength;
|
||||||
this.signedByGroup = signedByGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,16 +80,8 @@ public class UnverifiedMessage {
|
|||||||
/**
|
/**
|
||||||
* Returns the author's signature, or null if this is an anonymous message.
|
* Returns the author's signature, or null if this is an anonymous message.
|
||||||
*/
|
*/
|
||||||
public byte[] getAuthorSignature() {
|
public byte[] getSignature() {
|
||||||
return authorSig;
|
return signature;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the group's signature, or null if this is a private message or
|
|
||||||
* a message belonging to an unrestricted group.
|
|
||||||
*/
|
|
||||||
public byte[] getGroupSignature() {
|
|
||||||
return groupSig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the offset of the message body within the serialised message. */
|
/** Returns the offset of the message body within the serialised message. */
|
||||||
@@ -109,15 +98,7 @@ public class UnverifiedMessage {
|
|||||||
* Returns the length in bytes of the data covered by the author's
|
* Returns the length in bytes of the data covered by the author's
|
||||||
* signature.
|
* signature.
|
||||||
*/
|
*/
|
||||||
public int getLengthSignedByAuthor() {
|
public int getSignedLength() {
|
||||||
return signedByAuthor;
|
return signedLength;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the length in bytes of the data covered by the group's
|
|
||||||
* signature.
|
|
||||||
*/
|
|
||||||
public int getLengthSignedByGroup() {
|
|
||||||
return signedByGroup;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,6 @@ import net.sf.briar.api.db.PrivateMessageHeader;
|
|||||||
import net.sf.briar.api.messaging.Group;
|
import net.sf.briar.api.messaging.Group;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.GroupStatus;
|
import net.sf.briar.api.messaging.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.LocalGroup;
|
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Rating;
|
import net.sf.briar.api.messaging.Rating;
|
||||||
@@ -112,14 +111,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void addLocalAuthor(T txn, LocalAuthor a) throws DbException;
|
void addLocalAuthor(T txn, LocalAuthor a) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a restricted group to which the user can post messages. Storing
|
|
||||||
* a group does not create a subscription to it.
|
|
||||||
* <p>
|
|
||||||
* Locking: identity write.
|
|
||||||
*/
|
|
||||||
void addLocalGroup(T txn, LocalGroup g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records a received message as needing to be acknowledged.
|
* Records a received message as needing to be acknowledged.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -192,14 +183,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
boolean containsContact(T txn, ContactId c) throws DbException;
|
boolean containsContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the database contains the given restricted group to
|
|
||||||
* which the user can post messages.
|
|
||||||
* <p>
|
|
||||||
* Locking: identity read.
|
|
||||||
*/
|
|
||||||
boolean containsLocalGroup(T txn, GroupId g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the database contains the given message.
|
* Returns true if the database contains the given message.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -301,6 +284,14 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
MessageId getGroupMessageParent(T txn, MessageId m) throws DbException;
|
MessageId getGroupMessageParent(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the IDs of all group messages posted by the given author.
|
||||||
|
* <p>
|
||||||
|
* Locking: message read.
|
||||||
|
*/
|
||||||
|
Collection<MessageId> getGroupMessages(T txn, AuthorId a)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time at which a connection to each contact was last opened
|
* Returns the time at which a connection to each contact was last opened
|
||||||
* or closed.
|
* or closed.
|
||||||
@@ -323,13 +314,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException;
|
Collection<LocalAuthor> getLocalAuthors(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all restricted groups to which the user can post messages.
|
|
||||||
* <p>
|
|
||||||
* Locking: identity read.
|
|
||||||
*/
|
|
||||||
Collection<LocalGroup> getLocalGroups(T txn) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the local transport properties for all transports.
|
* Returns the local transport properties for all transports.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -556,15 +540,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
Map<GroupId, Integer> getUnreadMessageCounts(T txn) throws DbException;
|
Map<GroupId, Integer> getUnreadMessageCounts(T txn) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the IDs of all messages posted by the given author to
|
|
||||||
* unrestricted groups.
|
|
||||||
* <p>
|
|
||||||
* Locking: message read.
|
|
||||||
*/
|
|
||||||
Collection<MessageId> getUnrestrictedGroupMessages(T txn, AuthorId a)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the contacts to which the given group is visible.
|
* Returns the contacts to which the given group is visible.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -631,13 +606,6 @@ interface Database<T> {
|
|||||||
*/
|
*/
|
||||||
void removeContact(T txn, ContactId c) throws DbException;
|
void removeContact(T txn, ContactId c) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the given restricted group to which the user can post messages.
|
|
||||||
* <p>
|
|
||||||
* Locking: identity write.
|
|
||||||
*/
|
|
||||||
void removeLocalGroup(T txn, GroupId g) throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a message (and all associated state) from the database.
|
* Removes a message (and all associated state) from the database.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ import net.sf.briar.api.messaging.Ack;
|
|||||||
import net.sf.briar.api.messaging.Group;
|
import net.sf.briar.api.messaging.Group;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.GroupStatus;
|
import net.sf.briar.api.messaging.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.LocalGroup;
|
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Offer;
|
import net.sf.briar.api.messaging.Offer;
|
||||||
@@ -285,22 +284,6 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLocalGroup(LocalGroup g) throws DbException {
|
|
||||||
identityLock.writeLock().lock();
|
|
||||||
try {
|
|
||||||
T txn = db.startTransaction();
|
|
||||||
try {
|
|
||||||
db.addLocalGroup(txn, g);
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
} catch(DbException e) {
|
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
identityLock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addLocalGroupMessage(Message m) throws DbException {
|
public void addLocalGroupMessage(Message m) throws DbException {
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
contactLock.readLock().lock();
|
contactLock.readLock().lock();
|
||||||
@@ -362,13 +345,9 @@ DatabaseCleaner.Callback {
|
|||||||
if(!c.equals(sender)) db.addStatus(txn, c, id, false);
|
if(!c.equals(sender)) db.addStatus(txn, c, id, false);
|
||||||
}
|
}
|
||||||
// Calculate and store the message's sendability
|
// Calculate and store the message's sendability
|
||||||
if(m.getGroup().isRestricted()) {
|
int sendability = calculateSendability(txn, m);
|
||||||
db.setSendability(txn, id, 1);
|
db.setSendability(txn, id, sendability);
|
||||||
} else {
|
if(sendability > 0) updateAncestorSendability(txn, id, true);
|
||||||
int sendability = calculateSendability(txn, m);
|
|
||||||
db.setSendability(txn, id, sendability);
|
|
||||||
if(sendability > 0) updateAncestorSendability(txn, id, true);
|
|
||||||
}
|
|
||||||
// Count the bytes stored
|
// Count the bytes stored
|
||||||
synchronized(spaceLock) {
|
synchronized(spaceLock) {
|
||||||
bytesStoredSinceLastCheck += m.getSerialised().length;
|
bytesStoredSinceLastCheck += m.getSerialised().length;
|
||||||
@@ -1066,23 +1045,6 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<LocalGroup> getLocalGroups() throws DbException {
|
|
||||||
identityLock.readLock().lock();
|
|
||||||
try {
|
|
||||||
T txn = db.startTransaction();
|
|
||||||
try {
|
|
||||||
Collection<LocalGroup> groups = db.getLocalGroups(txn);
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
return groups;
|
|
||||||
} catch(DbException e) {
|
|
||||||
db.abortTransaction(txn);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
identityLock.readLock().unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||||
throws DbException {
|
throws DbException {
|
||||||
transportLock.readLock().lock();
|
transportLock.readLock().lock();
|
||||||
@@ -1964,8 +1926,8 @@ DatabaseCleaner.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the sendability of all messages posted by the given author to
|
* Updates the sendability of all group messages posted by the given
|
||||||
* unrestricted groups, and the ancestors of those messages if necessary.
|
* author, and the ancestors of those messages if necessary.
|
||||||
* <p>
|
* <p>
|
||||||
* Locking: message write.
|
* Locking: message write.
|
||||||
* @param increment true if the user's rating for the author has changed
|
* @param increment true if the user's rating for the author has changed
|
||||||
@@ -1973,7 +1935,7 @@ DatabaseCleaner.Callback {
|
|||||||
*/
|
*/
|
||||||
private void updateAuthorSendability(T txn, AuthorId a, boolean increment)
|
private void updateAuthorSendability(T txn, AuthorId a, boolean increment)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
for(MessageId id : db.getUnrestrictedGroupMessages(txn, a)) {
|
for(MessageId id : db.getGroupMessages(txn, a)) {
|
||||||
int sendability = db.getSendability(txn, id);
|
int sendability = db.getSendability(txn, id);
|
||||||
if(increment) {
|
if(increment) {
|
||||||
db.setSendability(txn, id, sendability + 1);
|
db.setSendability(txn, id, sendability + 1);
|
||||||
@@ -2125,8 +2087,6 @@ DatabaseCleaner.Callback {
|
|||||||
throw new NoSuchSubscriptionException();
|
throw new NoSuchSubscriptionException();
|
||||||
affected = db.getVisibility(txn, id);
|
affected = db.getVisibility(txn, id);
|
||||||
db.removeSubscription(txn, id);
|
db.removeSubscription(txn, id);
|
||||||
if(db.containsLocalGroup(txn, id))
|
|
||||||
db.removeLocalGroup(txn, id);
|
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
} catch(DbException e) {
|
} catch(DbException e) {
|
||||||
db.abortTransaction(txn);
|
db.abortTransaction(txn);
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ import net.sf.briar.api.db.PrivateMessageHeader;
|
|||||||
import net.sf.briar.api.messaging.Group;
|
import net.sf.briar.api.messaging.Group;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.GroupStatus;
|
import net.sf.briar.api.messaging.GroupStatus;
|
||||||
import net.sf.briar.api.messaging.LocalGroup;
|
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.Rating;
|
import net.sf.briar.api.messaging.Rating;
|
||||||
@@ -71,15 +70,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " privateKey BINARY NOT NULL,"
|
+ " privateKey BINARY NOT NULL,"
|
||||||
+ " PRIMARY KEY (authorId))";
|
+ " PRIMARY KEY (authorId))";
|
||||||
|
|
||||||
// Locking: identity
|
|
||||||
private static final String CREATE_LOCAL_GROUPS =
|
|
||||||
"CREATE TABLE localGroups"
|
|
||||||
+ " (groupId HASH NOT NULL,"
|
|
||||||
+ " name VARCHAR NOT NULL,"
|
|
||||||
+ " publicKey BINARY NOT NULL,"
|
|
||||||
+ " privateKey BINARY NOT NULL,"
|
|
||||||
+ " PRIMARY KEY (groupId))";
|
|
||||||
|
|
||||||
// Locking: contact
|
// Locking: contact
|
||||||
// Dependents: message, retention, subscription, transport, window
|
// Dependents: message, retention, subscription, transport, window
|
||||||
private static final String CREATE_CONTACTS =
|
private static final String CREATE_CONTACTS =
|
||||||
@@ -104,7 +94,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
"CREATE TABLE groups"
|
"CREATE TABLE groups"
|
||||||
+ " (groupId HASH NOT NULL,"
|
+ " (groupId HASH NOT NULL,"
|
||||||
+ " name VARCHAR NOT NULL,"
|
+ " name VARCHAR NOT NULL,"
|
||||||
+ " publicKey BINARY," // Null for unrestricted groups
|
+ " salt BINARY NOT NULL,"
|
||||||
+ " visibleToAll BOOLEAN NOT NULL,"
|
+ " visibleToAll BOOLEAN NOT NULL,"
|
||||||
+ " PRIMARY KEY (groupId))";
|
+ " PRIMARY KEY (groupId))";
|
||||||
|
|
||||||
@@ -126,7 +116,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " (contactId INT NOT NULL,"
|
+ " (contactId INT NOT NULL,"
|
||||||
+ " groupId HASH NOT NULL," // Not a foreign key
|
+ " groupId HASH NOT NULL," // Not a foreign key
|
||||||
+ " name VARCHAR NOT NULL,"
|
+ " name VARCHAR NOT NULL,"
|
||||||
+ " publicKey BINARY," // Null for unrestricted groups
|
+ " salt BINARY NOT NULL,"
|
||||||
+ " PRIMARY KEY (contactId, groupId),"
|
+ " PRIMARY KEY (contactId, groupId),"
|
||||||
+ " FOREIGN KEY (contactId)"
|
+ " FOREIGN KEY (contactId)"
|
||||||
+ " REFERENCES contacts (contactId)"
|
+ " REFERENCES contacts (contactId)"
|
||||||
@@ -406,7 +396,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
try {
|
try {
|
||||||
s = txn.createStatement();
|
s = txn.createStatement();
|
||||||
s.executeUpdate(insertTypeNames(CREATE_LOCAL_AUTHORS));
|
s.executeUpdate(insertTypeNames(CREATE_LOCAL_AUTHORS));
|
||||||
s.executeUpdate(insertTypeNames(CREATE_LOCAL_GROUPS));
|
|
||||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||||
s.executeUpdate(INDEX_CONTACTS_BY_AUTHOR);
|
s.executeUpdate(INDEX_CONTACTS_BY_AUTHOR);
|
||||||
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
||||||
@@ -750,26 +739,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addLocalGroup(Connection txn, LocalGroup g) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
|
||||||
String sql = "INSERT INTO localGroups"
|
|
||||||
+ " (groupId, name, publicKey, privateKey)"
|
|
||||||
+ " VALUES (?, ?, ?, ?)";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setBytes(1, g.getId().getBytes());
|
|
||||||
ps.setString(2, g.getName());
|
|
||||||
ps.setBytes(3, g.getPublicKey());
|
|
||||||
ps.setBytes(4, g.getPrivateKey());
|
|
||||||
int affected = ps.executeUpdate();
|
|
||||||
if(affected != 1) throw new DbStateException();
|
|
||||||
ps.close();
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMessageToAck(Connection txn, ContactId c, MessageId m)
|
public void addMessageToAck(Connection txn, ContactId c, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -916,13 +885,12 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.close();
|
ps.close();
|
||||||
if(count > MAX_SUBSCRIPTIONS) throw new DbStateException();
|
if(count > MAX_SUBSCRIPTIONS) throw new DbStateException();
|
||||||
if(count == MAX_SUBSCRIPTIONS) return false;
|
if(count == MAX_SUBSCRIPTIONS) return false;
|
||||||
sql = "INSERT INTO groups (groupId, name, publicKey, visibleToAll)"
|
sql = "INSERT INTO groups (groupId, name, salt, visibleToAll)"
|
||||||
+ " VALUES (?, ?, ?, FALSE)";
|
+ " VALUES (?, ?, ?, FALSE)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getId().getBytes());
|
ps.setBytes(1, g.getId().getBytes());
|
||||||
ps.setString(2, g.getName());
|
ps.setString(2, g.getName());
|
||||||
if(g.isRestricted()) ps.setBytes(3, g.getPublicKey());
|
ps.setBytes(3, g.getSalt());
|
||||||
else ps.setNull(3, BINARY);
|
|
||||||
int affected = ps.executeUpdate();
|
int affected = ps.executeUpdate();
|
||||||
if(affected != 1) throw new DbStateException();
|
if(affected != 1) throw new DbStateException();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1059,27 +1027,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsLocalGroup(Connection txn, GroupId g)
|
|
||||||
throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
String sql = "SELECT NULL FROM localGroups WHERE groupId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setBytes(1, g.getBytes());
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
boolean found = rs.next();
|
|
||||||
if(rs.next()) throw new DbStateException();
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
return found;
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(rs);
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsMessage(Connection txn, MessageId m)
|
public boolean containsMessage(Connection txn, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1172,8 +1119,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
// Add all subscribed groups to the list
|
// Add all subscribed groups to the list
|
||||||
String sql = "SELECT groupId, name, publicKey, visibleToAll"
|
String sql = "SELECT groupId, name, salt, visibleToAll FROM groups";
|
||||||
+ " FROM groups";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<GroupStatus> groups = new ArrayList<GroupStatus>();
|
List<GroupStatus> groups = new ArrayList<GroupStatus>();
|
||||||
@@ -1182,24 +1128,23 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
GroupId id = new GroupId(rs.getBytes(1));
|
GroupId id = new GroupId(rs.getBytes(1));
|
||||||
subscribed.add(id);
|
subscribed.add(id);
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
byte[] publicKey = rs.getBytes(3);
|
byte[] salt = rs.getBytes(3);
|
||||||
Group group = new Group(id, name, publicKey);
|
Group group = new Group(id, name, salt);
|
||||||
boolean visibleToAll = rs.getBoolean(4);
|
boolean visibleToAll = rs.getBoolean(4);
|
||||||
groups.add(new GroupStatus(group, true, visibleToAll));
|
groups.add(new GroupStatus(group, true, visibleToAll));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
// Add all contact groups to the list, unless already added
|
// Add all contact groups to the list, unless already added
|
||||||
sql = "SELECT DISTINCT groupId, name, publicKey"
|
sql = "SELECT DISTINCT groupId, name, salt FROM contactGroups";
|
||||||
+ " FROM contactGroups";
|
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId id = new GroupId(rs.getBytes(1));
|
GroupId id = new GroupId(rs.getBytes(1));
|
||||||
if(subscribed.contains(id)) continue;
|
if(subscribed.contains(id)) continue;
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
byte[] publicKey = rs.getBytes(3);
|
byte[] salt = rs.getBytes(3);
|
||||||
Group group = new Group(id, name, publicKey);
|
Group group = new Group(id, name, salt);
|
||||||
groups.add(new GroupStatus(group, false, false));
|
groups.add(new GroupStatus(group, false, false));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
@@ -1340,16 +1285,16 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT name, publicKey FROM groups WHERE groupId = ?";
|
String sql = "SELECT name, salt FROM groups WHERE groupId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
if(!rs.next()) throw new DbStateException();
|
if(!rs.next()) throw new DbStateException();
|
||||||
String name = rs.getString(1);
|
String name = rs.getString(1);
|
||||||
byte[] publicKey = rs.getBytes(2);
|
byte[] salt = rs.getBytes(2);
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
return new Group(g, name, publicKey);
|
return new Group(g, name, salt);
|
||||||
} catch(SQLException e) {
|
} catch(SQLException e) {
|
||||||
tryToClose(rs);
|
tryToClose(rs);
|
||||||
tryToClose(ps);
|
tryToClose(ps);
|
||||||
@@ -1439,6 +1384,31 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<MessageId> getGroupMessages(Connection txn,
|
||||||
|
AuthorId a) throws DbException {
|
||||||
|
PreparedStatement ps = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
String sql = "SELECT messageId"
|
||||||
|
+ " FROM messages AS m"
|
||||||
|
+ " JOIN groups AS g"
|
||||||
|
+ " ON m.groupId = g.groupId"
|
||||||
|
+ " WHERE authorId = ?";
|
||||||
|
ps = txn.prepareStatement(sql);
|
||||||
|
ps.setBytes(1, a.getBytes());
|
||||||
|
rs = ps.executeQuery();
|
||||||
|
List<MessageId> ids = new ArrayList<MessageId>();
|
||||||
|
while(rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
|
rs.close();
|
||||||
|
ps.close();
|
||||||
|
return Collections.unmodifiableList(ids);
|
||||||
|
} catch(SQLException e) {
|
||||||
|
tryToClose(rs);
|
||||||
|
tryToClose(ps);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Map<ContactId, Long> getLastConnected(Connection txn)
|
public Map<ContactId, Long> getLastConnected(Connection txn)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -1512,34 +1482,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<LocalGroup> getLocalGroups(Connection txn)
|
|
||||||
throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
String sql = "SELECT groupId, name, publicKey, privateKey"
|
|
||||||
+ " FROM localGroups";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
List<LocalGroup> groups = new ArrayList<LocalGroup>();
|
|
||||||
while(rs.next()) {
|
|
||||||
GroupId groupId = new GroupId(rs.getBytes(1));
|
|
||||||
String name = rs.getString(2);
|
|
||||||
byte[] publicKey = rs.getBytes(3);
|
|
||||||
byte[] privateKey = rs.getBytes(4);
|
|
||||||
groups.add(new LocalGroup(groupId, name, publicKey,
|
|
||||||
privateKey));
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
return Collections.unmodifiableList(groups);
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(rs);
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<TransportId, TransportProperties> getLocalProperties(
|
public Map<TransportId, TransportProperties> getLocalProperties(
|
||||||
Connection txn) throws DbException {
|
Connection txn) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -2223,7 +2165,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getStarredFlag(Connection txn, MessageId m) throws DbException {
|
public boolean getStarredFlag(Connection txn, MessageId m)
|
||||||
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
@@ -2249,15 +2192,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT groupId, name, publicKey FROM groups";
|
String sql = "SELECT groupId, name, salt FROM groups";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<Group> subs = new ArrayList<Group>();
|
List<Group> subs = new ArrayList<Group>();
|
||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId groupId = new GroupId(rs.getBytes(1));
|
GroupId groupId = new GroupId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
byte[] publicKey = rs.getBytes(3);
|
byte[] salt = rs.getBytes(3);
|
||||||
subs.add(new Group(groupId, name, publicKey));
|
subs.add(new Group(groupId, name, salt));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -2274,7 +2217,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT groupId, name, publicKey FROM contactGroups"
|
String sql = "SELECT groupId, name, salt FROM contactGroups"
|
||||||
+ " WHERE contactId = ?";
|
+ " WHERE contactId = ?";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
@@ -2283,8 +2226,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId groupId = new GroupId(rs.getBytes(1));
|
GroupId groupId = new GroupId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
byte[] publicKey = rs.getBytes(3);
|
byte[] salt = rs.getBytes(3);
|
||||||
subs.add(new Group(groupId, name, publicKey));
|
subs.add(new Group(groupId, name, salt));
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -2336,7 +2279,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
String sql = "SELECT g.groupId, name, publicKey,"
|
String sql = "SELECT g.groupId, name, salt,"
|
||||||
+ " localVersion, txCount"
|
+ " localVersion, txCount"
|
||||||
+ " FROM groups AS g"
|
+ " FROM groups AS g"
|
||||||
+ " JOIN groupVisibilities AS vis"
|
+ " JOIN groupVisibilities AS vis"
|
||||||
@@ -2356,8 +2299,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
GroupId groupId = new GroupId(rs.getBytes(1));
|
GroupId groupId = new GroupId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
byte[] key = rs.getBytes(3);
|
byte[] salt = rs.getBytes(3);
|
||||||
subs.add(new Group(groupId, name, key));
|
subs.add(new Group(groupId, name, salt));
|
||||||
version = rs.getLong(4);
|
version = rs.getLong(4);
|
||||||
txCount = rs.getInt(5);
|
txCount = rs.getInt(5);
|
||||||
}
|
}
|
||||||
@@ -2564,32 +2507,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<MessageId> getUnrestrictedGroupMessages(Connection txn,
|
|
||||||
AuthorId a) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
String sql = "SELECT messageId"
|
|
||||||
+ " FROM messages AS m"
|
|
||||||
+ " JOIN groups AS g"
|
|
||||||
+ " ON m.groupId = g.groupId"
|
|
||||||
+ " WHERE authorId = ?"
|
|
||||||
+ " AND publicKey IS NULL";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setBytes(1, a.getBytes());
|
|
||||||
rs = ps.executeQuery();
|
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
|
||||||
while(rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
|
||||||
rs.close();
|
|
||||||
ps.close();
|
|
||||||
return Collections.unmodifiableList(ids);
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(rs);
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<ContactId> getVisibility(Connection txn, GroupId g)
|
public Collection<ContactId> getVisibility(Connection txn, GroupId g)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
@@ -2808,21 +2725,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeLocalGroup(Connection txn, GroupId g) throws DbException {
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
|
||||||
String sql = "DELETE FROM localGroups WHERE groupId = ?";
|
|
||||||
ps = txn.prepareStatement(sql);
|
|
||||||
ps.setBytes(1, g.getBytes());
|
|
||||||
int affected = ps.executeUpdate();
|
|
||||||
if(affected != 1) throw new DbStateException();
|
|
||||||
ps.close();
|
|
||||||
} catch(SQLException e) {
|
|
||||||
tryToClose(ps);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
public void removeMessage(Connection txn, MessageId m) throws DbException {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
@@ -3395,15 +3297,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
// Store the new subscriptions, if any
|
// Store the new subscriptions, if any
|
||||||
if(subs.isEmpty()) return true;
|
if(subs.isEmpty()) return true;
|
||||||
sql = "INSERT INTO contactGroups"
|
sql = "INSERT INTO contactGroups"
|
||||||
+ " (contactId, groupId, name, publicKey)"
|
+ " (contactId, groupId, name, salt)"
|
||||||
+ " VALUES (?, ?, ?, ?)";
|
+ " VALUES (?, ?, ?, ?)";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
for(Group g : subs) {
|
for(Group g : subs) {
|
||||||
ps.setBytes(2, g.getId().getBytes());
|
ps.setBytes(2, g.getId().getBytes());
|
||||||
ps.setString(3, g.getName());
|
ps.setString(3, g.getName());
|
||||||
if(g.isRestricted()) ps.setBytes(4, g.getPublicKey());
|
ps.setBytes(4, g.getSalt());
|
||||||
else ps.setNull(4, BINARY);
|
|
||||||
ps.addBatch();
|
ps.addBatch();
|
||||||
}
|
}
|
||||||
int[] batchAffected = ps.executeBatch();
|
int[] batchAffected = ps.executeBatch();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.messaging;
|
package net.sf.briar.messaging;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Types.GROUP;
|
import static net.sf.briar.api.messaging.Types.GROUP;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
@@ -10,7 +11,6 @@ import net.sf.briar.api.crypto.MessageDigest;
|
|||||||
import net.sf.briar.api.messaging.Group;
|
import net.sf.briar.api.messaging.Group;
|
||||||
import net.sf.briar.api.messaging.GroupFactory;
|
import net.sf.briar.api.messaging.GroupFactory;
|
||||||
import net.sf.briar.api.messaging.GroupId;
|
import net.sf.briar.api.messaging.GroupId;
|
||||||
import net.sf.briar.api.messaging.LocalGroup;
|
|
||||||
import net.sf.briar.api.serial.Writer;
|
import net.sf.briar.api.serial.Writer;
|
||||||
import net.sf.briar.api.serial.WriterFactory;
|
import net.sf.briar.api.serial.WriterFactory;
|
||||||
|
|
||||||
@@ -28,29 +28,20 @@ class GroupFactoryImpl implements GroupFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Group createGroup(String name) throws IOException {
|
public Group createGroup(String name) throws IOException {
|
||||||
return createGroup(name, null);
|
byte[] salt = new byte[GROUP_SALT_LENGTH];
|
||||||
|
crypto.getSecureRandom().nextBytes(salt);
|
||||||
|
return createGroup(name, salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Group createGroup(String name, byte[] publicKey) throws IOException {
|
public Group createGroup(String name, byte[] salt) throws IOException {
|
||||||
GroupId id = getId(name, publicKey);
|
|
||||||
return new Group(id, name, publicKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalGroup createLocalGroup(String name, byte[] publicKey,
|
|
||||||
byte[] privateKey) throws IOException {
|
|
||||||
GroupId id = getId(name, publicKey);
|
|
||||||
return new LocalGroup(id, name, publicKey, privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroupId getId(String name, byte[] publicKey) throws IOException {
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
Writer w = writerFactory.createWriter(out);
|
Writer w = writerFactory.createWriter(out);
|
||||||
w.writeStructId(GROUP);
|
w.writeStructId(GROUP);
|
||||||
w.writeString(name);
|
w.writeString(name);
|
||||||
if(publicKey == null) w.writeNull();
|
w.writeBytes(salt);
|
||||||
else w.writeBytes(publicKey);
|
|
||||||
MessageDigest messageDigest = crypto.getMessageDigest();
|
MessageDigest messageDigest = crypto.getMessageDigest();
|
||||||
messageDigest.update(out.toByteArray());
|
messageDigest.update(out.toByteArray());
|
||||||
return new GroupId(messageDigest.digest());
|
GroupId id = new GroupId(messageDigest.digest());
|
||||||
|
return new Group(id, name, salt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import static net.sf.briar.api.messaging.MessagingConstants.MAX_BODY_LENGTH;
|
|||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.SALT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MESSAGE_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Types.AUTHOR;
|
import static net.sf.briar.api.messaging.Types.AUTHOR;
|
||||||
import static net.sf.briar.api.messaging.Types.GROUP;
|
import static net.sf.briar.api.messaging.Types.GROUP;
|
||||||
import static net.sf.briar.api.messaging.Types.MESSAGE;
|
import static net.sf.briar.api.messaging.Types.MESSAGE;
|
||||||
@@ -39,7 +39,7 @@ import com.google.inject.Inject;
|
|||||||
|
|
||||||
class MessageFactoryImpl implements MessageFactory {
|
class MessageFactoryImpl implements MessageFactory {
|
||||||
|
|
||||||
private final Signature authorSignature, groupSignature;
|
private final Signature signature;
|
||||||
private final SecureRandom random;
|
private final SecureRandom random;
|
||||||
private final MessageDigest messageDigest;
|
private final MessageDigest messageDigest;
|
||||||
private final WriterFactory writerFactory;
|
private final WriterFactory writerFactory;
|
||||||
@@ -49,8 +49,7 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
@Inject
|
@Inject
|
||||||
MessageFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory,
|
MessageFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory,
|
||||||
Clock clock) {
|
Clock clock) {
|
||||||
authorSignature = crypto.getSignature();
|
signature = crypto.getSignature();
|
||||||
groupSignature = crypto.getSignature();
|
|
||||||
random = crypto.getSecureRandom();
|
random = crypto.getSecureRandom();
|
||||||
messageDigest = crypto.getMessageDigest();
|
messageDigest = crypto.getMessageDigest();
|
||||||
this.writerFactory = writerFactory;
|
this.writerFactory = writerFactory;
|
||||||
@@ -60,46 +59,27 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
|
|
||||||
public Message createPrivateMessage(MessageId parent, String contentType,
|
public Message createPrivateMessage(MessageId parent, String contentType,
|
||||||
byte[] body) throws IOException, GeneralSecurityException {
|
byte[] body) throws IOException, GeneralSecurityException {
|
||||||
return createMessage(parent, null, null, null, null, contentType, body);
|
return createMessage(parent, null, null, null, contentType, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message createAnonymousMessage(MessageId parent, Group group,
|
public Message createAnonymousMessage(MessageId parent, Group group,
|
||||||
String contentType, byte[] body) throws IOException,
|
String contentType, byte[] body) throws IOException,
|
||||||
GeneralSecurityException {
|
GeneralSecurityException {
|
||||||
return createMessage(parent, group, null, null, null, contentType,
|
return createMessage(parent, group, null, null, contentType, body);
|
||||||
body);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Message createAnonymousMessage(MessageId parent, Group group,
|
|
||||||
PrivateKey groupKey, String contentType, byte[] body)
|
|
||||||
throws IOException, GeneralSecurityException {
|
|
||||||
return createMessage(parent, group, groupKey, null, null, contentType,
|
|
||||||
body);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message createPseudonymousMessage(MessageId parent, Group group,
|
public Message createPseudonymousMessage(MessageId parent, Group group,
|
||||||
Author author, PrivateKey authorKey, String contentType,
|
Author author, PrivateKey privateKey, String contentType,
|
||||||
byte[] body) throws IOException, GeneralSecurityException {
|
byte[] body) throws IOException, GeneralSecurityException {
|
||||||
return createMessage(parent, group, null, author, authorKey,
|
return createMessage(parent, group, author, privateKey, contentType,
|
||||||
contentType, body);
|
body);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message createPseudonymousMessage(MessageId parent, Group group,
|
private Message createMessage(MessageId parent, Group group, Author author,
|
||||||
PrivateKey groupKey, Author author, PrivateKey authorKey,
|
PrivateKey privateKey, String contentType, byte[] body)
|
||||||
String contentType, byte[] body) throws IOException,
|
throws IOException, GeneralSecurityException {
|
||||||
GeneralSecurityException {
|
|
||||||
return createMessage(parent, group, groupKey, author, authorKey,
|
|
||||||
contentType, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Message createMessage(MessageId parent, Group group,
|
|
||||||
PrivateKey groupKey, Author author, PrivateKey authorKey,
|
|
||||||
String contentType, byte[] body) throws IOException,
|
|
||||||
GeneralSecurityException {
|
|
||||||
// Validate the arguments
|
// Validate the arguments
|
||||||
if((author == null) != (authorKey == null))
|
if((author == null) != (privateKey == null))
|
||||||
throw new IllegalArgumentException();
|
|
||||||
if((group == null || !group.isRestricted()) != (groupKey == null))
|
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if(contentType.getBytes("UTF-8").length > MAX_CONTENT_TYPE_LENGTH)
|
if(contentType.getBytes("UTF-8").length > MAX_CONTENT_TYPE_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
@@ -113,17 +93,11 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
w.addConsumer(counting);
|
w.addConsumer(counting);
|
||||||
Consumer digestingConsumer = new DigestingConsumer(messageDigest);
|
Consumer digestingConsumer = new DigestingConsumer(messageDigest);
|
||||||
w.addConsumer(digestingConsumer);
|
w.addConsumer(digestingConsumer);
|
||||||
Consumer authorConsumer = null;
|
Consumer signingConsumer = null;
|
||||||
if(authorKey != null) {
|
if(privateKey != null) {
|
||||||
authorSignature.initSign(authorKey);
|
signature.initSign(privateKey);
|
||||||
authorConsumer = new SigningConsumer(authorSignature);
|
signingConsumer = new SigningConsumer(signature);
|
||||||
w.addConsumer(authorConsumer);
|
w.addConsumer(signingConsumer);
|
||||||
}
|
|
||||||
Consumer groupConsumer = null;
|
|
||||||
if(groupKey != null) {
|
|
||||||
groupSignature.initSign(groupKey);
|
|
||||||
groupConsumer = new SigningConsumer(groupSignature);
|
|
||||||
w.addConsumer(groupConsumer);
|
|
||||||
}
|
}
|
||||||
// Write the message
|
// Write the message
|
||||||
w.writeStructId(MESSAGE);
|
w.writeStructId(MESSAGE);
|
||||||
@@ -136,32 +110,22 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
w.writeString(contentType);
|
w.writeString(contentType);
|
||||||
long timestamp = clock.currentTimeMillis();
|
long timestamp = clock.currentTimeMillis();
|
||||||
w.writeInt64(timestamp);
|
w.writeInt64(timestamp);
|
||||||
byte[] salt = new byte[SALT_LENGTH];
|
byte[] salt = new byte[MESSAGE_SALT_LENGTH];
|
||||||
random.nextBytes(salt);
|
random.nextBytes(salt);
|
||||||
w.writeBytes(salt);
|
w.writeBytes(salt);
|
||||||
w.writeBytes(body);
|
w.writeBytes(body);
|
||||||
int bodyStart = (int) counting.getCount() - body.length;
|
int bodyStart = (int) counting.getCount() - body.length;
|
||||||
// Sign the message with the author's private key, if there is one
|
// Sign the message with the author's private key, if there is one
|
||||||
if(authorKey == null) {
|
if(privateKey == null) {
|
||||||
w.writeNull();
|
w.writeNull();
|
||||||
} else {
|
} else {
|
||||||
w.removeConsumer(authorConsumer);
|
w.removeConsumer(signingConsumer);
|
||||||
byte[] sig = authorSignature.sign();
|
byte[] sig = signature.sign();
|
||||||
if(sig.length > MAX_SIGNATURE_LENGTH)
|
if(sig.length > MAX_SIGNATURE_LENGTH)
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
w.writeBytes(sig);
|
w.writeBytes(sig);
|
||||||
}
|
}
|
||||||
// Sign the message with the group's private key, if there is one
|
// Hash the message, including the signature, to get the message ID
|
||||||
if(groupKey == null) {
|
|
||||||
w.writeNull();
|
|
||||||
} else {
|
|
||||||
w.removeConsumer(groupConsumer);
|
|
||||||
byte[] sig = groupSignature.sign();
|
|
||||||
if(sig.length > MAX_SIGNATURE_LENGTH)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
w.writeBytes(sig);
|
|
||||||
}
|
|
||||||
// Hash the message, including the signatures, to get the message ID
|
|
||||||
w.removeConsumer(digestingConsumer);
|
w.removeConsumer(digestingConsumer);
|
||||||
MessageId id = new MessageId(messageDigest.digest());
|
MessageId id = new MessageId(messageDigest.digest());
|
||||||
// If the content type is text/plain, extract a subject line
|
// If the content type is text/plain, extract a subject line
|
||||||
@@ -181,8 +145,7 @@ class MessageFactoryImpl implements MessageFactory {
|
|||||||
private void writeGroup(Writer w, Group g) throws IOException {
|
private void writeGroup(Writer w, Group g) throws IOException {
|
||||||
w.writeStructId(GROUP);
|
w.writeStructId(GROUP);
|
||||||
w.writeString(g.getName());
|
w.writeString(g.getName());
|
||||||
if(g.isRestricted()) w.writeBytes(g.getPublicKey());
|
w.writeBytes(g.getSalt());
|
||||||
else w.writeNull();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeAuthor(Writer w, Author a) throws IOException {
|
private void writeAuthor(Writer w, Author a) throws IOException {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import static net.sf.briar.api.messaging.MessagingConstants.MAX_BODY_LENGTH;
|
|||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.MessagingConstants.SALT_LENGTH;
|
import static net.sf.briar.api.messaging.MessagingConstants.MESSAGE_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Types.MESSAGE;
|
import static net.sf.briar.api.messaging.Types.MESSAGE;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -67,8 +67,8 @@ class MessageReader implements StructReader<UnverifiedMessage> {
|
|||||||
long timestamp = r.readInt64();
|
long timestamp = r.readInt64();
|
||||||
if(timestamp < 0) throw new FormatException();
|
if(timestamp < 0) throw new FormatException();
|
||||||
// Read the salt
|
// Read the salt
|
||||||
byte[] salt = r.readBytes(SALT_LENGTH);
|
byte[] salt = r.readBytes(MESSAGE_SALT_LENGTH);
|
||||||
if(salt.length < SALT_LENGTH) throw new FormatException();
|
if(salt.length < MESSAGE_SALT_LENGTH) throw new FormatException();
|
||||||
// Read the message body
|
// Read the message body
|
||||||
byte[] body = r.readBytes(MAX_BODY_LENGTH);
|
byte[] body = r.readBytes(MAX_BODY_LENGTH);
|
||||||
// If the content type is text/plain, extract a subject line
|
// If the content type is text/plain, extract a subject line
|
||||||
@@ -84,23 +84,17 @@ class MessageReader implements StructReader<UnverifiedMessage> {
|
|||||||
// Record the offset of the body within the message
|
// Record the offset of the body within the message
|
||||||
int bodyStart = (int) counting.getCount() - body.length;
|
int bodyStart = (int) counting.getCount() - body.length;
|
||||||
// Record the length of the data covered by the author's signature
|
// Record the length of the data covered by the author's signature
|
||||||
int signedByAuthor = (int) counting.getCount();
|
int signedLength = (int) counting.getCount();
|
||||||
// Read the author's signature, if there is one
|
// Read the author's signature, if there is one
|
||||||
byte[] authorSig = null;
|
byte[] signature = null;
|
||||||
if(author == null) r.readNull();
|
if(author == null) r.readNull();
|
||||||
else authorSig = r.readBytes(MAX_SIGNATURE_LENGTH);
|
else signature = r.readBytes(MAX_SIGNATURE_LENGTH);
|
||||||
// Record the length of the data covered by the group's signature
|
// The signature will be verified later
|
||||||
int signedByGroup = (int) counting.getCount();
|
|
||||||
// Read the group's signature, if there is one
|
|
||||||
byte[] groupSig = null;
|
|
||||||
if(group == null || !group.isRestricted()) r.readNull();
|
|
||||||
else groupSig = r.readBytes(MAX_SIGNATURE_LENGTH);
|
|
||||||
// That's all, folks
|
|
||||||
r.removeConsumer(counting);
|
r.removeConsumer(counting);
|
||||||
r.removeConsumer(copying);
|
r.removeConsumer(copying);
|
||||||
byte[] raw = copying.getCopy();
|
byte[] raw = copying.getCopy();
|
||||||
return new UnverifiedMessage(parent, group, author, contentType,
|
return new UnverifiedMessage(parent, group, author, contentType,
|
||||||
subject, timestamp, raw, authorSig, groupSig, bodyStart,
|
subject, timestamp, raw, signature, bodyStart, body.length,
|
||||||
body.length, signedByAuthor, signedByGroup);
|
signedLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import net.sf.briar.api.crypto.KeyParser;
|
|||||||
import net.sf.briar.api.crypto.MessageDigest;
|
import net.sf.briar.api.crypto.MessageDigest;
|
||||||
import net.sf.briar.api.crypto.PublicKey;
|
import net.sf.briar.api.crypto.PublicKey;
|
||||||
import net.sf.briar.api.crypto.Signature;
|
import net.sf.briar.api.crypto.Signature;
|
||||||
import net.sf.briar.api.messaging.Group;
|
|
||||||
import net.sf.briar.api.messaging.Message;
|
import net.sf.briar.api.messaging.Message;
|
||||||
import net.sf.briar.api.messaging.MessageId;
|
import net.sf.briar.api.messaging.MessageId;
|
||||||
import net.sf.briar.api.messaging.MessageVerifier;
|
import net.sf.briar.api.messaging.MessageVerifier;
|
||||||
@@ -31,7 +30,7 @@ class MessageVerifierImpl implements MessageVerifier {
|
|||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
MessageDigest messageDigest = crypto.getMessageDigest();
|
MessageDigest messageDigest = crypto.getMessageDigest();
|
||||||
Signature signature = crypto.getSignature();
|
Signature signature = crypto.getSignature();
|
||||||
// Hash the message, including the signatures, to get the message ID
|
// Hash the message, including the signature, to get the message ID
|
||||||
byte[] raw = m.getSerialised();
|
byte[] raw = m.getSerialised();
|
||||||
messageDigest.update(raw);
|
messageDigest.update(raw);
|
||||||
MessageId id = new MessageId(messageDigest.digest());
|
MessageId id = new MessageId(messageDigest.digest());
|
||||||
@@ -40,20 +39,11 @@ class MessageVerifierImpl implements MessageVerifier {
|
|||||||
if(author != null) {
|
if(author != null) {
|
||||||
PublicKey k = keyParser.parsePublicKey(author.getPublicKey());
|
PublicKey k = keyParser.parsePublicKey(author.getPublicKey());
|
||||||
signature.initVerify(k);
|
signature.initVerify(k);
|
||||||
signature.update(raw, 0, m.getLengthSignedByAuthor());
|
signature.update(raw, 0, m.getSignedLength());
|
||||||
if(!signature.verify(m.getAuthorSignature()))
|
if(!signature.verify(m.getSignature()))
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
}
|
}
|
||||||
// Verify the group's signature, if there is one
|
return new MessageImpl(id, m.getParent(), m.getGroup(), author,
|
||||||
Group group = m.getGroup();
|
|
||||||
if(group != null && group.isRestricted()) {
|
|
||||||
PublicKey k = keyParser.parsePublicKey(group.getPublicKey());
|
|
||||||
signature.initVerify(k);
|
|
||||||
signature.update(raw, 0, m.getLengthSignedByGroup());
|
|
||||||
if(!signature.verify(m.getGroupSignature()))
|
|
||||||
throw new GeneralSecurityException();
|
|
||||||
}
|
|
||||||
return new MessageImpl(id, m.getParent(), group, author,
|
|
||||||
m.getContentType(), m.getSubject(), m.getTimestamp(), raw,
|
m.getContentType(), m.getSubject(), m.getTimestamp(), raw,
|
||||||
m.getBodyStart(), m.getBodyLength());
|
m.getBodyStart(), m.getBodyLength());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,8 +133,7 @@ class PacketWriterImpl implements PacketWriter {
|
|||||||
for(Group g : u.getGroups()) {
|
for(Group g : u.getGroups()) {
|
||||||
w.writeStructId(GROUP);
|
w.writeStructId(GROUP);
|
||||||
w.writeString(g.getName());
|
w.writeString(g.getName());
|
||||||
if(g.isRestricted()) w.writeBytes(g.getPublicKey());
|
w.writeBytes(g.getSalt());
|
||||||
else w.writeNull();
|
|
||||||
}
|
}
|
||||||
w.writeListEnd();
|
w.writeListEnd();
|
||||||
w.writeInt64(u.getVersion());
|
w.writeInt64(u.getVersion());
|
||||||
|
|||||||
@@ -68,8 +68,8 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
private final ContactId contactId;
|
private final ContactId contactId;
|
||||||
private final byte[] secret;
|
private final byte[] secret;
|
||||||
private final Author author;
|
private final Author author;
|
||||||
private final Group group, group1;
|
private final Group group;
|
||||||
private final Message message, message1, message2, message3;
|
private final Message message, message1;
|
||||||
private final String authorName = "Alice";
|
private final String authorName = "Alice";
|
||||||
private final String contentType = "text/plain";
|
private final String contentType = "text/plain";
|
||||||
private final String messageBody = "Hello world";
|
private final String messageBody = "Hello world";
|
||||||
@@ -93,33 +93,23 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
// Create a shared secret
|
// Create a shared secret
|
||||||
secret = new byte[32];
|
secret = new byte[32];
|
||||||
new Random().nextBytes(secret);
|
new Random().nextBytes(secret);
|
||||||
// Create two groups: one restricted, one unrestricted
|
// Create a group
|
||||||
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
GroupFactory groupFactory = i.getInstance(GroupFactory.class);
|
||||||
group = groupFactory.createGroup("Unrestricted group");
|
group = groupFactory.createGroup("Group");
|
||||||
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
|
||||||
KeyPair groupKeyPair = crypto.generateSignatureKeyPair();
|
|
||||||
group1 = groupFactory.createGroup("Restricted group",
|
|
||||||
groupKeyPair.getPublic().getEncoded());
|
|
||||||
// Create an author
|
// Create an author
|
||||||
AuthorFactory authorFactory = i.getInstance(AuthorFactory.class);
|
AuthorFactory authorFactory = i.getInstance(AuthorFactory.class);
|
||||||
|
CryptoComponent crypto = i.getInstance(CryptoComponent.class);
|
||||||
KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
|
KeyPair authorKeyPair = crypto.generateSignatureKeyPair();
|
||||||
author = authorFactory.createAuthor(authorName,
|
author = authorFactory.createAuthor(authorName,
|
||||||
authorKeyPair.getPublic().getEncoded());
|
authorKeyPair.getPublic().getEncoded());
|
||||||
// Create two messages to each group: one anonymous, one pseudonymous
|
// Create two messages to the group: one anonymous, one pseudonymous
|
||||||
MessageFactory messageFactory = i.getInstance(MessageFactory.class);
|
MessageFactory messageFactory = i.getInstance(MessageFactory.class);
|
||||||
message = messageFactory.createAnonymousMessage(null, group,
|
message = messageFactory.createAnonymousMessage(null, group,
|
||||||
contentType, messageBody.getBytes("UTF-8"));
|
contentType, messageBody.getBytes("UTF-8"));
|
||||||
message1 = messageFactory.createAnonymousMessage(null, group1,
|
message1 = messageFactory.createPseudonymousMessage(null, group,
|
||||||
groupKeyPair.getPrivate(), contentType,
|
|
||||||
messageBody.getBytes("UTF-8"));
|
|
||||||
message2 = messageFactory.createPseudonymousMessage(null, group,
|
|
||||||
author, authorKeyPair.getPrivate(), contentType,
|
author, authorKeyPair.getPrivate(), contentType,
|
||||||
messageBody.getBytes("UTF-8"));
|
messageBody.getBytes("UTF-8"));
|
||||||
message3 = messageFactory.createPseudonymousMessage(null, group1,
|
messageIds = Arrays.asList(message.getId(), message1.getId());
|
||||||
groupKeyPair.getPrivate(), author, authorKeyPair.getPrivate(),
|
|
||||||
contentType, messageBody.getBytes("UTF-8"));
|
|
||||||
messageIds = Arrays.asList(message.getId(), message1.getId(),
|
|
||||||
message2.getId(), message3.getId());
|
|
||||||
// Create some transport properties
|
// Create some transport properties
|
||||||
transportId = new TransportId(TestUtils.getRandomId());
|
transportId = new TransportId(TestUtils.getRandomId());
|
||||||
transportProperties = new TransportProperties(Collections.singletonMap(
|
transportProperties = new TransportProperties(Collections.singletonMap(
|
||||||
@@ -145,18 +135,14 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
|
|
||||||
writer.writeMessage(message.getSerialised());
|
writer.writeMessage(message.getSerialised());
|
||||||
writer.writeMessage(message1.getSerialised());
|
writer.writeMessage(message1.getSerialised());
|
||||||
writer.writeMessage(message2.getSerialised());
|
|
||||||
writer.writeMessage(message3.getSerialised());
|
|
||||||
|
|
||||||
writer.writeOffer(new Offer(messageIds));
|
writer.writeOffer(new Offer(messageIds));
|
||||||
|
|
||||||
BitSet requested = new BitSet(4);
|
BitSet requested = new BitSet(2);
|
||||||
requested.set(1);
|
requested.set(1);
|
||||||
requested.set(3);
|
writer.writeRequest(new Request(requested, 2));
|
||||||
writer.writeRequest(new Request(requested, 4));
|
|
||||||
|
|
||||||
SubscriptionUpdate su = new SubscriptionUpdate(
|
SubscriptionUpdate su = new SubscriptionUpdate(Arrays.asList(group), 1);
|
||||||
Arrays.asList(group, group1), 1);
|
|
||||||
writer.writeSubscriptionUpdate(su);
|
writer.writeSubscriptionUpdate(su);
|
||||||
|
|
||||||
TransportUpdate tu = new TransportUpdate(transportId,
|
TransportUpdate tu = new TransportUpdate(transportId,
|
||||||
@@ -191,12 +177,7 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
assertTrue(reader.hasMessage());
|
assertTrue(reader.hasMessage());
|
||||||
m = reader.readMessage();
|
m = reader.readMessage();
|
||||||
checkMessageEquality(message1, messageVerifier.verifyMessage(m));
|
checkMessageEquality(message1, messageVerifier.verifyMessage(m));
|
||||||
assertTrue(reader.hasMessage());
|
assertFalse(reader.hasMessage());
|
||||||
m = reader.readMessage();
|
|
||||||
checkMessageEquality(message2, messageVerifier.verifyMessage(m));
|
|
||||||
assertTrue(reader.hasMessage());
|
|
||||||
m = reader.readMessage();
|
|
||||||
checkMessageEquality(message3, messageVerifier.verifyMessage(m));
|
|
||||||
|
|
||||||
// Read the offer
|
// Read the offer
|
||||||
assertTrue(reader.hasOffer());
|
assertTrue(reader.hasOffer());
|
||||||
@@ -209,15 +190,13 @@ public class ProtocolIntegrationTest extends BriarTestCase {
|
|||||||
BitSet requested = req.getBitmap();
|
BitSet requested = req.getBitmap();
|
||||||
assertFalse(requested.get(0));
|
assertFalse(requested.get(0));
|
||||||
assertTrue(requested.get(1));
|
assertTrue(requested.get(1));
|
||||||
assertFalse(requested.get(2));
|
|
||||||
assertTrue(requested.get(3));
|
|
||||||
// If there are any padding bits, they should all be zero
|
// If there are any padding bits, they should all be zero
|
||||||
assertEquals(2, requested.cardinality());
|
assertEquals(1, requested.cardinality());
|
||||||
|
|
||||||
// Read the subscription update
|
// Read the subscription update
|
||||||
assertTrue(reader.hasSubscriptionUpdate());
|
assertTrue(reader.hasSubscriptionUpdate());
|
||||||
SubscriptionUpdate su = reader.readSubscriptionUpdate();
|
SubscriptionUpdate su = reader.readSubscriptionUpdate();
|
||||||
assertEquals(Arrays.asList(group, group1), su.getGroups());
|
assertEquals(Arrays.asList(group), su.getGroups());
|
||||||
assertEquals(1, su.getVersion());
|
assertEquals(1, su.getVersion());
|
||||||
|
|
||||||
// Read the transport update
|
// Read the transport update
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class PasswordBasedKdfTest extends BriarTestCase {
|
|||||||
public void testEncryptionAndDecryption() {
|
public void testEncryptionAndDecryption() {
|
||||||
CryptoComponent crypto = new CryptoComponentImpl();
|
CryptoComponent crypto = new CryptoComponentImpl();
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] input = new byte[123];
|
byte[] input = new byte[1234];
|
||||||
random.nextBytes(input);
|
random.nextBytes(input);
|
||||||
char[] password = "password".toCharArray();
|
char[] password = "password".toCharArray();
|
||||||
byte[] ciphertext = crypto.encryptWithPassword(input, password);
|
byte[] ciphertext = crypto.encryptWithPassword(input, password);
|
||||||
@@ -27,7 +27,7 @@ public class PasswordBasedKdfTest extends BriarTestCase {
|
|||||||
public void testInvalidCiphertextReturnsNull() {
|
public void testInvalidCiphertextReturnsNull() {
|
||||||
CryptoComponent crypto = new CryptoComponentImpl();
|
CryptoComponent crypto = new CryptoComponentImpl();
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
byte[] input = new byte[123];
|
byte[] input = new byte[1234];
|
||||||
random.nextBytes(input);
|
random.nextBytes(input);
|
||||||
char[] password = "password".toCharArray();
|
char[] password = "password".toCharArray();
|
||||||
byte[] ciphertext = crypto.encryptWithPassword(input, password);
|
byte[] ciphertext = crypto.encryptWithPassword(input, password);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
||||||
|
|
||||||
@@ -59,8 +61,8 @@ import org.junit.Test;
|
|||||||
public abstract class DatabaseComponentTest extends BriarTestCase {
|
public abstract class DatabaseComponentTest extends BriarTestCase {
|
||||||
|
|
||||||
protected final Object txn = new Object();
|
protected final Object txn = new Object();
|
||||||
protected final GroupId groupId, restrictedGroupId;
|
protected final GroupId groupId;
|
||||||
protected final Group group, restrictedGroup;
|
protected final Group group;
|
||||||
protected final AuthorId authorId;
|
protected final AuthorId authorId;
|
||||||
protected final Author author;
|
protected final Author author;
|
||||||
protected final AuthorId localAuthorId;
|
protected final AuthorId localAuthorId;
|
||||||
@@ -80,15 +82,12 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
|
|
||||||
public DatabaseComponentTest() {
|
public DatabaseComponentTest() {
|
||||||
groupId = new GroupId(TestUtils.getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
restrictedGroupId = new GroupId(TestUtils.getRandomId());
|
group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH]);
|
||||||
group = new Group(groupId, "Group name", null);
|
|
||||||
restrictedGroup = new Group(restrictedGroupId, "Restricted group name",
|
|
||||||
new byte[60]);
|
|
||||||
authorId = new AuthorId(TestUtils.getRandomId());
|
authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
author = new Author(authorId, "Alice", new byte[60]);
|
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
||||||
localAuthor = new LocalAuthor(localAuthorId, "Bob", new byte[60],
|
localAuthor = new LocalAuthor(localAuthorId, "Bob",
|
||||||
new byte[60]);
|
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100]);
|
||||||
messageId = new MessageId(TestUtils.getRandomId());
|
messageId = new MessageId(TestUtils.getRandomId());
|
||||||
messageId1 = new MessageId(TestUtils.getRandomId());
|
messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
privateMessageId = new MessageId(TestUtils.getRandomId());
|
privateMessageId = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -142,7 +141,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
// setRating(authorId, GOOD)
|
// setRating(authorId, GOOD)
|
||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
oneOf(database).setRating(txn, authorId, GOOD);
|
||||||
will(returnValue(UNRATED));
|
will(returnValue(UNRATED));
|
||||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
oneOf(database).getGroupMessages(txn, authorId);
|
||||||
will(returnValue(Collections.emptyList()));
|
will(returnValue(Collections.emptyList()));
|
||||||
oneOf(listener).eventOccurred(with(any(RatingChangedEvent.class)));
|
oneOf(listener).eventOccurred(with(any(RatingChangedEvent.class)));
|
||||||
// setRating(authorId, GOOD) again
|
// setRating(authorId, GOOD) again
|
||||||
@@ -186,8 +185,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).getVisibility(txn, groupId);
|
oneOf(database).getVisibility(txn, groupId);
|
||||||
will(returnValue(Collections.emptyList()));
|
will(returnValue(Collections.emptyList()));
|
||||||
oneOf(database).removeSubscription(txn, groupId);
|
oneOf(database).removeSubscription(txn, groupId);
|
||||||
oneOf(database).containsLocalGroup(txn, groupId);
|
|
||||||
will(returnValue(false));
|
|
||||||
oneOf(listener).eventOccurred(with(any(
|
oneOf(listener).eventOccurred(with(any(
|
||||||
SubscriptionRemovedEvent.class)));
|
SubscriptionRemovedEvent.class)));
|
||||||
oneOf(listener).eventOccurred(with(any(
|
oneOf(listener).eventOccurred(with(any(
|
||||||
@@ -228,59 +225,6 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRestrictedGroupMessagesAreAlwaysSendable()
|
|
||||||
throws Exception {
|
|
||||||
final Message groupMessage = new TestMessage(messageId, null,
|
|
||||||
restrictedGroup, author, contentType, subject, timestamp, raw);
|
|
||||||
final Message groupMessage1 = new TestMessage(messageId1, null,
|
|
||||||
restrictedGroup, null, contentType, subject, timestamp, raw);
|
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final DatabaseCleaner cleaner = context.mock(DatabaseCleaner.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
// addLocalGroupMessage(groupMessage)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).containsSubscription(txn, restrictedGroupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addGroupMessage(txn, groupMessage, false);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).setReadFlag(txn, messageId, true);
|
|
||||||
oneOf(database).getContactIds(txn);
|
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId, false);
|
|
||||||
oneOf(database).setSendability(txn, messageId, 1);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
// receiveMessage(groupMessage1)
|
|
||||||
oneOf(database).startTransaction();
|
|
||||||
will(returnValue(txn));
|
|
||||||
oneOf(database).containsContact(txn, contactId);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).containsVisibleSubscription(txn, contactId,
|
|
||||||
restrictedGroupId);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addGroupMessage(txn, groupMessage1, true);
|
|
||||||
will(returnValue(true));
|
|
||||||
oneOf(database).addStatus(txn, contactId, messageId1, true);
|
|
||||||
oneOf(database).getContactIds(txn);
|
|
||||||
will(returnValue(Arrays.asList(contactId)));
|
|
||||||
oneOf(database).setSendability(txn, messageId1, 1);
|
|
||||||
oneOf(database).addMessageToAck(txn, contactId, messageId1);
|
|
||||||
oneOf(database).commitTransaction(txn);
|
|
||||||
}});
|
|
||||||
|
|
||||||
DatabaseComponent db = createDatabaseComponent(database, cleaner,
|
|
||||||
shutdown);
|
|
||||||
|
|
||||||
db.addLocalGroupMessage(groupMessage);
|
|
||||||
db.receiveMessage(contactId, groupMessage1);
|
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNullParentStopsBackwardInclusion() throws Exception {
|
public void testNullParentStopsBackwardInclusion() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
@@ -295,7 +239,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
oneOf(database).setRating(txn, authorId, GOOD);
|
||||||
will(returnValue(UNRATED));
|
will(returnValue(UNRATED));
|
||||||
// The sendability of the author's messages should be incremented
|
// The sendability of the author's messages should be incremented
|
||||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
oneOf(database).getGroupMessages(txn, authorId);
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
will(returnValue(Arrays.asList(messageId)));
|
||||||
oneOf(database).getSendability(txn, messageId);
|
oneOf(database).getSendability(txn, messageId);
|
||||||
will(returnValue(0));
|
will(returnValue(0));
|
||||||
@@ -327,7 +271,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
oneOf(database).setRating(txn, authorId, GOOD);
|
||||||
will(returnValue(UNRATED));
|
will(returnValue(UNRATED));
|
||||||
// The sendability of the author's messages should be incremented
|
// The sendability of the author's messages should be incremented
|
||||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
oneOf(database).getGroupMessages(txn, authorId);
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
will(returnValue(Arrays.asList(messageId)));
|
||||||
oneOf(database).getSendability(txn, messageId);
|
oneOf(database).getSendability(txn, messageId);
|
||||||
will(returnValue(0));
|
will(returnValue(0));
|
||||||
@@ -364,7 +308,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase {
|
|||||||
oneOf(database).setRating(txn, authorId, GOOD);
|
oneOf(database).setRating(txn, authorId, GOOD);
|
||||||
will(returnValue(UNRATED));
|
will(returnValue(UNRATED));
|
||||||
// The sendability of the author's messages should be incremented
|
// The sendability of the author's messages should be incremented
|
||||||
oneOf(database).getUnrestrictedGroupMessages(txn, authorId);
|
oneOf(database).getGroupMessages(txn, authorId);
|
||||||
will(returnValue(Arrays.asList(messageId)));
|
will(returnValue(Arrays.asList(messageId)));
|
||||||
oneOf(database).getSendability(txn, messageId);
|
oneOf(database).getSendability(txn, messageId);
|
||||||
will(returnValue(0));
|
will(returnValue(0));
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package net.sf.briar.db;
|
package net.sf.briar.db;
|
||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
|
import static net.sf.briar.api.messaging.MessagingConstants.GROUP_SALT_LENGTH;
|
||||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
@@ -71,12 +73,12 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
|
|
||||||
public H2DatabaseTest() throws Exception {
|
public H2DatabaseTest() throws Exception {
|
||||||
groupId = new GroupId(TestUtils.getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
group = new Group(groupId, "Group name", null);
|
group = new Group(groupId, "Group", new byte[GROUP_SALT_LENGTH]);
|
||||||
authorId = new AuthorId(TestUtils.getRandomId());
|
authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
author = new Author(authorId, "Alice", new byte[60]);
|
author = new Author(authorId, "Alice", new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
localAuthorId = new AuthorId(TestUtils.getRandomId());
|
||||||
localAuthor = new LocalAuthor(localAuthorId, "Bob", new byte[60],
|
localAuthor = new LocalAuthor(localAuthorId, "Bob",
|
||||||
new byte[60]);
|
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100]);
|
||||||
messageId = new MessageId(TestUtils.getRandomId());
|
messageId = new MessageId(TestUtils.getRandomId());
|
||||||
messageId1 = new MessageId(TestUtils.getRandomId());
|
messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
contentType = "text/plain";
|
contentType = "text/plain";
|
||||||
@@ -535,38 +537,28 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetUnrestrictedGroupMessages() throws Exception {
|
public void testGetGroupMessages() throws Exception {
|
||||||
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||||
Author author1 = new Author(authorId1, "Bob", new byte[60]);
|
Author author1 = new Author(authorId1, "Bob",
|
||||||
|
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
Message message1 = new TestMessage(messageId1, null, group, author1,
|
Message message1 = new TestMessage(messageId1, null, group, author1,
|
||||||
contentType, subject, timestamp, raw);
|
contentType, subject, timestamp, raw);
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
|
||||||
Group group1 = new Group(groupId1, "Restricted group name",
|
|
||||||
new byte[60]);
|
|
||||||
MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
|
||||||
Message message2 = new TestMessage(messageId2, null, group1, author,
|
|
||||||
contentType, subject, timestamp, raw);
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
// Subscribe to an unrestricted group and store two messages
|
// Subscribe to a group and store two messages
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
db.addGroupMessage(txn, message, false);
|
db.addGroupMessage(txn, message, false);
|
||||||
db.addGroupMessage(txn, message1, false);
|
db.addGroupMessage(txn, message1, false);
|
||||||
|
|
||||||
// Subscribe to a restricted group and store a message
|
// Check that both messages are retrievable by their authors
|
||||||
db.addSubscription(txn, group1);
|
Collection<MessageId> ids = db.getGroupMessages(txn, authorId);
|
||||||
db.addGroupMessage(txn, message2, false);
|
|
||||||
|
|
||||||
// Check that only the messages in the unrestricted group are retrieved
|
|
||||||
Collection<MessageId> ids = db.getUnrestrictedGroupMessages(txn,
|
|
||||||
authorId);
|
|
||||||
Iterator<MessageId> it = ids.iterator();
|
Iterator<MessageId> it = ids.iterator();
|
||||||
assertTrue(it.hasNext());
|
assertTrue(it.hasNext());
|
||||||
assertEquals(messageId, it.next());
|
assertEquals(messageId, it.next());
|
||||||
assertFalse(it.hasNext());
|
assertFalse(it.hasNext());
|
||||||
ids = db.getUnrestrictedGroupMessages(txn, authorId1);
|
ids = db.getGroupMessages(txn, authorId1);
|
||||||
it = ids.iterator();
|
it = ids.iterator();
|
||||||
assertTrue(it.hasNext());
|
assertTrue(it.hasNext());
|
||||||
assertEquals(messageId1, it.next());
|
assertEquals(messageId1, it.next());
|
||||||
@@ -582,7 +574,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
MessageId childId2 = new MessageId(TestUtils.getRandomId());
|
MessageId childId2 = new MessageId(TestUtils.getRandomId());
|
||||||
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
MessageId childId3 = new MessageId(TestUtils.getRandomId());
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = new Group(groupId1, "Group name", null);
|
Group group1 = new Group(groupId1, "Another group",
|
||||||
|
new byte[GROUP_SALT_LENGTH]);
|
||||||
Message child1 = new TestMessage(childId1, messageId, group, author,
|
Message child1 = new TestMessage(childId1, messageId, group, author,
|
||||||
contentType, subject, timestamp, raw);
|
contentType, subject, timestamp, raw);
|
||||||
Message child2 = new TestMessage(childId2, messageId, group, author,
|
Message child2 = new TestMessage(childId2, messageId, group, author,
|
||||||
@@ -1193,7 +1186,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
public void testGetGroupMessageParentWithParentInAnotherGroup()
|
public void testGetGroupMessageParentWithParentInAnotherGroup()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = new Group(groupId1, "Group name", null);
|
Group group1 = new Group(groupId1, "Another group",
|
||||||
|
new byte[GROUP_SALT_LENGTH]);
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|
||||||
@@ -1446,7 +1440,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
// Subscribe to a couple of groups
|
// Subscribe to a couple of groups
|
||||||
db.addSubscription(txn, group);
|
db.addSubscription(txn, group);
|
||||||
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
GroupId groupId1 = new GroupId(TestUtils.getRandomId());
|
||||||
Group group1 = new Group(groupId1, "Group name", null);
|
Group group1 = new Group(groupId1, "Another group",
|
||||||
|
new byte[GROUP_SALT_LENGTH]);
|
||||||
db.addSubscription(txn, group1);
|
db.addSubscription(txn, group1);
|
||||||
|
|
||||||
// Store two messages in the first group
|
// Store two messages in the first group
|
||||||
@@ -1499,7 +1494,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
List<Group> groups = new ArrayList<Group>();
|
List<Group> groups = new ArrayList<Group>();
|
||||||
for(int i = 0; i < 100; i++) {
|
for(int i = 0; i < 100; i++) {
|
||||||
GroupId id = new GroupId(TestUtils.getRandomId());
|
GroupId id = new GroupId(TestUtils.getRandomId());
|
||||||
groups.add(new Group(id, "Group name", null));
|
String name = "Group " + i;
|
||||||
|
groups.add(new Group(id, name, new byte[GROUP_SALT_LENGTH]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
@@ -1834,7 +1830,8 @@ public class H2DatabaseTest extends BriarTestCase {
|
|||||||
public void testGetAvailableGroups() throws Exception {
|
public void testGetAvailableGroups() throws Exception {
|
||||||
ContactId contactId1 = new ContactId(2);
|
ContactId contactId1 = new ContactId(2);
|
||||||
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
AuthorId authorId1 = new AuthorId(TestUtils.getRandomId());
|
||||||
Author author1 = new Author(authorId1, "Carol", new byte[60]);
|
Author author1 = new Author(authorId1, "Carol",
|
||||||
|
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
|
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ public class ConstantsTest extends BriarTestCase {
|
|||||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||||
assertTrue(publicKey.length <= MAX_PUBLIC_KEY_LENGTH);
|
assertTrue(publicKey.length <= MAX_PUBLIC_KEY_LENGTH);
|
||||||
// Sign some random data and check the length of the signature
|
// Sign some random data and check the length of the signature
|
||||||
byte[] toBeSigned = new byte[1000];
|
byte[] toBeSigned = new byte[1234];
|
||||||
random.nextBytes(toBeSigned);
|
random.nextBytes(toBeSigned);
|
||||||
sig.initSign(keyPair.getPrivate());
|
sig.initSign(keyPair.getPrivate());
|
||||||
sig.update(toBeSigned);
|
sig.update(toBeSigned);
|
||||||
@@ -120,23 +120,19 @@ public class ConstantsTest extends BriarTestCase {
|
|||||||
MessageId parent = new MessageId(TestUtils.getRandomId());
|
MessageId parent = new MessageId(TestUtils.getRandomId());
|
||||||
// Create a maximum-length group
|
// Create a maximum-length group
|
||||||
String groupName = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
String groupName = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
||||||
byte[] groupPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
Group group = groupFactory.createGroup(groupName);
|
||||||
Group group = groupFactory.createGroup(groupName, groupPublic);
|
|
||||||
// Create a maximum-length author
|
// Create a maximum-length author
|
||||||
String authorName =
|
String authorName =
|
||||||
TestUtils.createRandomString(MAX_AUTHOR_NAME_LENGTH);
|
TestUtils.createRandomString(MAX_AUTHOR_NAME_LENGTH);
|
||||||
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
||||||
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
Author author = authorFactory.createAuthor(authorName, authorPublic);
|
||||||
// Create a maximum-length message
|
// Create a maximum-length message
|
||||||
PrivateKey groupPrivate =
|
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
|
||||||
crypto.generateSignatureKeyPair().getPrivate();
|
|
||||||
PrivateKey authorPrivate =
|
|
||||||
crypto.generateSignatureKeyPair().getPrivate();
|
|
||||||
String contentType =
|
String contentType =
|
||||||
TestUtils.createRandomString(MAX_CONTENT_TYPE_LENGTH);
|
TestUtils.createRandomString(MAX_CONTENT_TYPE_LENGTH);
|
||||||
byte[] body = new byte[MAX_BODY_LENGTH];
|
byte[] body = new byte[MAX_BODY_LENGTH];
|
||||||
Message message = messageFactory.createPseudonymousMessage(parent,
|
Message message = messageFactory.createPseudonymousMessage(parent,
|
||||||
group, groupPrivate, author, authorPrivate, contentType, body);
|
group, author, privateKey, contentType, body);
|
||||||
// Check the size of the serialised message
|
// Check the size of the serialised message
|
||||||
int length = message.getSerialised().length;
|
int length = message.getSerialised().length;
|
||||||
assertTrue(length > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH
|
assertTrue(length > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH
|
||||||
@@ -181,10 +177,8 @@ public class ConstantsTest extends BriarTestCase {
|
|||||||
// Create the maximum number of maximum-length groups
|
// Create the maximum number of maximum-length groups
|
||||||
Collection<Group> subs = new ArrayList<Group>();
|
Collection<Group> subs = new ArrayList<Group>();
|
||||||
for(int i = 0; i < MAX_SUBSCRIPTIONS; i++) {
|
for(int i = 0; i < MAX_SUBSCRIPTIONS; i++) {
|
||||||
String groupName =
|
String name = TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
||||||
TestUtils.createRandomString(MAX_GROUP_NAME_LENGTH);
|
subs.add(groupFactory.createGroup(name));
|
||||||
byte[] groupPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
|
|
||||||
subs.add(groupFactory.createGroup(groupName, groupPublic));
|
|
||||||
}
|
}
|
||||||
// Create a maximum-length subscription update
|
// Create a maximum-length subscription update
|
||||||
SubscriptionUpdate u = new SubscriptionUpdate(subs, Long.MAX_VALUE);
|
SubscriptionUpdate u = new SubscriptionUpdate(subs, Long.MAX_VALUE);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.sf.briar.messaging.simplex;
|
package net.sf.briar.messaging.simplex;
|
||||||
|
|
||||||
|
import static net.sf.briar.api.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
|
||||||
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
import static net.sf.briar.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@@ -108,11 +109,12 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
|||||||
// Add a local pseudonym for Alice
|
// Add a local pseudonym for Alice
|
||||||
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
||||||
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
|
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
|
||||||
new byte[60], new byte[60]);
|
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100]);
|
||||||
db.addLocalAuthor(aliceAuthor);
|
db.addLocalAuthor(aliceAuthor);
|
||||||
// Add Bob as a contact
|
// Add Bob as a contact
|
||||||
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
||||||
Author bobAuthor = new Author(bobId, "Bob", new byte[60]);
|
Author bobAuthor = new Author(bobId, "Bob",
|
||||||
|
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
ContactId contactId = db.addContact(bobAuthor, aliceId);
|
ContactId contactId = db.addContact(bobAuthor, aliceId);
|
||||||
// Add the transport and the endpoint
|
// Add the transport and the endpoint
|
||||||
db.addTransport(transportId, LATENCY);
|
db.addTransport(transportId, LATENCY);
|
||||||
@@ -161,12 +163,13 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
|
|||||||
km.start();
|
km.start();
|
||||||
// Add a local pseudonym for Bob
|
// Add a local pseudonym for Bob
|
||||||
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
AuthorId bobId = new AuthorId(TestUtils.getRandomId());
|
||||||
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob", new byte[60],
|
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
|
||||||
new byte[60]);
|
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[100]);
|
||||||
db.addLocalAuthor(bobAuthor);
|
db.addLocalAuthor(bobAuthor);
|
||||||
// Add Alice as a contact
|
// Add Alice as a contact
|
||||||
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
|
||||||
Author aliceAuthor = new Author(aliceId, "Alice", new byte[60]);
|
Author aliceAuthor = new Author(aliceId, "Alice",
|
||||||
|
new byte[MAX_PUBLIC_KEY_LENGTH]);
|
||||||
ContactId contactId = db.addContact(aliceAuthor, bobId);
|
ContactId contactId = db.addContact(aliceAuthor, bobId);
|
||||||
// Add the transport and the endpoint
|
// Add the transport and the endpoint
|
||||||
db.addTransport(transportId, LATENCY);
|
db.addTransport(transportId, LATENCY);
|
||||||
|
|||||||
@@ -263,13 +263,13 @@ public class RemovableDrivePluginTest extends BriarTestCase {
|
|||||||
assertEquals(0, files[0].length());
|
assertEquals(0, files[0].length());
|
||||||
// Writing to the output stream should increase the size of the file
|
// Writing to the output stream should increase the size of the file
|
||||||
OutputStream out = writer.getOutputStream();
|
OutputStream out = writer.getOutputStream();
|
||||||
out.write(new byte[123]);
|
out.write(new byte[1234]);
|
||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
// Disposing of the writer should not delete the file
|
// Disposing of the writer should not delete the file
|
||||||
writer.dispose(false);
|
writer.dispose(false);
|
||||||
assertTrue(files[0].exists());
|
assertTrue(files[0].exists());
|
||||||
assertEquals(123, files[0].length());
|
assertEquals(1234, files[0].length());
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
context.assertIsSatisfied();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user