From 7960ed9a06523b4e82849b8baa2e2a081b79ed71 Mon Sep 17 00:00:00 2001 From: Horis <8674809+821938089@users.noreply.github.com> Date: Wed, 21 May 2025 14:29:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/data/entities/BaseSource.kt | 7 +++- .../app/model/analyzeRule/AnalyzeRule.kt | 9 +++- gradle/libs.versions.toml | 3 ++ modules/rhino/build.gradle | 1 + .../java/com/script/rhino/ClassNameMatcher.kt | 41 +++++++++++++++++++ .../com/script/rhino/CollectionExtensions.kt | 22 ++++++++++ .../com/script/rhino/RhinoClassShutter.kt | 15 ++----- 7 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 modules/rhino/src/main/java/com/script/rhino/ClassNameMatcher.kt create mode 100644 modules/rhino/src/main/java/com/script/rhino/CollectionExtensions.kt diff --git a/app/src/main/java/io/legado/app/data/entities/BaseSource.kt b/app/src/main/java/io/legado/app/data/entities/BaseSource.kt index 440d344d4..fa010b507 100644 --- a/app/src/main/java/io/legado/app/data/entities/BaseSource.kt +++ b/app/src/main/java/io/legado/app/data/entities/BaseSource.kt @@ -14,7 +14,9 @@ import io.legado.app.help.crypto.SymmetricCryptoAndroid import io.legado.app.help.http.CookieStore import io.legado.app.help.source.copy import io.legado.app.help.source.getShareScope +import io.legado.app.model.Debug import io.legado.app.utils.GSON +import io.legado.app.utils.GSONStrict import io.legado.app.utils.fromJsonArray import io.legado.app.utils.fromJsonObject import io.legado.app.utils.has @@ -112,7 +114,10 @@ interface BaseSource : JsExtensions { else -> it } - GSON.fromJsonObject>(json).getOrNull()?.let { map -> + GSONStrict.fromJsonObject>(json).getOrNull()?.let { map -> + putAll(map) + } ?: GSON.fromJsonObject>(json).getOrNull()?.let { map -> + Debug.log("≡请求头规则 JSON 格式不规范,请改为规范格式") putAll(map) } } catch (e: Exception) { diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index fdb0607a3..e372614ab 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -520,6 +520,12 @@ class AnalyzeRule( return ruleList } + private fun getOrCreateSingleSourceRule(rule: String): List { + return stringRuleCache.getOrPutLimit(rule, 16) { + listOf(SourceRule(rule)) + } + } + /** * 规则类 */ @@ -672,7 +678,8 @@ class AnalyzeRule( regType == jsRuleType -> { if (isRule(ruleParam[index])) { - getString(arrayListOf(SourceRule(ruleParam[index]))).let { + val ruleList = getOrCreateSingleSourceRule(ruleParam[index]) + getString(ruleList).let { infoVal.insert(0, it) } } else { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index acf7ac9b4..d37f2e027 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,6 +48,8 @@ recyclerview = "1.2.0" #noinspection GradleDependency viewpager2 = "1.0.0" webkit = "1.13.0" +collection = "1.5.0" + zxingLite = "3.2.0" @@ -60,6 +62,7 @@ activity-ktx = { module = "androidx.activity:activity-ktx", version.ref = "activ androidx-annotation = { group = "androidx.annotation", name = "annotation", version = "1.9.1" } #androidx-annotation-experimental = { group = "androidx.annotation", name = "annotation-experimental", version = "1.3.1" } +androidx-collection = { module = "androidx.collection:collection", version.ref = "collection" } appcompat-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" } androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" } diff --git a/modules/rhino/build.gradle b/modules/rhino/build.gradle index 35a5dc293..6aec7b61f 100644 --- a/modules/rhino/build.gradle +++ b/modules/rhino/build.gradle @@ -40,6 +40,7 @@ dependencies { implementation(libs.kotlinx.coroutines.core) implementation(libs.okhttp) + implementation(libs.androidx.collection) // def coroutines_version = '1.7.3' // implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version") diff --git a/modules/rhino/src/main/java/com/script/rhino/ClassNameMatcher.kt b/modules/rhino/src/main/java/com/script/rhino/ClassNameMatcher.kt new file mode 100644 index 000000000..b2aab11c6 --- /dev/null +++ b/modules/rhino/src/main/java/com/script/rhino/ClassNameMatcher.kt @@ -0,0 +1,41 @@ +package com.script.rhino + +import androidx.collection.LruCache +import kotlin.math.min + +class ClassNameMatcher(classNames: List) { + + private val sortedClassNames = classNames.sorted() + private val matchCache = LruCache(64) + + fun match(className: String): Boolean { + matchCache[className]?.let { + return it + } + val match = matchInternal(className) + matchCache.put(className, match) + return match + } + + private fun matchInternal(className: String): Boolean { + val index = sortedClassNames.fastBinarySearch { prefix -> + comparePrefix(className, prefix) + } + if (index >= 0) { + return true + } + val prefix = sortedClassNames.getOrNull(-index - 2) ?: return false + return className.getOrNull(prefix.length) == '.' && className.startsWith(prefix) + } + + private fun comparePrefix(className: String, prefix: String): Int { + val len = min(className.length, prefix.length) + for (i in 0 ..< len) { + val c1 = className[i] + val c2 = prefix[i] + if (c1 != c2) return c2 - c1 + } + return prefix.length - className.length + } + +} diff --git a/modules/rhino/src/main/java/com/script/rhino/CollectionExtensions.kt b/modules/rhino/src/main/java/com/script/rhino/CollectionExtensions.kt new file mode 100644 index 000000000..bfc636e70 --- /dev/null +++ b/modules/rhino/src/main/java/com/script/rhino/CollectionExtensions.kt @@ -0,0 +1,22 @@ +package com.script.rhino + +inline fun List.fastBinarySearch( + comparison: (T) -> Int +): Int { + var low = 0 + var high = lastIndex + + while (low <= high) { + val mid = (low + high).ushr(1) // safe from overflows + val midVal = get(mid) + val cmp = comparison(midVal) + + if (cmp < 0) + low = mid + 1 + else if (cmp > 0) + high = mid - 1 + else + return mid // key found + } + return -(low + 1) // key not found +} diff --git a/modules/rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt b/modules/rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt index 7639ccfca..c2c2e3cfa 100644 --- a/modules/rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt +++ b/modules/rhino/src/main/java/com/script/rhino/RhinoClassShutter.kt @@ -45,8 +45,8 @@ import java.util.Collections */ object RhinoClassShutter : ClassShutter { - private val protectedClassNames by lazy { - hashSetOf( + private val protectedClassNamesMatcher by lazy { + listOf( "java.lang.Class", "java.lang.ClassLoader", "java.net.URLClassLoader", @@ -113,7 +113,7 @@ object RhinoClassShutter : ClassShutter { "com.script", "org.mozilla", "sun", - ).let { Collections.unmodifiableSet(it) } + ).let { ClassNameMatcher(it) } } private val systemClassProtectedName by lazy { @@ -181,14 +181,7 @@ object RhinoClassShutter : ClassShutter { } override fun visibleToScripts(fullClassName: String): Boolean { - var className = fullClassName - while (className.isNotEmpty()) { - if (protectedClassNames.contains(className)) { - return false - } - className = className.substringBeforeLast(".", "") - } - return true + return !protectedClassNamesMatcher.match(fullClassName) } } \ No newline at end of file