include origin-id only in mucs and only if stable-id is not supported

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/generator/MessageGenerator.java   | 152 
src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java |  10 
2 files changed, 112 insertions(+), 50 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/generator/MessageGenerator.java 🔗

@@ -1,12 +1,5 @@
 package eu.siacs.conversations.generator;
 
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
@@ -26,19 +19,31 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
 import im.conversations.android.xmpp.model.correction.Replace;
 import im.conversations.android.xmpp.model.reactions.Reaction;
 import im.conversations.android.xmpp.model.reactions.Reactions;
+import im.conversations.android.xmpp.model.unique.OriginId;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
 
 public class MessageGenerator extends AbstractGenerator {
-    private static final String OMEMO_FALLBACK_MESSAGE = "I sent you an OMEMO encrypted message but your client doesn’t seem to support that. Find more information on https://conversations.im/omemo";
-    private static final String PGP_FALLBACK_MESSAGE = "I sent you a PGP encrypted message but your client doesn’t seem to support that.";
+    private static final String OMEMO_FALLBACK_MESSAGE =
+            "I sent you an OMEMO encrypted message but your client doesn’t seem to support that."
+                    + " Find more information on https://conversations.im/omemo";
+    private static final String PGP_FALLBACK_MESSAGE =
+            "I sent you a PGP encrypted message but your client doesn’t seem to support that.";
 
     public MessageGenerator(XmppConnectionService service) {
         super(service);
     }
 
-    private im.conversations.android.xmpp.model.stanza.Message preparePacket(Message message) {
+    private im.conversations.android.xmpp.model.stanza.Message preparePacket(
+            final Message message) {
         Conversation conversation = (Conversation) message.getConversation();
         Account account = conversation.getAccount();
-        im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+        im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         final boolean isWithSelf = conversation.getContact().isSelf();
         if (conversation.getMode() == Conversation.MODE_SINGLE) {
             packet.setTo(message.getCounterpart());
@@ -60,8 +65,10 @@ public class MessageGenerator extends AbstractGenerator {
         }
         packet.setFrom(account.getJid());
         packet.setId(message.getUuid());
-        if (conversation.getMode() == Conversational.MODE_SINGLE || message.isPrivateMessage() || !conversation.getMucOptions().stableId()) {
-            packet.addChild("origin-id", Namespace.STANZA_IDS).setAttribute("id", message.getUuid());
+        if (conversation.getMode() == Conversational.MODE_MULTI
+                && !message.isPrivateMessage()
+                && !conversation.getMucOptions().stableId()) {
+            packet.addExtension(new OriginId(message.getUuid()));
         }
         if (message.edited()) {
             packet.addExtension(new Replace(message.getEditedIdWireFormat()));
@@ -69,16 +76,18 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public void addDelay(im.conversations.android.xmpp.model.stanza.Message packet, long timestamp) {
-        final SimpleDateFormat mDateFormat = new SimpleDateFormat(
-                "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
+    public void addDelay(
+            im.conversations.android.xmpp.model.stanza.Message packet, long timestamp) {
+        final SimpleDateFormat mDateFormat =
+                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
         mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
         Element delay = packet.addChild("delay", "urn:xmpp:delay");
         Date date = new Date(timestamp);
         delay.setAttribute("stamp", mDateFormat.format(date));
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message generateAxolotlChat(Message message, XmppAxolotlMessage axolotlMessage) {
+    public im.conversations.android.xmpp.model.stanza.Message generateAxolotlChat(
+            Message message, XmppAxolotlMessage axolotlMessage) {
         im.conversations.android.xmpp.model.stanza.Message packet = preparePacket(message);
         if (axolotlMessage == null) {
             return null;
@@ -92,8 +101,10 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message generateKeyTransportMessage(Jid to, XmppAxolotlMessage axolotlMessage) {
-        im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+    public im.conversations.android.xmpp.model.stanza.Message generateKeyTransportMessage(
+            Jid to, XmppAxolotlMessage axolotlMessage) {
+        im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
         packet.setTo(to);
         packet.setAxolotlMessage(axolotlMessage.toElement());
@@ -137,23 +148,32 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message generateChatState(Conversation conversation) {
+    public im.conversations.android.xmpp.model.stanza.Message generateChatState(
+            Conversation conversation) {
         final Account account = conversation.getAccount();
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(conversation.getMode() == Conversation.MODE_MULTI ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                conversation.getMode() == Conversation.MODE_MULTI
+                        ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT
+                        : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
         packet.setTo(conversation.getJid().asBareJid());
         packet.setFrom(account.getJid());
         packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
         packet.addChild("no-store", "urn:xmpp:hints");
-        packet.addChild("no-storage", "urn:xmpp:hints"); //wrong! don't copy this. Its *store*
+        packet.addChild("no-storage", "urn:xmpp:hints"); // wrong! don't copy this. Its *store*
         return packet;
     }
 
     public im.conversations.android.xmpp.model.stanza.Message confirm(final Message message) {
         final boolean groupChat = message.getConversation().getMode() == Conversational.MODE_MULTI;
         final Jid to = message.getCounterpart();
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(groupChat ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                groupChat
+                        ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT
+                        : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
         packet.setTo(groupChat ? to.asBareJid() : to);
         final Element displayed = packet.addChild("displayed", "urn:xmpp:chat-markers:0");
         if (groupChat) {
@@ -171,23 +191,32 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message reaction(final Conversational conversation, final String reactingTo, final Collection<String> ourReactions) {
+    public im.conversations.android.xmpp.model.stanza.Message reaction(
+            final Conversational conversation,
+            final String reactingTo,
+            final Collection<String> ourReactions) {
         final boolean groupChat = conversation.getMode() == Conversational.MODE_MULTI;
         final Jid to = conversation.getJid().asBareJid();
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(groupChat ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                groupChat
+                        ? im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT
+                        : im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
         packet.setTo(to);
         final var reactions = packet.addExtension(new Reactions());
         reactions.setId(reactingTo);
-        for(final String ourReaction : ourReactions) {
+        for (final String ourReaction : ourReactions) {
             reactions.addExtension(new Reaction(ourReaction));
         }
         packet.addChild("store", "urn:xmpp:hints");
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message conferenceSubject(Conversation conversation, String subject) {
-        im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+    public im.conversations.android.xmpp.model.stanza.Message conferenceSubject(
+            Conversation conversation, String subject) {
+        im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.GROUPCHAT);
         packet.setTo(conversation.getJid().asBareJid());
         packet.addChild("subject").setContent(subject);
@@ -195,8 +224,10 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message directInvite(final Conversation conversation, final Jid contact) {
-        im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+    public im.conversations.android.xmpp.model.stanza.Message directInvite(
+            final Conversation conversation, final Jid contact) {
+        im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.NORMAL);
         packet.setTo(contact);
         packet.setFrom(conversation.getAccount().getJid());
@@ -213,7 +244,8 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message invite(final Conversation conversation, final Jid contact) {
+    public im.conversations.android.xmpp.model.stanza.Message invite(
+            final Conversation conversation, final Jid contact) {
         final var packet = new im.conversations.android.xmpp.model.stanza.Message();
         packet.setTo(conversation.getJid().asBareJid());
         packet.setFrom(conversation.getAccount().getJid());
@@ -226,9 +258,13 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message received(Account account, final Jid from, final String id, ArrayList<String> namespaces, im.conversations.android.xmpp.model.stanza.Message.Type type) {
-        final var receivedPacket =
-                new im.conversations.android.xmpp.model.stanza.Message();
+    public im.conversations.android.xmpp.model.stanza.Message received(
+            Account account,
+            final Jid from,
+            final String id,
+            ArrayList<String> namespaces,
+            im.conversations.android.xmpp.model.stanza.Message.Type type) {
+        final var receivedPacket = new im.conversations.android.xmpp.model.stanza.Message();
         receivedPacket.setType(type);
         receivedPacket.setTo(from);
         receivedPacket.setFrom(account.getJid());
@@ -239,8 +275,10 @@ public class MessageGenerator extends AbstractGenerator {
         return receivedPacket;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message received(Account account, Jid to, String id) {
-        im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+    public im.conversations.android.xmpp.model.stanza.Message received(
+            Account account, Jid to, String id) {
+        im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         packet.setFrom(account.getJid());
         packet.setTo(to);
         packet.addChild("received", "urn:xmpp:receipts").setAttribute("id", id);
@@ -250,7 +288,8 @@ public class MessageGenerator extends AbstractGenerator {
 
     public im.conversations.android.xmpp.model.stanza.Message sessionFinish(
             final Jid with, final String sessionId, final Reason reason) {
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
         packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.CHAT);
         packet.setTo(with);
         final Element finish = packet.addChild("finish", Namespace.JINGLE_MESSAGE);
@@ -261,24 +300,33 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message sessionProposal(final JingleConnectionManager.RtpSessionProposal proposal) {
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.CHAT); //we want to carbon copy those
+    public im.conversations.android.xmpp.model.stanza.Message sessionProposal(
+            final JingleConnectionManager.RtpSessionProposal proposal) {
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                im.conversations.android.xmpp.model.stanza.Message.Type
+                        .CHAT); // we want to carbon copy those
         packet.setTo(proposal.with);
         packet.setId(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX + proposal.sessionId);
         final Element propose = packet.addChild("propose", Namespace.JINGLE_MESSAGE);
         propose.setAttribute("id", proposal.sessionId);
         for (final Media media : proposal.media) {
-            propose.addChild("description", Namespace.JINGLE_APPS_RTP).setAttribute("media", media.toString());
+            propose.addChild("description", Namespace.JINGLE_APPS_RTP)
+                    .setAttribute("media", media.toString());
         }
         packet.addChild("request", "urn:xmpp:receipts");
         packet.addChild("store", "urn:xmpp:hints");
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message sessionRetract(final JingleConnectionManager.RtpSessionProposal proposal) {
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.CHAT); //we want to carbon copy those
+    public im.conversations.android.xmpp.model.stanza.Message sessionRetract(
+            final JingleConnectionManager.RtpSessionProposal proposal) {
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                im.conversations.android.xmpp.model.stanza.Message.Type
+                        .CHAT); // we want to carbon copy those
         packet.setTo(proposal.with);
         final Element propose = packet.addChild("retract", Namespace.JINGLE_MESSAGE);
         propose.setAttribute("id", proposal.sessionId);
@@ -287,9 +335,13 @@ public class MessageGenerator extends AbstractGenerator {
         return packet;
     }
 
-    public im.conversations.android.xmpp.model.stanza.Message sessionReject(final Jid with, final String sessionId) {
-        final im.conversations.android.xmpp.model.stanza.Message packet = new im.conversations.android.xmpp.model.stanza.Message();
-        packet.setType(im.conversations.android.xmpp.model.stanza.Message.Type.CHAT); //we want to carbon copy those
+    public im.conversations.android.xmpp.model.stanza.Message sessionReject(
+            final Jid with, final String sessionId) {
+        final im.conversations.android.xmpp.model.stanza.Message packet =
+                new im.conversations.android.xmpp.model.stanza.Message();
+        packet.setType(
+                im.conversations.android.xmpp.model.stanza.Message.Type
+                        .CHAT); // we want to carbon copy those
         packet.setTo(with);
         final Element propose = packet.addChild("reject", Namespace.JINGLE_MESSAGE);
         propose.setAttribute("id", sessionId);

src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java 🔗

@@ -1,5 +1,6 @@
 package im.conversations.android.xmpp.model.unique;
 
+import com.google.common.base.Strings;
 import im.conversations.android.annotation.XmlElement;
 import im.conversations.android.xmpp.model.Extension;
 
@@ -9,4 +10,13 @@ public class OriginId extends Extension {
     public OriginId() {
         super(OriginId.class);
     }
+
+    public OriginId(final String id) {
+        this();
+        this.setAttribute("id", id);
+    }
+
+    public String getId() {
+        return Strings.emptyToNull(this.getAttribute("id"));
+    }
 }