Detailed changes
  
  
    
    @@ -507,18 +507,25 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
     }
 
     public String getQuoteableBody() {
+        if (this.body == null) return null;
+
+        StringBuilder body = bodyMinusFallbacks("http://jabber.org/protocol/address").first;
+        return body.toString();
+    }
+
+    public String getRawBody() {
         return this.body;
     }
 
-    public String getBody() {
+    private Pair<StringBuilder, Boolean> bodyMinusFallbacks(String... fallbackNames) {
         StringBuilder body = new StringBuilder(this.body);
 
-        List<Element> fallbacks = getFallbacks("http://jabber.org/protocol/address", Namespace.OOB);
+        List<Element> fallbacks = getFallbacks(fallbackNames);
         List<Pair<Integer, Integer>> 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 "";
+                if (span.getAttribute("start") == null || span.getAttribute("end") == null) return new Pair<>(new StringBuilder(""), true);
                 spans.add(new Pair(parseInt(span.getAttribute("start")), parseInt(span.getAttribute("end"))));
             }
         }
@@ -530,9 +537,16 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
             }
         } catch (final IndexOutOfBoundsException e) { spans.clear(); }
 
-        if (spans.isEmpty() && getOob() != null) {
+        return new Pair<>(body, !spans.isEmpty());
+    }
+
+    public String getBody() {
+        Pair<StringBuilder, Boolean> result = bodyMinusFallbacks("http://jabber.org/protocol/address", Namespace.OOB);
+        StringBuilder body = result.first;
+
+        if (!result.second && getOob() != null) {
             return body.toString().replace(getOob().toString(), "");
-        } else if (spans.isEmpty() && isGeoUri()) {
+        } else if (!result.second && isGeoUri()) {
             return "";
         } else {
             return body.toString();
  
  
  
    
    @@ -112,7 +112,7 @@ public class MessageGenerator extends AbstractGenerator {
                     packet.addChild("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB)
                         .addChild("body", "urn:xmpp:fallback:0");
                 } else {
-                    long start = message.getQuoteableBody().length();
+                    long start = message.getRawBody().codePointCount(0, message.getRawBody().length());
                     message.appendBody(fileParams.url);
                     packet.addChild("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB)
                         .addChild("body", "urn:xmpp:fallback:0")
@@ -123,7 +123,7 @@ public class MessageGenerator extends AbstractGenerator {
 
             packet.addChild("x", Namespace.OOB).addChild("url").setContent(fileParams.url);
         }
-        if (message.getQuoteableBody() != null) packet.setBody(message.getQuoteableBody());
+        if (message.getRawBody() != null) packet.setBody(message.getRawBody());
         return packet;
     }
 
  
  
  
    
    @@ -1849,7 +1849,7 @@ public class XmppConnectionService extends Service {
         }
 
         MessagePacket packet = null;
-        final boolean addToConversation = !message.edited() && message.getQuoteableBody() != null;
+        final boolean addToConversation = !message.edited() && message.getRawBody() != null;
         boolean saveInDb = addToConversation;
         message.setStatus(Message.STATUS_WAITING);
 
@@ -1893,11 +1893,11 @@ public class XmppConnectionService extends Service {
                                         }
                                         params.setName(HttpConnectionManager.extractFilenameFromResponse(response));
 
-                                        if (link.toString().equals(message.getQuoteableBody())) {
+                                        if (link.toString().equals(message.getRawBody())) {
                                             Element fallback = new Element("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB);
                                             fallback.addChild("body", "urn:xmpp:fallback:0");
                                             message.addPayload(fallback);
-                                        } else if (message.getQuoteableBody().indexOf(link.toString()) >= 0) {
+                                        } else if (message.getRawBody().indexOf(link.toString()) >= 0) {
                                             // Part of the real body, not just a fallback
                                             Element fallback = new Element("fallback", "urn:xmpp:fallback:0").setAttribute("for", Namespace.OOB);
                                             fallback.addChild("body", "urn:xmpp:fallback:0")
  
  
  
    
    @@ -1795,7 +1795,7 @@ public class ConversationFragment extends XmppFragment
                             final Message previousReaction = conversation.findMessageReactingTo(reactions.getAttribute("id"), null);
                             if (previousReaction != null) reactions = previousReaction.getReactions();
                             for (Element el : reactions.getChildren()) {
-                                if (message.getQuoteableBody().endsWith(el.getContent())) {
+                                if (message.getRawBody().endsWith(el.getContent())) {
                                     reactions.removeChild(el);
                                 }
                             }
  
  
  
    
    @@ -97,7 +97,7 @@ public class ShareUtil {
 		final int resId;
 		if (message.isGeoUri()) {
 			resId = R.string.location;
-			url = message.getQuoteableBody();
+			url = message.getRawBody();
 		} else if (message.hasFileOnRemoteHost()) {
 			resId = R.string.file_url;
 			url = message.getFileParams().url;
  
  
  
    
    @@ -72,7 +72,7 @@ public class GeoHelper {
 		final ArrayList<Intent> intents = new ArrayList<>();
 		final GeoPoint geoPoint;
 		try {
-			geoPoint = parseGeoPoint(message.getQuoteableBody());
+			geoPoint = parseGeoPoint(message.getRawBody());
 		} catch (IllegalArgumentException e) {
 			return intents;
 		}
@@ -113,7 +113,7 @@ public class GeoHelper {
 	}
 
 	public static void view(Context context, Message message) {
-		final GeoPoint geoPoint = parseGeoPoint(message.getQuoteableBody());
+		final GeoPoint geoPoint = parseGeoPoint(message.getRawBody());
 		final String label = getLabel(context, message);
 		context.startActivity(geoIntent(geoPoint,label));
 	}
@@ -126,7 +126,7 @@ public class GeoHelper {
 
 	public static boolean openInOsmAnd(Context context, Message message) {
 		try {
-			final GeoPoint geoPoint = parseGeoPoint(message.getQuoteableBody());
+			final GeoPoint geoPoint = parseGeoPoint(message.getRawBody());
 			final String label = getLabel(context, message);
 			return geoIntent(geoPoint, label).resolveActivity(context.getPackageManager()) != null;
 		} catch (IllegalArgumentException e) {