From 8bc7d1b7f52b41cafb2a58197fb413aeb5271626 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 5 Jan 2022 14:06:59 -0500 Subject: [PATCH] Drop messages that have a story context. --- .../messages/MessageContentProcessor.java | 5 ++ .../api/SignalServiceMessageSender.java | 8 +++ .../api/messages/SignalServiceContent.java | 18 +++++- .../messages/SignalServiceDataMessage.java | 58 ++++++++++++++++--- .../src/main/proto/SignalService.proto | 6 ++ 5 files changed, 86 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java index 330add10c..f59e2ec61 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -259,6 +259,7 @@ public final class MessageContentProcessor { else if (message.getReaction().isPresent()) messageId = handleReaction(content, message, senderRecipient); else if (message.getRemoteDelete().isPresent()) messageId = handleRemoteDelete(content, message, senderRecipient); else if (message.getPayment().isPresent()) handlePayment(content, message, senderRecipient); + else if (message.getStoryContext().isPresent()) handleStoryMessage(content); else if (isMediaMessage) messageId = handleMediaMessage(content, message, smsMessageId, senderRecipient, threadRecipient, receivedTime); else if (message.getBody().isPresent()) messageId = handleTextMessage(content, message, smsMessageId, groupId, senderRecipient, threadRecipient, receivedTime); else if (Build.VERSION.SDK_INT > 19 && message.getGroupCallUpdate().isPresent()) handleGroupCallUpdateMessage(content, message, groupId, senderRecipient); @@ -1256,6 +1257,10 @@ public final class MessageContentProcessor { messageNotifier.updateNotification(context); } + private void handleStoryMessage(SignalServiceContent content) { + warn(content.getTimestamp(), "Detected a story reply. We do not support this yet. Dropping."); + } + private @Nullable MessageId handleMediaMessage(@NonNull SignalServiceContent content, @NonNull SignalServiceDataMessage message, @NonNull Optional smsMessageId, diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 32b8b3098..a29fee16e 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -901,6 +901,14 @@ public class SignalServiceMessageSender { } } + if (message.getStoryContext().isPresent()) { + SignalServiceDataMessage.StoryContext storyContext = message.getStoryContext().get(); + + builder.setStoryContext(DataMessage.StoryContext.newBuilder() + .setAuthorUuid(storyContext.getAuthorAci().toString()) + .setSentTimestamp(storyContext.getSentTimestamp())); + } + builder.setTimestamp(message.getTimestamp()); return enforceMaxContentSize(container.setDataMessage(builder).build()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java index 9b00072a3..dea1989e4 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java @@ -529,6 +529,7 @@ public final class SignalServiceContent { SignalServiceDataMessage.Reaction reaction = createReaction(content); SignalServiceDataMessage.RemoteDelete remoteDelete = createRemoteDelete(content); SignalServiceDataMessage.GroupCallUpdate groupCallUpdate = createGroupCallUpdate(content); + SignalServiceDataMessage.StoryContext storyContext = createStoryContext(content); if (content.getRequiredProtocolVersion() > SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE) { throw new UnsupportedDataMessageProtocolVersionException(SignalServiceProtos.DataMessage.ProtocolVersion.CURRENT_VALUE, @@ -577,7 +578,8 @@ public final class SignalServiceContent { reaction, remoteDelete, groupCallUpdate, - payment); + payment, + storyContext); } private static SignalServiceSyncMessage createSynchronizeMessage(SignalServiceMetadata metadata, @@ -1036,6 +1038,20 @@ public final class SignalServiceContent { } } + private static SignalServiceDataMessage.StoryContext createStoryContext(SignalServiceProtos.DataMessage content) throws InvalidMessageStructureException { + if (!content.hasStoryContext()) { + return null; + } + + ACI aci = ACI.parseOrNull(content.getStoryContext().getAuthorUuid()); + + if (aci == null) { + throw new InvalidMessageStructureException("Invalid author ACI!"); + } + + return new SignalServiceDataMessage.StoryContext(aci, content.getStoryContext().getSentTimestamp()); + } + private static SignalServiceDataMessage.PaymentNotification createPaymentNotification(SignalServiceProtos.DataMessage.Payment content) throws InvalidMessageStructureException { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java index 5c3222914..dab6be261 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java @@ -16,7 +16,6 @@ import org.whispersystems.signalservice.api.util.OptionalUtil; import java.util.LinkedList; import java.util.List; -import java.util.UUID; /** * Represents a decrypted Signal Service data message. @@ -42,6 +41,7 @@ public class SignalServiceDataMessage { private final Optional remoteDelete; private final Optional groupCallUpdate; private final Optional payment; + private final Optional storyContext; /** * Construct a SignalServiceDataMessage. @@ -55,14 +55,26 @@ public class SignalServiceDataMessage { * @param expiresInSeconds Number of seconds in which the message should disappear after being seen. */ SignalServiceDataMessage(long timestamp, - SignalServiceGroup group, SignalServiceGroupV2 groupV2, + SignalServiceGroup group, + SignalServiceGroupV2 groupV2, List attachments, - String body, boolean endSession, int expiresInSeconds, - boolean expirationUpdate, byte[] profileKey, boolean profileKeyUpdate, - Quote quote, List sharedContacts, List previews, - List mentions, Sticker sticker, boolean viewOnce, Reaction reaction, RemoteDelete remoteDelete, + String body, + boolean endSession, + int expiresInSeconds, + boolean expirationUpdate, + byte[] profileKey, + boolean profileKeyUpdate, + Quote quote, + List sharedContacts, + List previews, + List mentions, + Sticker sticker, + boolean viewOnce, + Reaction reaction, + RemoteDelete remoteDelete, GroupCallUpdate groupCallUpdate, - Payment payment) + Payment payment, + StoryContext storyContext) { try { this.group = SignalServiceGroupContext.createOptional(group, groupV2); @@ -84,6 +96,7 @@ public class SignalServiceDataMessage { this.remoteDelete = Optional.fromNullable(remoteDelete); this.groupCallUpdate = Optional.fromNullable(groupCallUpdate); this.payment = Optional.fromNullable(payment); + this.storyContext = Optional.fromNullable(storyContext); if (attachments != null && !attachments.isEmpty()) { this.attachments = Optional.of(attachments); @@ -236,6 +249,10 @@ public class SignalServiceDataMessage { return payment; } + public Optional getStoryContext() { + return storyContext; + } + public Optional getGroupId() { byte[] groupId = null; @@ -273,6 +290,7 @@ public class SignalServiceDataMessage { private RemoteDelete remoteDelete; private GroupCallUpdate groupCallUpdate; private Payment payment; + private StoryContext storyContext; private Builder() {} @@ -400,6 +418,11 @@ public class SignalServiceDataMessage { return this; } + public Builder withStoryContext(StoryContext storyContext) { + this.storyContext = storyContext; + return this; + } + public SignalServiceDataMessage build() { if (timestamp == 0) timestamp = System.currentTimeMillis(); return new SignalServiceDataMessage(timestamp, group, groupV2, attachments, body, endSession, @@ -407,7 +430,8 @@ public class SignalServiceDataMessage { profileKeyUpdate, quote, sharedContacts, previews, mentions, sticker, viewOnce, reaction, remoteDelete, groupCallUpdate, - payment); + payment, + storyContext); } } @@ -651,4 +675,22 @@ public class SignalServiceDataMessage { return paymentNotification; } } + + public static class StoryContext { + private final ACI authorAci; + private final long sentTimestamp; + + public StoryContext(ACI authorAci, long sentTimestamp) { + this.authorAci = authorAci; + this.sentTimestamp = sentTimestamp; + } + + public ACI getAuthorAci() { + return authorAci; + } + + public long getSentTimestamp() { + return sentTimestamp; + } + } } diff --git a/libsignal/service/src/main/proto/SignalService.proto b/libsignal/service/src/main/proto/SignalService.proto index a02d54a22..889ec66aa 100644 --- a/libsignal/service/src/main/proto/SignalService.proto +++ b/libsignal/service/src/main/proto/SignalService.proto @@ -248,6 +248,11 @@ message DataMessage { optional string eraId = 1; } + message StoryContext { + optional string authorUuid = 1; + optional uint64 sentTimestamp = 2; + } + message Payment { message Address { @@ -320,6 +325,7 @@ message DataMessage { repeated BodyRange bodyRanges = 18; optional GroupCallUpdate groupCallUpdate = 19; optional Payment payment = 20; + optional StoryContext storyContext = 21; } message NullMessage {