[英]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.