diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java index a838a75d5..e8fc39cdc 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java @@ -104,7 +104,42 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie return "http://" + removeTrailingBracket(url); } }; - private static final Linkify.MatchFilter WEBURL_MATCH_FILTER = (cs, start, end) -> start < 1 || (cs.charAt(start - 1) != '@' && cs.charAt(start - 1) != '.' && !cs.subSequence(Math.max(0, start - 3), start).equals("://")); + + private static String removeTrailingBracket(final String url) { + int numOpenBrackets = 0; + for (char c : url.toCharArray()) { + if (c == '(') { + ++numOpenBrackets; + } else if (c == ')') { + --numOpenBrackets; + } + } + if (numOpenBrackets != 0 && url.charAt(url.length() - 1) == ')') { + return url.substring(0, url.length() - 1); + } else { + return url; + } + } + + private static final Linkify.MatchFilter WEBURL_MATCH_FILTER = (cs, start, end) -> { + if (start > 0) { + if (cs.charAt(start - 1) == '@' || cs.charAt(start - 1) == '.' + || cs.subSequence(Math.max(0, start - 3), start).equals("://")) { + return false; + } + } + + if (end < cs.length()) { + // Reject strings that were probably matched only because they contain a dot followed by + // by some known TLD (see also comment for WORD_BOUNDARY in Patterns.java) + if (Character.isAlphabetic(cs.charAt(end-1)) && Character.isAlphabetic(cs.charAt(end))) { + return false; + } + } + + return true; + }; + private static final Linkify.MatchFilter XMPPURI_MATCH_FILTER = (s, start, end) -> { XmppUri uri = new XmppUri(s.subSequence(start, end).toString()); return uri.isJidValid(); @@ -127,21 +162,6 @@ public class MessageAdapter extends ArrayAdapter implements CopyTextVie updatePreferences(); } - private static String removeTrailingBracket(final String url) { - int numOpenBrackets = 0; - for (char c : url.toCharArray()) { - if (c == '(') { - ++numOpenBrackets; - } else if (c == ')') { - --numOpenBrackets; - } - } - if (numOpenBrackets != 0 && url.charAt(url.length() - 1) == ')') { - return url.substring(0, url.length() - 1); - } else { - return url; - } - } public static boolean cancelPotentialWork(Message message, ImageView imageView) { final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); diff --git a/src/main/java/eu/siacs/conversations/utils/Patterns.java b/src/main/java/eu/siacs/conversations/utils/Patterns.java index 6e9e85cd7..fae13aaea 100644 --- a/src/main/java/eu/siacs/conversations/utils/Patterns.java +++ b/src/main/java/eu/siacs/conversations/utils/Patterns.java @@ -353,7 +353,6 @@ public class Patterns { + "(?:" + PORT_NUMBER + ")?" + ")" + "(?:" + PATH_AND_QUERY + ")?" - + WORD_BOUNDARY + ")"; /** * Regular expression to match strings that start with a supported protocol. Rules for domain @@ -367,7 +366,6 @@ public class Patterns { + "(?:" + PORT_NUMBER + ")?" + ")" + "(?:" + PATH_AND_QUERY + ")?" - + WORD_BOUNDARY + ")"; /** * Regular expression pattern to match IRIs. If a string starts with http(s):// the expression