I have an EditText in my view. I am using HtmlCompat.fromHtml()
to show the contents of an email in this EditText so it can be viewed and edited. If the html contains any JavaScript then it is being rendered in the resulting Spanned.
If I have the following (example) code:
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));
then the EditText shows the contents of <script type=\\"text/javascript\\">alert(\\"This should not appear in the EditText\\");</script>
I would have expected it to be removed/hidden. But I get:
Is there any way to stop this or is there some other way to have html from an email rendered in an EditText for editing? I know that Gmail can do it on Android, but I can't see how it was done?
<script>whatever</script>
is being stripped leaving the "whatever" in place. This is the default behavior of HtmlCompat.fromHtml() for tags it does not recognize. You will need to strip the problem tags and the associated text from the string before calling HtmlCompat.fromHtml(). You could do this with a straight string match or with a regular expression.
For Java:
String newString = mHtmlString.replaceAll("(?is)<script.*?</script>","")
For Kotlin:
val newString = mHtmlString.replace(Regex("(?is)<script.*?</script>"), "")
A second way is to use the tag handler that you can specify in the call to 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)
}
}
}
This second method simply deletes the contents of the script tag from the output.
In case anyone is interested, the java version of @Cheticamp's answer that I came up with was:
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());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.