mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-15 04:18:53 +01:00
Ensure that attachment has expected group ID when loading.
This commit is contained in:
@@ -4,6 +4,8 @@ import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.attachment.Attachment;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
@@ -31,7 +33,13 @@ public class AttachmentReaderImpl implements AttachmentReader {
|
||||
public Attachment getAttachment(AttachmentHeader h) throws DbException {
|
||||
// TODO: Support large messages
|
||||
MessageId m = h.getMessageId();
|
||||
byte[] body = clientHelper.getMessage(m).getBody();
|
||||
Message message = clientHelper.getMessage(m);
|
||||
// Check that the message is in the expected group, to prevent it from
|
||||
// being loaded in the context of a different group
|
||||
if (!message.getGroupId().equals(h.getGroupId())) {
|
||||
throw new NoSuchMessageException();
|
||||
}
|
||||
byte[] body = message.getBody();
|
||||
try {
|
||||
BdfDictionary meta = clientHelper.getMessageMetadataAsDictionary(m);
|
||||
String contentType = meta.getString(MSG_KEY_CONTENT_TYPE);
|
||||
|
||||
@@ -149,7 +149,8 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
|
||||
}
|
||||
ContactId contactId = getContactId(txn, m.getGroupId());
|
||||
String contentType = d.getString(MSG_KEY_CONTENT_TYPE);
|
||||
AttachmentHeader a = new AttachmentHeader(m.getId(), contentType);
|
||||
AttachmentHeader a = new AttachmentHeader(m.getGroupId(), m.getId(),
|
||||
contentType);
|
||||
txn.attach(new AvatarUpdatedEvent(contactId, a));
|
||||
} catch (FormatException e) {
|
||||
throw new InvalidMessageException(e);
|
||||
@@ -184,7 +185,7 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
|
||||
if (newLatest != null && newLatest.version > version) {
|
||||
// latest update is newer than our own
|
||||
// no need to store or delete anything, just return latest
|
||||
return new AttachmentHeader(newLatest.messageId,
|
||||
return new AttachmentHeader(groupId, newLatest.messageId,
|
||||
newLatest.contentType);
|
||||
} else if (newLatest != null) {
|
||||
// delete latest update if it has the same or lower version
|
||||
@@ -192,7 +193,7 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
|
||||
db.deleteMessageMetadata(txn2, newLatest.messageId);
|
||||
}
|
||||
clientHelper.addLocalMessage(txn2, m, meta, true, false);
|
||||
return new AttachmentHeader(m.getId(), contentType);
|
||||
return new AttachmentHeader(groupId, m.getId(), contentType);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -225,7 +226,8 @@ class AvatarManagerImpl implements AvatarManager, OpenDatabaseHook, ContactHook,
|
||||
throws DbException, FormatException {
|
||||
LatestUpdate latest = findLatest(txn, groupId);
|
||||
if (latest == null) return null;
|
||||
return new AttachmentHeader(latest.messageId, latest.contentType);
|
||||
return new AttachmentHeader(groupId, latest.messageId,
|
||||
latest.contentType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -172,7 +172,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
} else if (messageType == PRIVATE_MESSAGE) {
|
||||
boolean hasText = metaDict.getBoolean(MSG_KEY_HAS_TEXT);
|
||||
List<AttachmentHeader> headers =
|
||||
parseAttachmentHeaders(metaDict);
|
||||
parseAttachmentHeaders(m.getGroupId(), metaDict);
|
||||
incomingPrivateMessage(txn, m, metaDict, hasText, headers);
|
||||
} else if (messageType == ATTACHMENT) {
|
||||
incomingAttachment(txn, m);
|
||||
@@ -203,16 +203,17 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
messageTracker.trackIncomingMessage(txn, m);
|
||||
}
|
||||
|
||||
private List<AttachmentHeader> parseAttachmentHeaders(BdfDictionary meta)
|
||||
private List<AttachmentHeader> parseAttachmentHeaders(GroupId g,
|
||||
BdfDictionary meta)
|
||||
throws FormatException {
|
||||
BdfList attachmentHeaders = meta.getList(MSG_KEY_ATTACHMENT_HEADERS);
|
||||
int length = attachmentHeaders.size();
|
||||
List<AttachmentHeader> headers = new ArrayList<>(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
BdfList header = attachmentHeaders.getList(i);
|
||||
MessageId id = new MessageId(header.getRaw(0));
|
||||
MessageId m = new MessageId(header.getRaw(0));
|
||||
String contentType = header.getString(1);
|
||||
headers.add(new AttachmentHeader(id, contentType));
|
||||
headers.add(new AttachmentHeader(g, m, contentType));
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
@@ -280,7 +281,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
// Mark attachments as temporary, not shared until we're ready to send
|
||||
db.transaction(false, txn ->
|
||||
clientHelper.addLocalMessage(txn, m, meta, false, true));
|
||||
return new AttachmentHeader(m.getId(), contentType);
|
||||
return new AttachmentHeader(groupId, m.getId(), contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,7 +358,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
boolean hasText = meta.getBoolean(MSG_KEY_HAS_TEXT);
|
||||
headers.add(new PrivateMessageHeader(id, g, timestamp,
|
||||
local, read, s.isSent(), s.isSeen(), hasText,
|
||||
parseAttachmentHeaders(meta)));
|
||||
parseAttachmentHeaders(g, meta)));
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
@@ -424,6 +425,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
public DeletionResult deleteMessages(Transaction txn, ContactId c,
|
||||
Set<MessageId> messageIds) throws DbException {
|
||||
DeletionResult result = new DeletionResult();
|
||||
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
|
||||
for (MessageId m : messageIds) {
|
||||
// get attachment headers
|
||||
List<AttachmentHeader> headers;
|
||||
@@ -434,7 +436,7 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
if (messageType != null && messageType != PRIVATE_MESSAGE)
|
||||
throw new AssertionError("not supported");
|
||||
headers = messageType == null ? emptyList() :
|
||||
parseAttachmentHeaders(meta);
|
||||
parseAttachmentHeaders(g, meta);
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -460,7 +462,6 @@ class MessagingManagerImpl implements MessagingManager, IncomingMessageHook,
|
||||
result.addNotFullyDownloaded();
|
||||
}
|
||||
}
|
||||
GroupId g = getContactGroup(db.getContact(txn, c)).getId();
|
||||
recalculateGroupCount(txn, g);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.briarproject.briar.attachment;
|
||||
|
||||
import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||
import org.briarproject.bramble.api.data.BdfEntry;
|
||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.briar.api.attachment.Attachment;
|
||||
import org.briarproject.briar.api.attachment.AttachmentHeader;
|
||||
import org.briarproject.briar.api.attachment.InvalidAttachmentException;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static java.lang.System.arraycopy;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMessage;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.util.IoUtils.copyAndClose;
|
||||
import static org.briarproject.briar.api.attachment.MediaConstants.MSG_KEY_CONTENT_TYPE;
|
||||
import static org.briarproject.briar.api.attachment.MediaConstants.MSG_KEY_DESCRIPTOR_LENGTH;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
public class AttachmentReaderImplTest extends BrambleMockTestCase {
|
||||
|
||||
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||
|
||||
private final GroupId groupId = new GroupId(getRandomId());
|
||||
private final Message message = getMessage(groupId, 1234);
|
||||
private final String contentType = "image/jpeg";
|
||||
private final AttachmentHeader header = new AttachmentHeader(groupId,
|
||||
message.getId(), contentType);
|
||||
|
||||
private final AttachmentReaderImpl attachmentReader =
|
||||
new AttachmentReaderImpl(clientHelper);
|
||||
|
||||
@Test(expected = NoSuchMessageException.class)
|
||||
public void testWrongGroup() throws Exception {
|
||||
GroupId wrongGroupId = new GroupId(getRandomId());
|
||||
AttachmentHeader wrongGroup = new AttachmentHeader(wrongGroupId,
|
||||
message.getId(), contentType);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getMessage(message.getId());
|
||||
will(returnValue(message));
|
||||
}});
|
||||
|
||||
attachmentReader.getAttachment(wrongGroup);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidAttachmentException.class)
|
||||
public void testMissingContentType() throws Exception {
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
|
||||
testInvalidMetadata(meta);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidAttachmentException.class)
|
||||
public void testWrongContentType() throws Exception {
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_CONTENT_TYPE, "image/png"));
|
||||
|
||||
testInvalidMetadata(meta);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidAttachmentException.class)
|
||||
public void testMissingDescriptorLength() throws Exception {
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_CONTENT_TYPE, contentType));
|
||||
|
||||
testInvalidMetadata(meta);
|
||||
}
|
||||
|
||||
private void testInvalidMetadata(BdfDictionary meta) throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getMessage(message.getId());
|
||||
will(returnValue(message));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(message.getId());
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
|
||||
attachmentReader.getAttachment(header);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSkipsDescriptor() throws Exception {
|
||||
int descriptorLength = 123;
|
||||
BdfDictionary meta = BdfDictionary.of(
|
||||
new BdfEntry(MSG_KEY_CONTENT_TYPE, contentType),
|
||||
new BdfEntry(MSG_KEY_DESCRIPTOR_LENGTH, descriptorLength));
|
||||
|
||||
byte[] body = message.getBody();
|
||||
byte[] expectedData = new byte[body.length - descriptorLength];
|
||||
arraycopy(body, descriptorLength, expectedData, 0, expectedData.length);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(clientHelper).getMessage(message.getId());
|
||||
will(returnValue(message));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(message.getId());
|
||||
will(returnValue(meta));
|
||||
}});
|
||||
|
||||
Attachment attachment = attachmentReader.getAttachment(header);
|
||||
InputStream in = attachment.getStream();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
copyAndClose(in, out);
|
||||
byte[] data = out.toByteArray();
|
||||
|
||||
assertArrayEquals(expectedData, data);
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
@@ -49,7 +50,8 @@ public class AuthorManagerImplTest extends BrambleMockTestCase {
|
||||
private final Contact contact = getContact(remote, local, verified);
|
||||
private final String contentType = getRandomString(MAX_CONTENT_TYPE_BYTES);
|
||||
private final AttachmentHeader avatarHeader =
|
||||
new AttachmentHeader(new MessageId(getRandomId()), contentType);
|
||||
new AttachmentHeader(new GroupId(getRandomId()),
|
||||
new MessageId(getRandomId()), contentType);
|
||||
|
||||
private final AuthorManagerImpl authorManager =
|
||||
new AuthorManagerImpl(db, identityManager, avatarManager);
|
||||
|
||||
@@ -73,7 +73,8 @@ public class MessageSizeIntegrationTest extends BriarTestCase {
|
||||
// Create the maximum number of maximum-length attachment headers
|
||||
List<AttachmentHeader> headers = new ArrayList<>();
|
||||
for (int i = 0; i < MAX_ATTACHMENTS_PER_MESSAGE; i++) {
|
||||
headers.add(new AttachmentHeader(new MessageId(getRandomId()),
|
||||
headers.add(new AttachmentHeader(groupId,
|
||||
new MessageId(getRandomId()),
|
||||
getRandomString(MAX_CONTENT_TYPE_BYTES)));
|
||||
}
|
||||
PrivateMessage message = privateMessageFactory.createPrivateMessage(
|
||||
|
||||
Reference in New Issue
Block a user