mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 03:09:04 +01:00
Merge tag 'release-1.3.6' into briar-as-subproject
release-1.3.6
This commit is contained in:
@@ -10,4 +10,7 @@ dependencies {
|
||||
implementation project(path: ':briar:bramble-api', configuration: 'default')
|
||||
|
||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation "junit:junit:$junit_version"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.api.messaging;
|
||||
package org.briarproject.briar.api.attachment;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.api.messaging;
|
||||
package org.briarproject.briar.api.attachment;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -9,14 +10,21 @@ import javax.annotation.concurrent.Immutable;
|
||||
@NotNullByDefault
|
||||
public class AttachmentHeader {
|
||||
|
||||
private final GroupId groupId;
|
||||
private final MessageId messageId;
|
||||
private final String contentType;
|
||||
|
||||
public AttachmentHeader(MessageId messageId, String contentType) {
|
||||
public AttachmentHeader(GroupId groupId, MessageId messageId,
|
||||
String contentType) {
|
||||
this.groupId = groupId;
|
||||
this.messageId = messageId;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public MessageId getMessageId() {
|
||||
return messageId;
|
||||
}
|
||||
@@ -27,13 +35,15 @@ public class AttachmentHeader {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof AttachmentHeader &&
|
||||
messageId.equals(((AttachmentHeader) o).messageId);
|
||||
if (o instanceof AttachmentHeader) {
|
||||
AttachmentHeader h = (AttachmentHeader) o;
|
||||
return groupId.equals(h.groupId) && messageId.equals(h.messageId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return messageId.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.briarproject.briar.api.attachment;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
||||
|
||||
public interface AttachmentReader {
|
||||
|
||||
/**
|
||||
* Returns the attachment with the given attachment header.
|
||||
*
|
||||
* @throws NoSuchMessageException If the header refers to a message in
|
||||
* a different group from the one specified in the header, to a message
|
||||
* that is not an attachment, or to an attachment that does not have the
|
||||
* expected content type. This is meant to prevent social engineering
|
||||
* attacks that use invalid attachment IDs to test whether messages exist
|
||||
* in the victim's database
|
||||
*/
|
||||
Attachment getAttachment(AttachmentHeader h) throws DbException;
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.api.messaging;
|
||||
package org.briarproject.briar.api.attachment;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.briarproject.briar.api.attachment;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||
|
||||
public interface MediaConstants {
|
||||
|
||||
// Metadata keys for messages
|
||||
String MSG_KEY_CONTENT_TYPE = "contentType";
|
||||
String MSG_KEY_DESCRIPTOR_LENGTH = "descriptorLength";
|
||||
|
||||
/**
|
||||
* The maximum length of an attachment's content type in UTF-8 bytes.
|
||||
*/
|
||||
int MAX_CONTENT_TYPE_BYTES = 80;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of image attachments.
|
||||
* TODO: Different limit for GIFs?
|
||||
*/
|
||||
int MAX_IMAGE_SIZE = MAX_MESSAGE_BODY_LENGTH - 100; // 6 * 1024 * 1024;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.briarproject.briar.api.autodelete;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
|
||||
public interface AutoDeleteConstants {
|
||||
|
||||
/**
|
||||
* The minimum valid auto-delete timer duration in milliseconds.
|
||||
*/
|
||||
long MIN_AUTO_DELETE_TIMER_MS = MINUTES.toMillis(1);
|
||||
|
||||
/**
|
||||
* The maximum valid auto-delete timer duration in milliseconds.
|
||||
*/
|
||||
long MAX_AUTO_DELETE_TIMER_MS = DAYS.toMillis(365);
|
||||
|
||||
/**
|
||||
* Placeholder value indicating that a message has no auto-delete timer.
|
||||
* This value should not be sent over the wire - send null instead.
|
||||
*/
|
||||
long NO_AUTO_DELETE_TIMER = -1;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.briarproject.briar.api.autodelete;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.DAYS;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface AutoDeleteManager {
|
||||
|
||||
/**
|
||||
* The unique ID of the auto-delete client.
|
||||
*/
|
||||
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.autodelete");
|
||||
|
||||
/**
|
||||
* The current major version of the auto-delete client.
|
||||
*/
|
||||
int MAJOR_VERSION = 0;
|
||||
|
||||
/**
|
||||
* The current minor version of the auto-delete client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
|
||||
/**
|
||||
* The default auto-delete timer duration.
|
||||
*/
|
||||
long DEFAULT_TIMER_DURATION = DAYS.toMillis(7);
|
||||
|
||||
/**
|
||||
* Returns the auto-delete timer duration for the given contact. Use
|
||||
* {@link #getAutoDeleteTimer(Transaction, ContactId, long)} if the timer
|
||||
* will be used in an outgoing message.
|
||||
*/
|
||||
long getAutoDeleteTimer(Transaction txn, ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the auto-delete timer duration for the given contact, for use in
|
||||
* a message with the given timestamp. The timestamp is stored. This method
|
||||
* requires a read-write transaction.
|
||||
*/
|
||||
long getAutoDeleteTimer(Transaction txn, ContactId c, long timestamp)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the auto-delete timer duration for the given contact.
|
||||
*/
|
||||
void setAutoDeleteTimer(Transaction txn, ContactId c, long timer)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Receives an auto-delete timer duration from the given contact, carried
|
||||
* in a message with the given timestamp. The local timer is set to the
|
||||
* same duration unless it has been
|
||||
* {@link #setAutoDeleteTimer(Transaction, ContactId, long) changed} more
|
||||
* recently than the remote timer.
|
||||
*/
|
||||
void receiveAutoDeleteTimer(Transaction txn, ContactId c, long timer,
|
||||
long timestamp) throws DbException;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.briarproject.briar.api.autodelete;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
|
||||
/**
|
||||
* Thrown when a database operation is attempted as part of message storing
|
||||
* and the operation is expecting a different timer state. This
|
||||
* exception may occur due to concurrent updates and does not indicate a
|
||||
* database error.
|
||||
*/
|
||||
public class UnexpectedTimerException extends DbException {
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.briarproject.briar.api.autodelete.event;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class AutoDeleteTimerMirroredEvent extends Event {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final long newTimer;
|
||||
|
||||
public AutoDeleteTimerMirroredEvent(ContactId contactId, long newTimer) {
|
||||
this.contactId = contactId;
|
||||
this.newTimer = newTimer;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public long getNewTimer() {
|
||||
return newTimer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.briarproject.briar.api.autodelete.event;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when one or more messages
|
||||
* in the private conversation with a contact have been deleted.
|
||||
*/
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class ConversationMessagesDeletedEvent extends Event {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final Collection<MessageId> messageIds;
|
||||
|
||||
public ConversationMessagesDeletedEvent(ContactId contactId,
|
||||
Collection<MessageId> messageIds) {
|
||||
this.contactId = contactId;
|
||||
this.messageIds = messageIds;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public Collection<MessageId> getMessageIds() {
|
||||
return messageIds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.briarproject.briar.api.avatar;
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface AvatarManager {
|
||||
|
||||
/**
|
||||
* The unique ID of the avatar client.
|
||||
*/
|
||||
ClientId CLIENT_ID = new ClientId("org.briarproject.briar.avatar");
|
||||
|
||||
/**
|
||||
* The current major version of the avatar client.
|
||||
*/
|
||||
int MAJOR_VERSION = 0;
|
||||
|
||||
/**
|
||||
* The current minor version of the avatar client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
|
||||
/**
|
||||
* Store a new profile image represented by the given InputStream
|
||||
* and share it with all contacts.
|
||||
*/
|
||||
AttachmentHeader addAvatar(String contentType, InputStream in)
|
||||
throws DbException, IOException;
|
||||
|
||||
/**
|
||||
* Returns the current known profile image header for the given contact
|
||||
* or null if none is known.
|
||||
*/
|
||||
@Nullable
|
||||
AttachmentHeader getAvatarHeader(Transaction txn, Contact c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns our current profile image header or null if none has been added.
|
||||
*/
|
||||
@Nullable
|
||||
AttachmentHeader getMyAvatarHeader(Transaction txn) throws DbException;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.briar.api.avatar;
|
||||
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public interface AvatarMessageEncoder {
|
||||
/**
|
||||
* Returns an update message and its metadata.
|
||||
*/
|
||||
Pair<Message, BdfDictionary> encodeUpdateMessage(GroupId groupId,
|
||||
long version, String contentType, InputStream in)
|
||||
throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.briarproject.briar.api.avatar.event;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when a new avatar is received.
|
||||
*/
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class AvatarUpdatedEvent extends Event {
|
||||
|
||||
private final ContactId contactId;
|
||||
private final AttachmentHeader attachmentHeader;
|
||||
|
||||
public AvatarUpdatedEvent(ContactId contactId,
|
||||
AttachmentHeader attachmentHeader) {
|
||||
this.contactId = contactId;
|
||||
this.attachmentHeader = attachmentHeader;
|
||||
}
|
||||
|
||||
public ContactId getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
|
||||
public AttachmentHeader getAttachmentHeader() {
|
||||
return attachmentHeader;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.briar.api.blog;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
@@ -15,9 +15,9 @@ public class BlogInvitationRequest extends InvitationRequest<Blog> {
|
||||
public BlogInvitationRequest(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, Blog blog, @Nullable String text,
|
||||
boolean available, boolean canBeOpened) {
|
||||
boolean available, boolean canBeOpened, long autoDeleteTimer) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, blog,
|
||||
text, available, canBeOpened);
|
||||
text, available, canBeOpened, autoDeleteTimer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,9 +12,10 @@ public class BlogInvitationResponse extends InvitationResponse {
|
||||
|
||||
public BlogInvitationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accept, GroupId shareableId) {
|
||||
SessionId sessionId, boolean accept, GroupId shareableId,
|
||||
long autoDeleteTimer, boolean isAutoDecline) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId,
|
||||
accept, shareableId);
|
||||
accept, shareableId, autoDeleteTimer, isAutoDecline);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -98,21 +99,38 @@ public interface BlogManager {
|
||||
*/
|
||||
Collection<Blog> getBlogs() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group IDs of all blogs to which the user subscribes.
|
||||
*/
|
||||
Collection<GroupId> getBlogIds(Transaction txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the header of the blog post with the given ID.
|
||||
*/
|
||||
BlogPostHeader getPostHeader(GroupId g, MessageId m) throws DbException;
|
||||
BlogPostHeader getPostHeader(Transaction txn, GroupId g, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the blog post with the given ID.
|
||||
*/
|
||||
String getPostText(MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the blog post with the given ID.
|
||||
*/
|
||||
String getPostText(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all posts in the given blog.
|
||||
*/
|
||||
Collection<BlogPostHeader> getPostHeaders(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all posts in the given blog.
|
||||
*/
|
||||
List<BlogPostHeader> getPostHeaders(Transaction txn, GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Marks a blog post as read or unread.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.briar.api.blog;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
@@ -18,5 +18,5 @@ public interface BlogSharingManager extends SharingManager<Blog> {
|
||||
/**
|
||||
* The current minor version of the blog sharing client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
int MINOR_VERSION = 1;
|
||||
}
|
||||
|
||||
@@ -61,8 +61,11 @@ public interface MessageTracker {
|
||||
|
||||
/**
|
||||
* Marks a message as read or unread and updates the group count.
|
||||
*
|
||||
* @return True if the message was previously marked as read
|
||||
*/
|
||||
void setReadFlag(GroupId g, MessageId m, boolean read) throws DbException;
|
||||
boolean setReadFlag(Transaction txn, GroupId g, MessageId m, boolean read)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Resets the {@link GroupCount} to the given msgCount and unreadCount.
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -15,11 +15,9 @@ public interface MessageTree<T extends MessageTree.MessageNode> {
|
||||
|
||||
void add(T node);
|
||||
|
||||
void setComparator(Comparator<T> comparator);
|
||||
|
||||
void clear();
|
||||
|
||||
Collection<T> depthFirstOrder();
|
||||
List<T> depthFirstOrder();
|
||||
|
||||
boolean contains(MessageId m);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.briarproject.briar.api.client;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo.Status;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo.Status;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ public interface ConversationManager {
|
||||
int DELETE_SESSION_INVITATION_INCOMPLETE = 1 << 1;
|
||||
int DELETE_SESSION_INTRODUCTION_IN_PROGRESS = 1 << 2;
|
||||
int DELETE_SESSION_INVITATION_IN_PROGRESS = 1 << 3;
|
||||
int DELETE_NOT_DOWNLOADED = 1 << 4;
|
||||
|
||||
/**
|
||||
* Clients that present messages in a private conversation need to
|
||||
@@ -43,6 +42,21 @@ public interface ConversationManager {
|
||||
*/
|
||||
GroupCount getGroupCount(ContactId c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the unified group count for all private conversation messages.
|
||||
*/
|
||||
GroupCount getGroupCount(Transaction txn, ContactId c) throws DbException;
|
||||
|
||||
void setReadFlag(GroupId g, MessageId m, boolean read)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a timestamp for an outgoing message, which is later than the
|
||||
* timestamp of any message in the conversation with the given contact.
|
||||
*/
|
||||
long getTimestampForOutgoingMessage(Transaction txn, ContactId c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Deletes all messages exchanged with the given contact.
|
||||
*/
|
||||
@@ -72,9 +86,6 @@ public interface ConversationManager {
|
||||
GroupCount getGroupCount(Transaction txn, ContactId c)
|
||||
throws DbException;
|
||||
|
||||
void setReadFlag(GroupId g, MessageId m, boolean read)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Deletes all messages associated with the given contact.
|
||||
*/
|
||||
|
||||
@@ -12,18 +12,20 @@ public abstract class ConversationMessageHeader {
|
||||
|
||||
private final MessageId id;
|
||||
private final GroupId groupId;
|
||||
private final long timestamp;
|
||||
private final boolean local, sent, seen, read;
|
||||
private final long timestamp, autoDeleteTimer;
|
||||
private final boolean local, read, sent, seen;
|
||||
|
||||
public ConversationMessageHeader(MessageId id, GroupId groupId, long timestamp,
|
||||
boolean local, boolean read, boolean sent, boolean seen) {
|
||||
public ConversationMessageHeader(MessageId id, GroupId groupId,
|
||||
long timestamp, boolean local, boolean read, boolean sent,
|
||||
boolean seen, long autoDeleteTimer) {
|
||||
this.id = id;
|
||||
this.groupId = groupId;
|
||||
this.timestamp = timestamp;
|
||||
this.local = local;
|
||||
this.read = read;
|
||||
this.sent = sent;
|
||||
this.seen = seen;
|
||||
this.read = read;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
}
|
||||
|
||||
public MessageId getId() {
|
||||
@@ -55,4 +57,8 @@ public abstract class ConversationMessageHeader {
|
||||
}
|
||||
|
||||
public abstract <T> T accept(ConversationMessageVisitor<T> v);
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ public abstract class ConversationRequest<N extends Nameable>
|
||||
private final String text;
|
||||
private final boolean answered;
|
||||
|
||||
public ConversationRequest(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, N nameable, @Nullable String text,
|
||||
boolean answered) {
|
||||
super(messageId, groupId, time, local, read, sent, seen);
|
||||
public ConversationRequest(MessageId messageId, GroupId groupId,
|
||||
long timestamp, boolean local, boolean read, boolean sent,
|
||||
boolean seen, SessionId sessionId, N nameable,
|
||||
@Nullable String text, boolean answered, long autoDeleteTimer) {
|
||||
super(messageId, groupId, timestamp, local, read, sent, seen,
|
||||
autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
this.nameable = nameable;
|
||||
this.text = text;
|
||||
|
||||
@@ -12,14 +12,16 @@ import javax.annotation.concurrent.Immutable;
|
||||
public abstract class ConversationResponse extends ConversationMessageHeader {
|
||||
|
||||
private final SessionId sessionId;
|
||||
private final boolean accepted;
|
||||
private final boolean accepted, isAutoDecline;
|
||||
|
||||
public ConversationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted) {
|
||||
super(id, groupId, time, local, read, sent, seen);
|
||||
SessionId sessionId, boolean accepted, long autoDeleteTimer,
|
||||
boolean isAutoDecline) {
|
||||
super(id, groupId, time, local, read, sent, seen, autoDeleteTimer);
|
||||
this.sessionId = sessionId;
|
||||
this.accepted = accepted;
|
||||
this.isAutoDecline = isAutoDecline;
|
||||
}
|
||||
|
||||
public SessionId getSessionId() {
|
||||
@@ -30,4 +32,7 @@ public abstract class ConversationResponse extends ConversationMessageHeader {
|
||||
return accepted;
|
||||
}
|
||||
|
||||
public boolean isAutoDecline() {
|
||||
return isAutoDecline;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_NOT_DOWNLOADED;
|
||||
import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_INTRODUCTION_INCOMPLETE;
|
||||
import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_INTRODUCTION_IN_PROGRESS;
|
||||
import static org.briarproject.briar.api.conversation.ConversationManager.DELETE_SESSION_INVITATION_INCOMPLETE;
|
||||
@@ -36,10 +35,6 @@ public class DeletionResult {
|
||||
result |= DELETE_SESSION_INTRODUCTION_IN_PROGRESS;
|
||||
}
|
||||
|
||||
public void addNotFullyDownloaded() {
|
||||
result |= DELETE_NOT_DOWNLOADED;
|
||||
}
|
||||
|
||||
public boolean allDeleted() {
|
||||
return result == 0;
|
||||
}
|
||||
@@ -59,9 +54,4 @@ public class DeletionResult {
|
||||
public boolean hasNotAllInvitationSelected() {
|
||||
return (result & DELETE_SESSION_INVITATION_INCOMPLETE) != 0;
|
||||
}
|
||||
|
||||
public boolean hasNotFullyDownloaded() {
|
||||
return (result & DELETE_NOT_DOWNLOADED) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class Feed {
|
||||
public class Feed implements Comparable<Feed> {
|
||||
|
||||
private final String url;
|
||||
private final Blog blog;
|
||||
@@ -94,4 +94,13 @@ public class Feed {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Feed o) {
|
||||
if (this == o) return 0;
|
||||
long aTime = getAdded(), bTime = o.getAdded();
|
||||
if (aTime > bTime) return -1;
|
||||
if (aTime < bTime) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.api.feed;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
|
||||
@@ -23,7 +24,7 @@ public interface FeedManager {
|
||||
/**
|
||||
* Adds an RSS feed as a new dedicated blog.
|
||||
*/
|
||||
void addFeed(String url) throws DbException, IOException;
|
||||
Feed addFeed(String url) throws DbException, IOException;
|
||||
|
||||
/**
|
||||
* Removes an RSS feed.
|
||||
@@ -35,4 +36,8 @@ public interface FeedManager {
|
||||
*/
|
||||
List<Feed> getFeeds() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns a list of all added RSS feeds
|
||||
*/
|
||||
List<Feed> getFeeds(Transaction txn) throws DbException;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ public class ForumInvitationRequest extends InvitationRequest<Forum> {
|
||||
public ForumInvitationRequest(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, Forum forum, @Nullable String text,
|
||||
boolean available, boolean canBeOpened) {
|
||||
boolean available, boolean canBeOpened, long autoDeleteTimer) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, forum,
|
||||
text, available, canBeOpened);
|
||||
text, available, canBeOpened, autoDeleteTimer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,9 +15,10 @@ public class ForumInvitationResponse extends InvitationResponse {
|
||||
|
||||
public ForumInvitationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accept, GroupId shareableId) {
|
||||
SessionId sessionId, boolean accept, GroupId shareableId,
|
||||
long autoDeleteTimer, boolean isAutoDecline) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId,
|
||||
accept, shareableId);
|
||||
accept, shareableId, autoDeleteTimer, isAutoDecline);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -59,6 +60,12 @@ public interface ForumManager {
|
||||
*/
|
||||
ForumPostHeader addLocalPost(ForumPost p) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores a local forum post.
|
||||
*/
|
||||
ForumPostHeader addLocalPost(Transaction txn, ForumPost p)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the forum with the given ID.
|
||||
*/
|
||||
@@ -74,16 +81,32 @@ public interface ForumManager {
|
||||
*/
|
||||
Collection<Forum> getForums() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all forums to which the user subscribes.
|
||||
*/
|
||||
Collection<Forum> getForums(Transaction txn) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the forum post with the given ID.
|
||||
*/
|
||||
String getPostText(MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the forum post with the given ID.
|
||||
*/
|
||||
String getPostText(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all posts in the given forum.
|
||||
*/
|
||||
Collection<ForumPostHeader> getPostHeaders(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all posts in the given forum.
|
||||
*/
|
||||
List<ForumPostHeader> getPostHeaders(Transaction txn, GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Registers a hook to be called whenever a forum is removed.
|
||||
*/
|
||||
@@ -94,6 +117,11 @@ public interface ForumManager {
|
||||
*/
|
||||
GroupCount getGroupCount(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group count for the given forum.
|
||||
*/
|
||||
GroupCount getGroupCount(Transaction txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Marks a message as read or unread and updates the group count.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.briar.api.forum;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.client.PostHeader;
|
||||
|
||||
@@ -18,5 +18,5 @@ public interface ForumSharingManager extends SharingManager<Forum> {
|
||||
/**
|
||||
* The current minor version of the forum sharing client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
int MINOR_VERSION = 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.briarproject.briar.api.identity;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.NullSafety;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class AuthorInfo {
|
||||
|
||||
public enum Status {
|
||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
|
||||
|
||||
public boolean isContact() {
|
||||
return this == UNVERIFIED || this == VERIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
private final Status status;
|
||||
@Nullable
|
||||
private final String alias;
|
||||
@Nullable
|
||||
private final AttachmentHeader avatarHeader;
|
||||
|
||||
public AuthorInfo(Status status, @Nullable String alias,
|
||||
@Nullable AttachmentHeader avatarHeader) {
|
||||
this.status = status;
|
||||
this.alias = alias;
|
||||
this.avatarHeader = avatarHeader;
|
||||
}
|
||||
|
||||
public AuthorInfo(Status status) {
|
||||
this(status, null, null);
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AttachmentHeader getAvatarHeader() {
|
||||
return avatarHeader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = status.ordinal();
|
||||
if (alias != null) hashCode += alias.hashCode();
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof AuthorInfo)) return false;
|
||||
AuthorInfo info = (AuthorInfo) o;
|
||||
return status == info.status &&
|
||||
// aliases are equal
|
||||
NullSafety.equals(alias, info.alias) &&
|
||||
// avatars are equal
|
||||
NullSafety.equals(avatarHeader, info.avatarHeader);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.briarproject.briar.api.identity;
|
||||
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface AuthorManager {
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the given author.
|
||||
*/
|
||||
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the given author.
|
||||
*/
|
||||
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the given contact.
|
||||
*/
|
||||
AuthorInfo getAuthorInfo(Contact c) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the given contact.
|
||||
*/
|
||||
AuthorInfo getAuthorInfo(Transaction txn, Contact c)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the {@link LocalAuthor}.
|
||||
*/
|
||||
AuthorInfo getMyAuthorInfo() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the {@link AuthorInfo} for the {@link LocalAuthor}.
|
||||
*/
|
||||
AuthorInfo getMyAuthorInfo(Transaction txn) throws DbException;
|
||||
}
|
||||
@@ -31,18 +31,18 @@ public interface IntroductionManager extends ConversationClient {
|
||||
/**
|
||||
* The current minor version of the introduction client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
int MINOR_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Sends two initial introduction messages.
|
||||
*/
|
||||
void makeIntroduction(Contact c1, Contact c2, @Nullable String text,
|
||||
long timestamp) throws DbException;
|
||||
void makeIntroduction(Contact c1, Contact c2, @Nullable String text)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to an introduction.
|
||||
*/
|
||||
void respondToIntroduction(ContactId contactId, SessionId sessionId,
|
||||
long timestamp, boolean accept) throws DbException;
|
||||
boolean accept) throws DbException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.briar.api.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
@@ -18,12 +18,12 @@ public class IntroductionRequest extends ConversationRequest<Author> {
|
||||
|
||||
private final AuthorInfo authorInfo;
|
||||
|
||||
public IntroductionRequest(MessageId messageId, GroupId groupId,
|
||||
long time, boolean local, boolean read, boolean sent, boolean seen,
|
||||
public IntroductionRequest(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, Author author, @Nullable String text,
|
||||
boolean answered, AuthorInfo authorInfo) {
|
||||
boolean answered, AuthorInfo authorInfo, long autoDeleteTimer) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
author, text, answered);
|
||||
author, text, answered, autoDeleteTimer);
|
||||
this.authorInfo = authorInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package org.briarproject.briar.api.introduction;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageVisitor;
|
||||
import org.briarproject.briar.api.conversation.ConversationResponse;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@@ -25,9 +25,10 @@ public class IntroductionResponse extends ConversationResponse {
|
||||
public IntroductionResponse(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted, Author author,
|
||||
AuthorInfo introducedAuthorInfo, Role role, boolean canSucceed) {
|
||||
AuthorInfo introducedAuthorInfo, Role role, boolean canSucceed,
|
||||
long autoDeleteTimer, boolean isAutoDecline) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
accepted);
|
||||
accepted, autoDeleteTimer, isAutoDecline);
|
||||
this.introducedAuthor = author;
|
||||
this.introducedAuthorInfo = introducedAuthorInfo;
|
||||
this.ourRole = role;
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.briarproject.briar.api.messaging;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
/**
|
||||
* An exception that is thrown when an {@link AttachmentHeader} is used to
|
||||
* load an {@link Attachment}, and the header refers to a message that is not
|
||||
* an attachment, or to an attachment that does not have the expected content
|
||||
* type.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
public class InvalidAttachmentException extends DbException {
|
||||
}
|
||||
@@ -7,22 +7,21 @@ public interface MessagingConstants {
|
||||
/**
|
||||
* The maximum length of a private message's text in UTF-8 bytes.
|
||||
*/
|
||||
int MAX_PRIVATE_MESSAGE_TEXT_LENGTH = MAX_MESSAGE_BODY_LENGTH - 1024;
|
||||
int MAX_PRIVATE_MESSAGE_TEXT_LENGTH = MAX_MESSAGE_BODY_LENGTH - 2048;
|
||||
|
||||
/**
|
||||
* The maximum length of an incoming private message's text in UTF-8 bytes.
|
||||
* This is higher than MAX_PRIVATE_MESSAGE_TEXT_LENGTH for compatibility
|
||||
* with older peers.
|
||||
* <p>
|
||||
* TODO: Remove after a reasonable migration period (added 2021-03-12).
|
||||
*/
|
||||
int MAX_PRIVATE_MESSAGE_INCOMING_TEXT_LENGTH =
|
||||
MAX_MESSAGE_BODY_LENGTH - 1024;
|
||||
|
||||
/**
|
||||
* The maximum number of attachments per private message.
|
||||
*/
|
||||
int MAX_ATTACHMENTS_PER_MESSAGE = 10;
|
||||
|
||||
/**
|
||||
* The maximum length of an attachment's content type in UTF-8 bytes.
|
||||
*/
|
||||
int MAX_CONTENT_TYPE_BYTES = 50;
|
||||
|
||||
/**
|
||||
* The maximum allowed size of image attachments.
|
||||
* TODO: Different limit for GIFs?
|
||||
*/
|
||||
int MAX_IMAGE_SIZE = MAX_MESSAGE_BODY_LENGTH - 100; // 6 * 1024 * 1024;
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.briarproject.briar.api.attachment.FileTooBigException;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager.ConversationClient;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -30,13 +32,18 @@ public interface MessagingManager extends ConversationClient {
|
||||
/**
|
||||
* The current minor version of the messaging client.
|
||||
*/
|
||||
int MINOR_VERSION = 2;
|
||||
int MINOR_VERSION = 3;
|
||||
|
||||
/**
|
||||
* Stores a local private message.
|
||||
*/
|
||||
void addLocalMessage(PrivateMessage m) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores a local private message.
|
||||
*/
|
||||
void addLocalMessage(Transaction txn, PrivateMessage m) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores a local attachment message.
|
||||
*
|
||||
@@ -68,21 +75,8 @@ public interface MessagingManager extends ConversationClient {
|
||||
String getMessageText(MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the attachment with the given message ID and content type.
|
||||
*
|
||||
* @throws InvalidAttachmentException If the header refers to a message
|
||||
* that is not an attachment, or to an attachment that does not have the
|
||||
* expected content type
|
||||
* Returns the private message format supported by the given contact.
|
||||
*/
|
||||
Attachment getAttachment(AttachmentHeader h) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the contact with the given {@link ContactId} does support
|
||||
* image attachments.
|
||||
*
|
||||
* Added: 2019-01-01
|
||||
*/
|
||||
boolean contactSupportsImages(Transaction txn, ContactId c)
|
||||
PrivateMessageFormat getContactMessageFormat(Transaction txn, ContactId c)
|
||||
throws DbException;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,50 +2,73 @@ package org.briarproject.briar.api.messaging;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.briarproject.briar.api.autodelete.AutoDeleteConstants.NO_AUTO_DELETE_TIMER;
|
||||
import static org.briarproject.briar.api.messaging.PrivateMessageFormat.TEXT_IMAGES;
|
||||
import static org.briarproject.briar.api.messaging.PrivateMessageFormat.TEXT_IMAGES_AUTO_DELETE;
|
||||
import static org.briarproject.briar.api.messaging.PrivateMessageFormat.TEXT_ONLY;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class PrivateMessage {
|
||||
|
||||
private final Message message;
|
||||
private final boolean legacyFormat, hasText;
|
||||
private final boolean hasText;
|
||||
private final List<AttachmentHeader> attachmentHeaders;
|
||||
private final long autoDeleteTimer;
|
||||
private final PrivateMessageFormat format;
|
||||
|
||||
/**
|
||||
* Constructor for private messages in the legacy format, which does not
|
||||
* support attachments.
|
||||
* Constructor for private messages in the
|
||||
* {@link PrivateMessageFormat#TEXT_ONLY TEXT_ONLY} format.
|
||||
*/
|
||||
public PrivateMessage(Message message) {
|
||||
this.message = message;
|
||||
legacyFormat = true;
|
||||
hasText = true;
|
||||
attachmentHeaders = emptyList();
|
||||
autoDeleteTimer = NO_AUTO_DELETE_TIMER;
|
||||
format = TEXT_ONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for private messages in the current format, which supports
|
||||
* attachments.
|
||||
* Constructor for private messages in the
|
||||
* {@link PrivateMessageFormat#TEXT_IMAGES TEXT_IMAGES} format.
|
||||
*/
|
||||
public PrivateMessage(Message message, boolean hasText,
|
||||
List<AttachmentHeader> headers) {
|
||||
this.message = message;
|
||||
this.hasText = hasText;
|
||||
this.attachmentHeaders = headers;
|
||||
legacyFormat = false;
|
||||
autoDeleteTimer = NO_AUTO_DELETE_TIMER;
|
||||
format = TEXT_IMAGES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for private messages in the
|
||||
* {@link PrivateMessageFormat#TEXT_IMAGES_AUTO_DELETE TEXT_IMAGES_AUTO_DELETE}
|
||||
* format.
|
||||
*/
|
||||
public PrivateMessage(Message message, boolean hasText,
|
||||
List<AttachmentHeader> headers, long autoDeleteTimer) {
|
||||
this.message = message;
|
||||
this.hasText = hasText;
|
||||
this.attachmentHeaders = headers;
|
||||
this.autoDeleteTimer = autoDeleteTimer;
|
||||
format = TEXT_IMAGES_AUTO_DELETE;
|
||||
}
|
||||
|
||||
public Message getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public boolean isLegacyFormat() {
|
||||
return legacyFormat;
|
||||
public PrivateMessageFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
public boolean hasText() {
|
||||
@@ -55,4 +78,8 @@ public class PrivateMessage {
|
||||
public List<AttachmentHeader> getAttachmentHeaders() {
|
||||
return attachmentHeaders;
|
||||
}
|
||||
|
||||
public long getAutoDeleteTimer() {
|
||||
return autoDeleteTimer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.api.messaging;
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -11,11 +12,29 @@ import javax.annotation.Nullable;
|
||||
@NotNullByDefault
|
||||
public interface PrivateMessageFactory {
|
||||
|
||||
/**
|
||||
* Creates a private message in the
|
||||
* {@link PrivateMessageFormat#TEXT_ONLY TEXT_ONLY} format.
|
||||
*/
|
||||
PrivateMessage createLegacyPrivateMessage(GroupId groupId, long timestamp,
|
||||
String text) throws FormatException;
|
||||
|
||||
/**
|
||||
* Creates a private message in the
|
||||
* {@link PrivateMessageFormat#TEXT_IMAGES TEXT_IMAGES} format. This format
|
||||
* requires the contact to support client version 0.1 or higher.
|
||||
*/
|
||||
PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
|
||||
@Nullable String text, List<AttachmentHeader> headers)
|
||||
throws FormatException;
|
||||
|
||||
/**
|
||||
* Creates a private message in the
|
||||
* {@link PrivateMessageFormat#TEXT_IMAGES_AUTO_DELETE TEXT_IMAGES_AUTO_DELETE}
|
||||
* format. This format requires the contact to support client version 0.3
|
||||
* or higher.
|
||||
*/
|
||||
PrivateMessage createPrivateMessage(GroupId groupId, long timestamp,
|
||||
@Nullable String text, List<AttachmentHeader> headers,
|
||||
long autoDeleteTimer) throws FormatException;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.briarproject.briar.api.messaging;
|
||||
|
||||
public enum PrivateMessageFormat {
|
||||
|
||||
/**
|
||||
* First version of the private message format, which doesn't support
|
||||
* image attachments or auto-deletion.
|
||||
*/
|
||||
TEXT_ONLY,
|
||||
|
||||
/**
|
||||
* Second version of the private message format, which supports image
|
||||
* attachments but not auto-deletion. Support for this format was
|
||||
* added in client version 0.1.
|
||||
*/
|
||||
TEXT_IMAGES,
|
||||
|
||||
/**
|
||||
* Third version of the private message format, which supports image
|
||||
* attachments and auto-deletion. Support for this format was added
|
||||
* in client version 0.3.
|
||||
*/
|
||||
TEXT_IMAGES_AUTO_DELETE
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.api.messaging;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageVisitor;
|
||||
|
||||
@@ -19,8 +20,9 @@ public class PrivateMessageHeader extends ConversationMessageHeader {
|
||||
|
||||
public PrivateMessageHeader(MessageId id, GroupId groupId, long timestamp,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
boolean hasText, List<AttachmentHeader> headers) {
|
||||
super(id, groupId, timestamp, local, read, sent, seen);
|
||||
boolean hasText, List<AttachmentHeader> headers,
|
||||
long autoDeleteTimer) {
|
||||
super(id, groupId, timestamp, local, read, sent, seen, autoDeleteTimer);
|
||||
this.hasText = hasText;
|
||||
this.attachmentHeaders = headers;
|
||||
}
|
||||
@@ -37,5 +39,4 @@ public class PrivateMessageHeader extends ConversationMessageHeader {
|
||||
public <T> T accept(ConversationMessageVisitor<T> v) {
|
||||
return v.visitPrivateMessageHeader(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.briarproject.briar.api.privategroup;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.briarproject.briar.api.privategroup;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.briar.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
@@ -8,21 +8,14 @@ import javax.annotation.concurrent.Immutable;
|
||||
@NotNullByDefault
|
||||
public class JoinMessageHeader extends GroupMessageHeader {
|
||||
|
||||
private final Visibility visibility;
|
||||
private final boolean isInitial;
|
||||
|
||||
public JoinMessageHeader(GroupMessageHeader h, Visibility visibility,
|
||||
boolean isInitial) {
|
||||
public JoinMessageHeader(GroupMessageHeader h, boolean isInitial) {
|
||||
super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
|
||||
h.getAuthor(), h.getAuthorInfo(), h.isRead());
|
||||
this.visibility = visibility;
|
||||
this.isInitial = isInitial;
|
||||
}
|
||||
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
public boolean isInitial() {
|
||||
return isInitial;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface PrivateGroupManager {
|
||||
@@ -66,6 +67,11 @@ public interface PrivateGroupManager {
|
||||
*/
|
||||
void markGroupDissolved(Transaction txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the given private group has been dissolved.
|
||||
*/
|
||||
boolean isDissolved(Transaction txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the given private group has been dissolved.
|
||||
*/
|
||||
@@ -76,6 +82,12 @@ public interface PrivateGroupManager {
|
||||
*/
|
||||
GroupMessageHeader addLocalMessage(GroupMessage p) throws DbException;
|
||||
|
||||
/**
|
||||
* Stores and sends a local private group message.
|
||||
*/
|
||||
GroupMessageHeader addLocalMessage(Transaction txn, GroupMessage p)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the private group with the given ID.
|
||||
*/
|
||||
@@ -91,26 +103,54 @@ public interface PrivateGroupManager {
|
||||
*/
|
||||
Collection<PrivateGroup> getPrivateGroups() throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all private groups the user is a member of.
|
||||
*/
|
||||
Collection<PrivateGroup> getPrivateGroups(Transaction txn)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the private group message with the given ID.
|
||||
*/
|
||||
String getMessageText(MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the text of the private group message with the given ID.
|
||||
*/
|
||||
String getMessageText(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all messages in the given private group.
|
||||
*/
|
||||
Collection<GroupMessageHeader> getHeaders(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the headers of all messages in the given private group.
|
||||
*/
|
||||
List<GroupMessageHeader> getHeaders(Transaction txn, GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all members of the given private group.
|
||||
*/
|
||||
Collection<GroupMember> getMembers(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all members of the given private group.
|
||||
*/
|
||||
Collection<GroupMember> getMembers(Transaction txn, GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the given author is a member of the given private group.
|
||||
*/
|
||||
boolean isMember(Transaction txn, GroupId g, Author a) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group count for the given private group.
|
||||
*/
|
||||
GroupCount getGroupCount(Transaction txn, GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the group count for the given private group.
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface GroupInvitationManager extends ConversationClient {
|
||||
/**
|
||||
* The current minor version of the private group invitation client.
|
||||
*/
|
||||
int MINOR_VERSION = 0;
|
||||
int MINOR_VERSION = 1;
|
||||
|
||||
/**
|
||||
* Sends an invitation to share the given private group with the given
|
||||
@@ -43,7 +43,8 @@ public interface GroupInvitationManager extends ConversationClient {
|
||||
* pending.
|
||||
*/
|
||||
void sendInvitation(GroupId g, ContactId c, @Nullable String text,
|
||||
long timestamp, byte[] signature) throws DbException;
|
||||
long timestamp, byte[] signature, long autoDeleteTimer)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to a pending private group invitation from the given contact.
|
||||
|
||||
@@ -18,9 +18,10 @@ public class GroupInvitationRequest extends InvitationRequest<PrivateGroup> {
|
||||
public GroupInvitationRequest(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, PrivateGroup shareable,
|
||||
@Nullable String text, boolean available, boolean canBeOpened) {
|
||||
@Nullable String text, boolean available, boolean canBeOpened,
|
||||
long autoDeleteTimer) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, shareable,
|
||||
text, available, canBeOpened);
|
||||
text, available, canBeOpened, autoDeleteTimer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,9 +15,10 @@ public class GroupInvitationResponse extends InvitationResponse {
|
||||
|
||||
public GroupInvitationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accept, GroupId shareableId) {
|
||||
SessionId sessionId, boolean accept, GroupId shareableId,
|
||||
long autoDeleteTimer, boolean isAutoDecline) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId,
|
||||
accept, shareableId);
|
||||
accept, shareableId, autoDeleteTimer, isAutoDecline);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,9 +15,9 @@ public abstract class InvitationRequest<S extends Shareable> extends
|
||||
public InvitationRequest(MessageId messageId, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, S object, @Nullable String text,
|
||||
boolean available, boolean canBeOpened) {
|
||||
boolean available, boolean canBeOpened, long autoDeleteTimer) {
|
||||
super(messageId, groupId, time, local, read, sent, seen, sessionId,
|
||||
object, text, !available);
|
||||
object, text, !available, autoDeleteTimer);
|
||||
this.canBeOpened = canBeOpened;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ public abstract class InvitationResponse extends ConversationResponse {
|
||||
|
||||
public InvitationResponse(MessageId id, GroupId groupId, long time,
|
||||
boolean local, boolean read, boolean sent, boolean seen,
|
||||
SessionId sessionId, boolean accepted, GroupId shareableId) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, accepted);
|
||||
SessionId sessionId, boolean accepted, GroupId shareableId,
|
||||
long autoDeleteTimer, boolean isAutoDecline) {
|
||||
super(id, groupId, time, local, read, sent, seen, sessionId, accepted,
|
||||
autoDeleteTimer, isAutoDecline);
|
||||
this.shareableId = shareableId;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.briar.api.sharing;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.briar.api.client.SessionId;
|
||||
@@ -21,7 +22,7 @@ public interface SharingManager<S extends Shareable>
|
||||
* including optional text.
|
||||
*/
|
||||
void sendInvitation(GroupId shareableId, ContactId contactId,
|
||||
@Nullable String text, long timestamp) throws DbException;
|
||||
@Nullable String text) throws DbException;
|
||||
|
||||
/**
|
||||
* Responds to a pending group invitation
|
||||
@@ -45,6 +46,12 @@ public interface SharingManager<S extends Shareable>
|
||||
*/
|
||||
Collection<Contact> getSharedWith(GroupId g) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns all contacts with whom the given group is shared.
|
||||
*/
|
||||
Collection<Contact> getSharedWith(Transaction txn, GroupId g)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns true if the group not already shared and no invitation is open
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.briarproject.briar.api.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface TestAvatarCreator {
|
||||
@Nullable
|
||||
InputStream getAvatarInputStream() throws IOException;
|
||||
}
|
||||
@@ -14,13 +14,16 @@ public interface TestDataCreator {
|
||||
* @param numContacts Number of contacts to create. Must be >= 1
|
||||
* @param numPrivateMsgs Number of private messages to create for each
|
||||
* contact.
|
||||
* @param avatarPercent Percentage of contacts
|
||||
* that will use a random profile image. Between 0 and 100.
|
||||
* @param numBlogPosts Number of blog posts to create.
|
||||
* @param numForums Number of forums to create.
|
||||
* @param numForumPosts Number of forum posts to create per forum.
|
||||
*/
|
||||
void createTestData(int numContacts, int numPrivateMsgs, int numBlogPosts,
|
||||
int numForums, int numForumPosts);
|
||||
void createTestData(int numContacts, int numPrivateMsgs, int avatarPercent,
|
||||
int numBlogPosts, int numForums, int numForumPosts);
|
||||
|
||||
@IoExecutor
|
||||
Contact addContact(String name) throws DbException;
|
||||
Contact addContact(String name, boolean alias, boolean avatar)
|
||||
throws DbException;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.briarproject.briar.api.identity;
|
||||
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.briar.api.attachment.MediaConstants.MAX_CONTENT_TYPE_BYTES;
|
||||
import static org.briarproject.briar.api.identity.AuthorInfo.Status.NONE;
|
||||
import static org.briarproject.briar.api.identity.AuthorInfo.Status.VERIFIED;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
public class AuthorInfoTest extends BrambleTestCase {
|
||||
|
||||
private final String contentType = getRandomString(MAX_CONTENT_TYPE_BYTES);
|
||||
private final AttachmentHeader avatarHeader =
|
||||
new AttachmentHeader(new GroupId(getRandomId()),
|
||||
new MessageId(getRandomId()), contentType);
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(NONE, null, null)
|
||||
);
|
||||
assertEquals(
|
||||
new AuthorInfo(NONE, "test", null),
|
||||
new AuthorInfo(NONE, "test", null)
|
||||
);
|
||||
assertEquals(
|
||||
new AuthorInfo(NONE, "test", avatarHeader),
|
||||
new AuthorInfo(NONE, "test", avatarHeader)
|
||||
);
|
||||
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(VERIFIED)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE, "test", null),
|
||||
new AuthorInfo(NONE)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(NONE, "test", null)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE, "a", null),
|
||||
new AuthorInfo(NONE, "b", null)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE, "a", null),
|
||||
new AuthorInfo(NONE, "a", avatarHeader)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
|
||||
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
|
||||
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
|
||||
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
|
||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user