diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java index dadfa1d44..c7f1430db 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java @@ -1,7 +1,6 @@ package org.thoughtcrime.securesms.linkpreview; import android.annotation.SuppressLint; -import android.text.Html; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.URLSpan; @@ -10,6 +9,7 @@ import android.text.util.Linkify; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.core.text.HtmlCompat; import androidx.core.text.util.LinkifyCompat; import com.annimon.stream.Collectors; @@ -100,11 +100,6 @@ public final class LinkPreviewUtil { } public static @NonNull OpenGraph parseOpenGraphFields(@Nullable String html) { - return parseOpenGraphFields(html, text -> Html.fromHtml(text).toString()); - } - - @VisibleForTesting - static @NonNull OpenGraph parseOpenGraphFields(@Nullable String html, @NonNull HtmlDecoder htmlDecoder) { if (html == null) { return new OpenGraph(Collections.emptyMap(), null, null); } @@ -119,7 +114,7 @@ public final class LinkPreviewUtil { if (property != null) { Matcher contentMatcher = OPEN_GRAPH_CONTENT_PATTERN.matcher(tag); if (contentMatcher.find() && contentMatcher.groupCount() > 0) { - String content = htmlDecoder.fromEncoded(contentMatcher.group(1)); + String content = fromDoubleEncoded(contentMatcher.group(1)); openGraphTags.put(property.toLowerCase(), content); } } @@ -134,7 +129,7 @@ public final class LinkPreviewUtil { if (property != null) { Matcher contentMatcher = OPEN_GRAPH_CONTENT_PATTERN.matcher(tag); if (contentMatcher.find() && contentMatcher.groupCount() > 0) { - String content = htmlDecoder.fromEncoded(contentMatcher.group(1)); + String content = fromDoubleEncoded(contentMatcher.group(1)); openGraphTags.put(property.toLowerCase(), content); } } @@ -145,7 +140,7 @@ public final class LinkPreviewUtil { Matcher titleMatcher = TITLE_PATTERN.matcher(html); if (titleMatcher.find() && titleMatcher.groupCount() > 0) { - htmlTitle = htmlDecoder.fromEncoded(titleMatcher.group(1)); + htmlTitle = fromDoubleEncoded(titleMatcher.group(1)); } Matcher faviconMatcher = FAVICON_PATTERN.matcher(html); @@ -169,6 +164,9 @@ public final class LinkPreviewUtil { } } + private static @NonNull String fromDoubleEncoded(@NonNull String html) { + return HtmlCompat.fromHtml(HtmlCompat.fromHtml(html, 0).toString(), 0).toString(); + } public static final class OpenGraph { @@ -216,10 +214,6 @@ public final class LinkPreviewUtil { } } - public interface HtmlDecoder { - @NonNull String fromEncoded(@NonNull String html); - } - public static class Links { static final Links EMPTY = new Links(Collections.emptyList()); diff --git a/app/src/test/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtilTest_parseOpenGraphFields.java b/app/src/test/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtilTest_parseOpenGraphFields.java index e8171d520..17914b714 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtilTest_parseOpenGraphFields.java +++ b/app/src/test/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtilTest_parseOpenGraphFields.java @@ -1,8 +1,12 @@ package org.thoughtcrime.securesms.linkpreview; +import android.app.Application; + import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.robolectric.ParameterizedRobolectricTestRunner; +import org.robolectric.annotation.Config; import org.whispersystems.libsignal.util.guava.Optional; import java.util.Arrays; @@ -10,7 +14,8 @@ import java.util.Collection; import static junit.framework.TestCase.assertEquals; -@RunWith(Parameterized.class) +@RunWith(ParameterizedRobolectricTestRunner.class) +@Config(manifest = Config.NONE, application = Application.class) public class LinkPreviewUtilTest_parseOpenGraphFields { private final String html; @@ -19,7 +24,7 @@ public class LinkPreviewUtilTest_parseOpenGraphFields { private final long date; private final String imageUrl; - @Parameterized.Parameters + @ParameterizedRobolectricTestRunner.Parameters public static Collection data() { return Arrays.asList(new Object[][]{ // Normal @@ -150,6 +155,16 @@ public class LinkPreviewUtilTest_parseOpenGraphFields { 694051200000L, null}, + // Double encoded HTML + { "\n" + + "" + + "" + + "", + "Daily Bugle", + "A newspaper's", + 694051200000L, + "https://images.com/my-image.jpg"}, + }); } @@ -163,7 +178,7 @@ public class LinkPreviewUtilTest_parseOpenGraphFields { @Test public void parseOpenGraphFields() { - LinkPreviewUtil.OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(html, html -> html); + LinkPreviewUtil.OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(html); assertEquals(Optional.fromNullable(title), openGraph.getTitle()); assertEquals(Optional.fromNullable(description), openGraph.getDescription()); assertEquals(date, openGraph.getDate());