Как остановить EditText, показывая javascript после Android HtmlCompat.from Html () создает Spanned - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть EditText на мой взгляд. Я использую HtmlCompat.fromHtml(), чтобы показать содержимое электронного письма в этом тексте редактирования, чтобы его можно было просматривать и редактировать. Если html содержит какой-либо JavaScript, то он воспроизводится в полученном Spanned.

Если у меня есть следующий (пример) код:

String htmlString = "<html>\n" +
    "\n" +
    "<head>\n" +
    "    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n" +
    "    <script type=\"text/javascript\">\n" +
    "        alert(\"This should not appear in the EditText\");\n" +
    "    </script>\n" +
    "</head>\n" +
    "\n" +
    "<body style=\"margin: 0;padding: 0;box-sizing: border-box;-webkit-font-smoothing: antialiased;-webkit-text-size-adjust: none;width: 100% !important;height: 100% !important;line-height: 1.6;margin-top: 0 !important;margin-left: 0 !important;margin-right: 0 !important\" class=\"\">\n" +
    "    <div dir=\"auto\">Technician booked for tomorrow morning\n" +
    "        <br>\n" +
    "        <br>\n" +
    "    </div>\n" +
    "    <div dir=\"auto\">\n" +
    "        <a href=\"http://www.bluemail.me/r?b=15726\"></a>\n" +
    "    </div>\n" +
    "</body>\n" +
    "\n" +
    "</html>";

emailTextView.setText(HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT));

, тогда EditText показывает содержимое <script type=\"text/javascript\">alert(\"This should not appear in the EditText\");</script> Я бы ожидал, что оно будет удалено / скрыто. Но я получаю:

screen shot showing the issue

Есть ли способ остановить это или есть какой-то другой способ получить html из электронного письма, представленного в EditText для редактирования? Я знаю, что Gmail может сделать это на Android, но я не вижу, как это было сделано?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

На случай, если кому-то будет интересно, ответ @ Cheticamp java, который я придумал, был:

Html.ImageGetter imageGetter = new PicassoImageGetter(textView);
textView.setText(HtmlCompat.fromHtml(htmlString, HtmlCompat.FROM_HTML_MODE_COMPACT, imageGetter, new Html.TagHandler() {

    @Override
    public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {
        if (!tag.equals("script")) {
            return;
        }
        if (opening) {
            output.setSpan(new DeleteScriptTagContent(), output.length(), output.length(), Spannable.SPAN_MARK_POINT);
        } else {
            Object[] spans = output.getSpans(0, output.length(), DeleteScriptTagContent.class);
            if (spans.length == 0) {
                return;
            }
            Object lastSpan = spans[spans.length - 1];
            int startIndex = output.getSpanStart(lastSpan);
            int endIndex = output.getSpanEnd(lastSpan);
            if (startIndex == -1 || endIndex == -1) {
                return;
            }
            output.delete(startIndex, endIndex);
        }
    }

    class DeleteScriptTagContent {
    }
}));
textView.setMovementMethod(LinkMovementMethod.getInstance());
0 голосов
/ 13 февраля 2020

<script>whatever</script> убирается, оставляя «что угодно» на месте. Это поведение по умолчанию HtmlCompat.from Html () для тегов, которые он не распознает. Перед вызовом HtmlCompat.from Html () вам нужно убрать теги проблемы и связанный текст из строки. Вы можете сделать это с помощью прямой строки или с помощью регулярного выражения.

Для Java:

String newString =  mHtmlString.replaceAll("(?is)<script.*?</script>","")

Для Kotlin:

val newString = mHtmlString.replace(Regex("(?is)<script.*?</script>"), "")

Второй способ использовать обработчик тега, который вы можете указать при вызове из Html (String, int, ImageGetter, TagHandler) .

override fun handleTag(
    opening: Boolean,
    tag: String,
    output: Editable,
    xmlReader: XMLReader?
) {
    class DeleteSpan

    if (!tag.equals("script", true)) {
        return
    }
    if (opening) {
        output.setSpan(DeleteSpan(), output.length, output.length, Spannable.SPAN_MARK_POINT)
    } else {
        val spans = output.getSpans(0, output.length, DeleteSpan::class.java)
        val lastSpan = spans[spans.size - 1]
        output.apply {
            delete(getSpanStart(lastSpan), getSpanEnd(lastSpan))
            removeSpan(lastSpan)
        }
    }
}

Этот второй метод просто удаляет содержимое тег сценария из вывода.

...