diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt index 8ca06d701e..052b4d4259 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt @@ -897,7 +897,7 @@ object DataMessageProcessor { SignalDatabase.messages.beginTransaction() try { - val quote: QuoteModel? = getValidatedQuote(context, envelope.timestamp!!, message) + val quote: QuoteModel? = getValidatedQuote(context, envelope.timestamp!!, message, senderRecipient, threadRecipient) val contacts: List = getContacts(message) val linkPreviews: List = getLinkPreviews(message.preview, message.body ?: "", false) val mentions: List = getMentions(message.bodyRanges.take(BODY_RANGE_PROCESSING_LIMIT)) @@ -1077,7 +1077,7 @@ object DataMessageProcessor { return SignalDatabase.messages.insertMessageInbox(textMessage).orNull() } - fun getValidatedQuote(context: Context, timestamp: Long, message: DataMessage): QuoteModel? { + fun getValidatedQuote(context: Context, timestamp: Long, message: DataMessage, senderRecipient: Recipient, threadRecipient: Recipient): QuoteModel? { val quote: DataMessage.Quote = message.quote ?: return null if (quote.id == null) { @@ -1088,7 +1088,7 @@ object DataMessageProcessor { val authorId = Recipient.externalPush(ServiceId.parseOrThrow(quote.authorAci!!)).id var quotedMessage = SignalDatabase.messages.getMessageFor(quote.id!!, authorId) as? MmsMessageRecord - if (quotedMessage != null && !quotedMessage.isRemoteDelete) { + if (quotedMessage != null && isSenderValid(quotedMessage, timestamp, senderRecipient, threadRecipient) && !quotedMessage.isRemoteDelete) { log(timestamp, "Found matching message record...") val attachments: MutableList = mutableListOf() @@ -1127,7 +1127,7 @@ object DataMessageProcessor { QuoteModel.Type.fromProto(quote.type), quotedMessage.messageRanges ) - } else if (quotedMessage != null) { + } else if (quotedMessage != null && quotedMessage.isRemoteDelete) { warn(timestamp, "Found the target for the quote, but it's flagged as remotely deleted.") } @@ -1144,6 +1144,21 @@ object DataMessageProcessor { ) } + private fun isSenderValid(quotedMessage: MmsMessageRecord, timestamp: Long, senderRecipient: Recipient, threadRecipient: Recipient): Boolean { + if (threadRecipient.isGroup) { + val groupRecord = SignalDatabase.groups.getGroup(threadRecipient.id).orNull() + if (groupRecord != null && !groupRecord.members.contains(senderRecipient.id)) { + warn(timestamp, "Sender is not in the group! Thread: ${quotedMessage.threadId} Sender: ${senderRecipient.id}") + return false + } + } else if (senderRecipient.id != threadRecipient.id) { + warn(timestamp, "Sender is not a part of the 1:1 thread! Thread: ${quotedMessage.threadId} Sender: ${senderRecipient.id}") + return false + } + + return true + } + fun getContacts(message: DataMessage): List { return message.contact.map { ContactModelMapper.remoteToLocal(it) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt index 8bbc965679..2cb2bfede6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt @@ -446,6 +446,7 @@ open class MessageContentProcessor(private val context: Context) { SyncMessageProcessor.process( context, senderRecipient, + threadRecipient, envelope, content, metadata, diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt index f5ef7ca7f7..6723ad5ac9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt @@ -136,6 +136,7 @@ object SyncMessageProcessor { fun process( context: Context, senderRecipient: Recipient, + threadRecipient: Recipient, envelope: Envelope, content: Content, metadata: EnvelopeMetadata, @@ -144,7 +145,7 @@ object SyncMessageProcessor { val syncMessage = content.syncMessage!! when { - syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, earlyMessageCacheEntry) + syncMessage.sent != null -> handleSynchronizeSentMessage(context, envelope, content, metadata, syncMessage.sent!!, senderRecipient, threadRecipient, earlyMessageCacheEntry) syncMessage.request != null -> handleSynchronizeRequestMessage(context, syncMessage.request!!, envelope.timestamp!!) syncMessage.read.isNotEmpty() -> handleSynchronizeReadMessage(context, syncMessage.read, envelope.timestamp!!, earlyMessageCacheEntry) syncMessage.viewed.isNotEmpty() -> handleSynchronizeViewedMessage(context, syncMessage.viewed, envelope.timestamp!!) @@ -174,6 +175,7 @@ object SyncMessageProcessor { metadata: EnvelopeMetadata, sent: Sent, senderRecipient: Recipient, + threadRecipient: Recipient, earlyMessageCacheEntry: EarlyMessageCacheEntry? ) { log(envelope.timestamp!!, "Processing sent transcript for message with ID ${sent.timestamp!!}") @@ -227,7 +229,7 @@ object SyncMessageProcessor { threadId = SignalDatabase.threads.getOrCreateThreadIdFor(getSyncMessageDestination(sent)) } dataMessage.hasRemoteDelete -> DataMessageProcessor.handleRemoteDelete(context, envelope, dataMessage, senderRecipient.id, earlyMessageCacheEntry) - dataMessage.isMediaMessage -> threadId = handleSynchronizeSentMediaMessage(context, sent, envelope.timestamp!!) + dataMessage.isMediaMessage -> threadId = handleSynchronizeSentMediaMessage(context, sent, envelope.timestamp!!, senderRecipient, threadRecipient) else -> threadId = handleSynchronizeSentTextMessage(sent, envelope.timestamp!!) } @@ -803,12 +805,12 @@ object SyncMessageProcessor { } @Throws(MmsException::class, BadGroupIdException::class) - private fun handleSynchronizeSentMediaMessage(context: Context, sent: Sent, envelopeTimestamp: Long): Long { + private fun handleSynchronizeSentMediaMessage(context: Context, sent: Sent, envelopeTimestamp: Long, senderRecipient: Recipient, threadRecipient: Recipient): Long { log(envelopeTimestamp, "Synchronize sent media message for " + sent.timestamp!!) val recipient: Recipient = getSyncMessageDestination(sent) val dataMessage: DataMessage = sent.message!! - val quote: QuoteModel? = DataMessageProcessor.getValidatedQuote(context, envelopeTimestamp, dataMessage) + val quote: QuoteModel? = DataMessageProcessor.getValidatedQuote(context, envelopeTimestamp, dataMessage, senderRecipient, threadRecipient) val sticker: Attachment? = DataMessageProcessor.getStickerAttachment(envelopeTimestamp, dataMessage) val sharedContacts: List = DataMessageProcessor.getContacts(dataMessage) val previews: List = DataMessageProcessor.getLinkPreviews(dataMessage.preview, dataMessage.body ?: "", false)