diff --git a/src/main/java/eu/siacs/conversations/entities/Message.java b/src/main/java/eu/siacs/conversations/entities/Message.java index 399dc61734db6647bafc08ea726ebfec23fbddce..5c6f263af9d7b20597dff87fe8cf048029be44e0 100644 --- a/src/main/java/eu/siacs/conversations/entities/Message.java +++ b/src/main/java/eu/siacs/conversations/entities/Message.java @@ -9,6 +9,7 @@ import android.text.Html; import android.text.SpannableStringBuilder; import android.util.Base64; import android.util.Log; +import android.util.Pair; import com.cheogram.android.BobTransfer; import com.cheogram.android.GetThumbnailForCid; @@ -409,10 +410,29 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable } public String getBody() { - if (getOob() != null) { - return body.replace(getOob().toString(), ""); + StringBuilder body = new StringBuilder(this.body); + + List fallbacks = getFallbacks(); + List> spans = new ArrayList<>(); + for (Element fallback : fallbacks) { + for (Element span : fallback.getChildren()) { + if (!span.getName().equals("body") && !span.getNamespace().equals("urn:xmpp:fallback:0")) continue; + if (span.getAttribute("start") == null || span.getAttribute("end") == null) return ""; + spans.add(new Pair(parseInt(span.getAttribute("start")), parseInt(span.getAttribute("end")))); + } + } + // Do them in reverse order so that span deletions don't affect the indexes of other spans + spans.sort((x, y) -> y.first.compareTo(x.first)); + try { + for (Pair span : spans) { + body.delete(span.first, span.second); + } + } catch (final StringIndexOutOfBoundsException e) { spans.clear(); } + + if (spans.isEmpty() && getOob() != null) { + return body.toString().replace(getOob().toString(), ""); } else { - return body; + return body.toString(); } } @@ -953,6 +973,24 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable return new ArrayList<>(this.payloads); } + public List getFallbacks() { + List fallbacks = new ArrayList<>(); + + if (this.payloads == null) return fallbacks; + + for (Element el : this.payloads) { + if (el.getName().equals("fallback") && el.getNamespace().equals("urn:xmpp:fallback:0")) { + final String fallbackFor = el.getAttribute("for"); + if (fallbackFor == null) continue; + if (fallbackFor.equals("http://jabber.org/protocol/address") || fallbackFor.equals(Namespace.OOB)) { + fallbacks.add(el); + } + } + } + + return fallbacks; + } + public Element getHtml() { if (this.payloads == null) return null; diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 90a312204094c58cc2bda1baf3e27ed4aa7f25bf..b1d57fef74cc7b7933866fe646cfd2ddbef7e040 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -107,6 +107,8 @@ public class MessageGenerator extends AbstractGenerator { final Message.FileParams fileParams = message.getFileParams(); content = fileParams.url; packet.addChild("x", Namespace.OOB).addChild("url").setContent(content); + packet.addChild("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB) + .addChild("body", "urn:xmpp:fallback:0"); } else { content = message.getBody(); } @@ -121,6 +123,8 @@ public class MessageGenerator extends AbstractGenerator { final String url = fileParams.url; packet.setBody(url); packet.addChild("x", Namespace.OOB).addChild("url").setContent(url); + packet.addChild("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB) + .addChild("body", "urn:xmpp:fallback:0"); } else { if (Config.supportUnencrypted()) { packet.setBody(PGP_FALLBACK_MESSAGE); diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 655ddcbf8ff6dc54ee1fc6853f29d88217e08a46..f0b3d83e27289f9bac282e4d9f723fba2c4a211d 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -633,7 +633,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } message.markable = packet.hasChild("markable", "urn:xmpp:chat-markers:0"); for (Element el : packet.getChildren()) { - if (el.getName().equals("query") && el.getNamespace().equals("http://jabber.org/protocol/disco#items") && el.getAttribute("node").equals("http://jabber.org/protocol/commands")) { + if ((el.getName().equals("query") && el.getNamespace().equals("http://jabber.org/protocol/disco#items") && el.getAttribute("node").equals("http://jabber.org/protocol/commands")) || + (el.getName().equals("fallback") && el.getNamespace().equals("urn:xmpp:fallback:0"))) { message.addPayload(el); } if (el.getName().equals("thread") && (el.getNamespace() == null || el.getNamespace().equals("jabber:client"))) {