diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index af4349350a7ca0b437f33c42f1e24feb8effa126..42975cb8f87d393cafe795141432162fedad90a9 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/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 ourReactions) { + public im.conversations.android.xmpp.model.stanza.Message reaction( + final Conversational conversation, + final String reactingTo, + final Collection 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 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 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); diff --git a/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java b/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java index 31a93962104ef834cae83978ce89d65946fb61b8..ce2a07a02e6018aaeb643f3c1891846c921c495d 100644 --- a/src/main/java/im/conversations/android/xmpp/model/unique/OriginId.java +++ b/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")); + } }