From c0b3a3ff0c32c8025174ebb92fbcf4a7fc67f497 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 15 Feb 2016 23:15:04 +0100 Subject: basic support for XEP-0308: Last Message Correction. fixes #864 --- .../siacs/conversations/parser/MessageParser.java | 61 +++++++++++++++++----- 1 file changed, 47 insertions(+), 14 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 3bf48831..18edfdeb 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -297,6 +297,8 @@ public class MessageParser extends AbstractParser implements final String body = packet.getBody(); final Element mucUserElement = packet.findChild("x", "http://jabber.org/protocol/muc#user"); final String pgpEncrypted = packet.findChildContent("x", "jabber:x:encrypted"); + final Element replaceElement = packet.findChild("replace","urn:xmpp:message-correct:0"); + final String replacementId = replaceElement == null ? null : replaceElement.getAttribute("id"); final Element axolotlEncrypted = packet.findChild(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); int status; final Jid counterpart; @@ -390,6 +392,33 @@ public class MessageParser extends AbstractParser implements } else { updateLastseen(timestamp, account, packet.getFrom(), true); } + + if (replacementId != null) { + Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, counterpart); + if (replacedMessage != null) { + final boolean fingerprintsMatch = replacedMessage.getAxolotlFingerprint() == null + || replacedMessage.getAxolotlFingerprint().equals(message.getAxolotlFingerprint()); + final boolean trueCountersMatch = replacedMessage.getTrueCounterpart() != null + && replacedMessage.getTrueCounterpart().equals(message.getTrueCounterpart()); + if (fingerprintsMatch && (trueCountersMatch || conversation.getMode() == Conversation.MODE_SINGLE)) { + Log.d(Config.LOGTAG, "replaced message '" + replacedMessage.getBody() + "' with '" + message.getBody() + "'"); + replacedMessage.setBody(message.getBody()); + replacedMessage.setEdited(replacedMessage.getRemoteMsgId()); + replacedMessage.setRemoteMsgId(remoteMsgId); + if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) { + replacedMessage.markUnread(); + } + mXmppConnectionService.updateMessage(replacedMessage); + if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { + sendMessageReceipts(account, packet); + } + return; + } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": received message correction but verification didn't check out"); + } + } + } + boolean checkForDuplicates = query != null || (isTypeGroupChat && packet.hasChild("delay","urn:xmpp:delay")) || message.getType() == Message.TYPE_PRIVATE; @@ -420,20 +449,7 @@ public class MessageParser extends AbstractParser implements } if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { - ArrayList receiptsNamespaces = new ArrayList<>(); - if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) { - receiptsNamespaces.add("urn:xmpp:chat-markers:0"); - } - if (packet.hasChild("request", "urn:xmpp:receipts")) { - receiptsNamespaces.add("urn:xmpp:receipts"); - } - if (receiptsNamespaces.size() > 0) { - MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, - packet, - receiptsNamespaces, - packet.getType()); - mXmppConnectionService.sendMessagePacket(account, receipt); - } + sendMessageReceipts(account, packet); } if (message.getStatus() == Message.STATUS_RECEIVED @@ -524,4 +540,21 @@ public class MessageParser extends AbstractParser implements contact.setPresenceName(nick); } } + + private void sendMessageReceipts(Account account, MessagePacket packet) { + ArrayList receiptsNamespaces = new ArrayList<>(); + if (packet.hasChild("markable", "urn:xmpp:chat-markers:0")) { + receiptsNamespaces.add("urn:xmpp:chat-markers:0"); + } + if (packet.hasChild("request", "urn:xmpp:receipts")) { + receiptsNamespaces.add("urn:xmpp:receipts"); + } + if (receiptsNamespaces.size() > 0) { + MessagePacket receipt = mXmppConnectionService.getMessageGenerator().received(account, + packet, + receiptsNamespaces, + packet.getType()); + mXmppConnectionService.sendMessagePacket(account, receipt); + } + } } -- cgit v1.2.3 From a9b957e8a2b9cb7729ed0d2cc8b5efa1bee50c79 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 16 Feb 2016 09:57:59 +0100 Subject: added setting to opt-out of message correction. renamed preferences and options to settings --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 18edfdeb..620039a1 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -393,7 +393,7 @@ public class MessageParser extends AbstractParser implements updateLastseen(timestamp, account, packet.getFrom(), true); } - if (replacementId != null) { + if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) { Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, counterpart); if (replacedMessage != null) { final boolean fingerprintsMatch = replacedMessage.getAxolotlFingerprint() == null -- cgit v1.2.3 From c2fbdbde830fb3f15e4bdd1c1fb904e69b68927e Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 16 Feb 2016 14:22:47 +0100 Subject: log reason why otr message won't be parsed --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 620039a1..69b0e828 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -312,7 +312,7 @@ public class MessageParser extends AbstractParser implements } boolean isTypeGroupChat = packet.getType() == MessagePacket.TYPE_GROUPCHAT; - boolean isProperlyAddressed = (to != null ) && (!to.isBareJid() || account.countPresences() == 1); + boolean isProperlyAddressed = (to != null ) && (!to.isBareJid() || account.countPresences() <= 1); boolean isMucStatusMessage = from.isBareJid() && mucUserElement != null && mucUserElement.hasChild("status"); if (packet.fromAccount(account)) { status = Message.STATUS_SEND; @@ -357,6 +357,7 @@ public class MessageParser extends AbstractParser implements return; } } else { + Log.d(Config.LOGTAG,account.getJid().toBareJid()+": ignoring OTR message from "+from+" isForwarded="+Boolean.toString(isForwarded)+", isProperlyAddressed="+Boolean.valueOf(isProperlyAddressed)); message = new Message(conversation, body, Message.ENCRYPTION_NONE, status); } } else if (pgpEncrypted != null) { -- cgit v1.2.3 From 59978e157ccbf4717a15238ddb0b0d0d422d7e3f Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 17 Feb 2016 16:51:36 +0100 Subject: only offer message correction for the very last message --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 69b0e828..c4b63d61 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -336,6 +336,7 @@ public class MessageParser extends AbstractParser implements if (isTypeGroupChat) { if (counterpart.getResourcepart().equals(conversation.getMucOptions().getActualNick())) { status = Message.STATUS_SEND_RECEIVED; + isCarbon = true; //not really carbon but received from another resource if (mXmppConnectionService.markMessage(conversation, remoteMsgId, status)) { return; } else if (remoteMsgId == null || Config.IGNORE_ID_REWRITE_IN_MUC) { @@ -395,7 +396,10 @@ public class MessageParser extends AbstractParser implements } if (replacementId != null && mXmppConnectionService.allowMessageCorrection()) { - Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, counterpart); + Message replacedMessage = conversation.findMessageWithRemoteIdAndCounterpart(replacementId, + counterpart, + message.getStatus() == Message.STATUS_RECEIVED, + message.isCarbon()); if (replacedMessage != null) { final boolean fingerprintsMatch = replacedMessage.getAxolotlFingerprint() == null || replacedMessage.getAxolotlFingerprint().equals(message.getAxolotlFingerprint()); -- cgit v1.2.3 From e6f8b7d9fa30e4e231a07cdbbb225e462893eb3d Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Fri, 19 Feb 2016 21:02:33 +0100 Subject: decrypt pgp message corrections --- .../eu/siacs/conversations/parser/MessageParser.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index c4b63d61..247fd72b 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -117,13 +117,6 @@ public class MessageParser extends AbstractParser implements return finishedMessage; } - private Message parsePGPChat(final Conversation conversation, String pgpEncrypted, int status) { - final Message message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status); - PgpDecryptionService pgpDecryptionService = conversation.getAccount().getPgpDecryptionService(); - pgpDecryptionService.add(message); - return message; - } - private class Invite { Jid jid; String password; @@ -362,7 +355,7 @@ public class MessageParser extends AbstractParser implements message = new Message(conversation, body, Message.ENCRYPTION_NONE, status); } } else if (pgpEncrypted != null) { - message = parsePGPChat(conversation, pgpEncrypted, status); + message = new Message(conversation, pgpEncrypted, Message.ENCRYPTION_PGP, status); } else if (axolotlEncrypted != null) { message = parseAxolotlChat(axolotlEncrypted, from, remoteMsgId, conversation, status); if (message == null) { @@ -410,6 +403,7 @@ public class MessageParser extends AbstractParser implements replacedMessage.setBody(message.getBody()); replacedMessage.setEdited(replacedMessage.getRemoteMsgId()); replacedMessage.setRemoteMsgId(remoteMsgId); + replacedMessage.setEncryption(message.getEncryption()); if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) { replacedMessage.markUnread(); } @@ -417,6 +411,9 @@ public class MessageParser extends AbstractParser implements if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { sendMessageReceipts(account, packet); } + if (replacedMessage.getEncryption() == Message.ENCRYPTION_PGP) { + conversation.getAccount().getPgpDecryptionService().add(replacedMessage); + } return; } else { Log.d(Config.LOGTAG,account.getJid().toBareJid()+": received message correction but verification didn't check out"); @@ -438,6 +435,10 @@ public class MessageParser extends AbstractParser implements conversation.add(message); } + if (message.getEncryption() == Message.ENCRYPTION_PGP) { + conversation.getAccount().getPgpDecryptionService().add(message); + } + if (query == null || query.getWith() == null) { //either no mam or catchup if (status == Message.STATUS_SEND || status == Message.STATUS_SEND_RECEIVED) { mXmppConnectionService.markRead(conversation); -- cgit v1.2.3 From 3bde4dbedb80a8e1de89c09f58d842d7382598e8 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 20 Feb 2016 00:01:39 +0100 Subject: change uuid when replacing messages --- src/main/java/eu/siacs/conversations/parser/MessageParser.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/main/java/eu/siacs/conversations/parser/MessageParser.java') diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 247fd72b..f01e7ce1 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -9,6 +9,7 @@ import net.java.otr4j.session.SessionStatus; import java.util.ArrayList; import java.util.Set; +import java.util.UUID; import eu.siacs.conversations.Config; import eu.siacs.conversations.crypto.axolotl.AxolotlService; @@ -400,6 +401,8 @@ public class MessageParser extends AbstractParser implements && replacedMessage.getTrueCounterpart().equals(message.getTrueCounterpart()); if (fingerprintsMatch && (trueCountersMatch || conversation.getMode() == Conversation.MODE_SINGLE)) { Log.d(Config.LOGTAG, "replaced message '" + replacedMessage.getBody() + "' with '" + message.getBody() + "'"); + final String uuid = replacedMessage.getUuid(); + replacedMessage.setUuid(UUID.randomUUID().toString()); replacedMessage.setBody(message.getBody()); replacedMessage.setEdited(replacedMessage.getRemoteMsgId()); replacedMessage.setRemoteMsgId(remoteMsgId); @@ -407,7 +410,7 @@ public class MessageParser extends AbstractParser implements if (replacedMessage.getStatus() == Message.STATUS_RECEIVED) { replacedMessage.markUnread(); } - mXmppConnectionService.updateMessage(replacedMessage); + mXmppConnectionService.updateMessage(replacedMessage, uuid); if (mXmppConnectionService.confirmMessages() && remoteMsgId != null && !isForwarded && !isTypeGroupChat) { sendMessageReceipts(account, packet); } -- cgit v1.2.3