Don't show aesgcm urls to people

Stephen Paul Weber created

Change summary

src/main/java/eu/siacs/conversations/entities/Message.java   |  5 
src/main/java/eu/siacs/conversations/utils/MessageUtils.java | 27 ++++++
2 files changed, 31 insertions(+), 1 deletion(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Message.java 🔗

@@ -547,7 +547,10 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
         Pair<StringBuilder, Boolean> result = bodyMinusFallbacks("http://jabber.org/protocol/address", Namespace.OOB);
         StringBuilder body = result.first;
 
-        if (!result.second && getOob() != null) {
+        final String aesgcm = MessageUtils.aesgcmDownloadable(body.toString());
+        if (!result.second && aesgcm != null) {
+            return body.toString().replace(aesgcm, "");
+        } else if (!result.second && getOob() != null) {
             return body.toString().replace(getOob().toString(), "");
         } else if (!result.second && isGeoUri()) {
             return "";

src/main/java/eu/siacs/conversations/utils/MessageUtils.java 🔗

@@ -108,6 +108,33 @@ public class MessageUtils {
         return validAesGcm || validOob;
     }
 
+    public static String aesgcmDownloadable(final String body) {
+        final String[] lines = body.split("\n");
+        if (lines.length == 0) {
+            return null;
+        }
+        for (final String line : lines) {
+            if (line.contains("\\s+")) {
+                return null;
+            }
+        }
+        final URI uri;
+        try {
+            uri = new URI(lines[0]);
+        } catch (final URISyntaxException e) {
+            return null;
+        }
+        if (!URL.WELL_KNOWN_SCHEMES.contains(uri.getScheme())) {
+            return null;
+        }
+        final String ref = uri.getFragment();
+        final String protocol = uri.getScheme();
+        final boolean encrypted = ref != null && AesGcmURL.IV_KEY.matcher(ref).matches();
+        final boolean followedByDataUri = lines.length == 2 && lines[1].startsWith("data:");
+        final boolean validAesGcm = AesGcmURL.PROTOCOL_NAME.equalsIgnoreCase(protocol) && encrypted && (lines.length == 1 || followedByDataUri);
+        return validAesGcm ? lines[0] : null;
+    }
+
     public static String filterLtrRtl(String body) {
         return LTR_RTL.matcher(body).replaceFirst(EMPTY_STRING);
     }