Просмотр исходного кода

清理书籍简介中的脚本和样式代码

5151561 3 месяцев назад
Родитель
Сommit
4a665910a5

+ 2 - 1
app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt

@@ -64,6 +64,7 @@ import io.legado.app.ui.main.MainIntent
 import io.legado.app.ui.widget.components.image.cover.buildCoverImageRequest
 import io.legado.app.utils.ArchiveUtils
 import io.legado.app.utils.GSON
+import io.legado.app.utils.HtmlFormatter
 import io.legado.app.utils.ImageSaveUtils
 import io.legado.app.utils.UrlUtil
 import io.legado.app.utils.fromJsonArray
@@ -1712,7 +1713,7 @@ class BookInfoViewModel(
             durChapterIndex = durChapterIndex,
             durChapterPos = durChapterPos,
             remark = remark,
-            displayIntro = getDisplayIntro(),
+            displayIntro = HtmlFormatter.formatDisplayText(getDisplayIntro()),
         )
     }
 

+ 2 - 1
app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt

@@ -60,6 +60,7 @@ import io.legado.app.ui.widget.components.icon.AppIcon
 import io.legado.app.ui.widget.components.image.cover.BookshelfCover
 import io.legado.app.ui.widget.components.image.cover.CoilBookCover
 import io.legado.app.ui.widget.components.text.AppText
+import io.legado.app.utils.HtmlFormatter
 import io.legado.app.utils.toTimeAgo
 import kotlinx.collections.immutable.ImmutableList
 
@@ -755,7 +756,7 @@ fun BookItem(
         columnContent = if (layoutMode == 0 && !isCompact && settings.showBookIntro) {
             {
                 val kindList = bookUi.displayTags
-                val intro = book.intro?.takeIf { it.isNotBlank() }
+                val intro = HtmlFormatter.formatDisplayText(book.intro).takeIf { it.isNotBlank() }
                 if (settings.bookshelfShowTag && kindList.isNotEmpty()) {
                     Row(
                         modifier = Modifier

+ 12 - 0
app/src/main/java/io/legado/app/utils/HtmlFormatter.kt

@@ -1,6 +1,7 @@
 package io.legado.app.utils
 
 import io.legado.app.model.analyzeRule.AnalyzeUrl
+import org.jsoup.Jsoup
 import java.net.URL
 import java.util.regex.Pattern
 
@@ -34,6 +35,17 @@ object HtmlFormatter {
             .replace(lastRegex, "")
     }
 
+    /**
+     * Formats untrusted HTML for plain-text UI surfaces.
+     * Script and style elements must be removed with their contents before stripping tags.
+     */
+    fun formatDisplayText(html: String?): String {
+        if (html.isNullOrBlank()) return ""
+        val body = Jsoup.parseBodyFragment(html).body()
+        body.select("script, style, noscript").remove()
+        return format(body.html())
+    }
+
     fun formatKeepImg(html: String?, redirectUrl: URL? = null): String {
         html ?: return ""
         val keepImgHtml = format(html, notImgHtmlRegex)

+ 31 - 0
app/src/test/java/io/legado/app/utils/HtmlFormatterTest.kt

@@ -0,0 +1,31 @@
+package io.legado.app.utils
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class HtmlFormatterTest {
+
+    @Test
+    fun formatDisplayText_removesScriptAndStyleContents() {
+        val result = HtmlFormatter.formatDisplayText(
+            """
+                <style>.intro { color: red; }</style>
+                <p>第一段</p>
+                <script>window.alert('bad')</script>
+                <div>第二段</div>
+            """.trimIndent()
+        )
+
+        assertTrue(result.contains("第一段"))
+        assertTrue(result.contains("第二段"))
+        assertFalse(result.contains("color: red"))
+        assertFalse(result.contains("window.alert"))
+    }
+
+    @Test
+    fun formatDisplayText_keepsPlainText() {
+        assertEquals("普通简介", HtmlFormatter.formatDisplayText("普通简介"))
+    }
+}