簡體   English   中英

Android HtmlCompat.fromHtml() 創建 Spanned 后如何停止 EditText 顯示 javascript

[英]How to stop EditText showing javascript after Android HtmlCompat.fromHtml() creates a Spanned

我有一個 EditText 在我看來。 我正在使用HtmlCompat.fromHtml()在此 EditText 中顯示電子郵件的內容,以便可以查看和編輯它。 如果 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>我希望它被刪除/隱藏。 但我得到:

顯示問題的屏幕截圖

有什么辦法可以阻止這種情況,還是有其他方法可以讓 EditText 中呈現的電子郵件中的 html 進行編輯? 我知道 Gmail 可以在 Android 上完成,但我看不到它是如何完成的?

<script>whatever</script>被剝離,留下“whatever”。 這是 HtmlCompat.fromHtml() 對於它無法識別的標簽的默認行為。 在調用 HtmlCompat.fromHtml() 之前,您需要從字符串中去除問題標簽和相關文本。 您可以使用直接字符串匹配或正則表達式來執行此操作。

對於 Java:

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

對於科特林:

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

第二種方法是使用您可以在調用fromHtml(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)
        }
    }
}

第二種方法只是從輸出中刪除腳本標記的內容。

如果有人感興趣,我想出的@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());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM