pull/2457/head
kunfei 2 years ago
parent a3a3c53199
commit 2eb138646d
  1. 3
      app/build.gradle
  2. 6
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  3. 7
      app/src/main/java/io/legado/app/help/book/ContentProcessor.kt
  4. 74
      app/src/main/java/io/legado/app/utils/RegexExtensions.kt

@ -212,9 +212,6 @@ dependencies {
//implementation('com.github.gedoor:rhino-android:1.8')
implementation(fileTree(dir: 'lib', include: ['rhino-*.jar']))
//,android自带的正则匹配出现超时问题无法处理
implementation('com.google.re2j:re2j:1.7')
//
implementation('com.squareup.okhttp3:okhttp:4.10.0')
implementation(fileTree(dir: 'cronetlib', include: ['*.jar', '*.aar']))

@ -100,10 +100,10 @@ data class BookChapter(
if (item.pattern.isNotEmpty()) {
try {
val mDisplayTitle = if (item.isRegex) {
displayTitle.replaceRegex(
item.pattern,
displayTitle.replace(
item.pattern.toRegex(),
item.replacement
).getOrThrow()
)
} else {
displayTitle.replace(item.pattern, item.replacement)
}

@ -9,7 +9,6 @@ import io.legado.app.data.entities.ReplaceRule
import io.legado.app.exception.RegexTimeoutException
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
import io.legado.app.utils.replaceRegex
import io.legado.app.utils.stackTraceStr
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.CancellationException
@ -141,10 +140,10 @@ class ContentProcessor private constructor(
if (item.pattern.isNotEmpty()) {
try {
mContent = if (item.isRegex) {
mContent.replaceRegex(
item.pattern,
mContent.replace(
item.pattern.toRegex(),
item.replacement
).getOrThrow()
)
} else {
mContent.replace(item.pattern, item.replacement)
}

@ -1,34 +1,64 @@
package io.legado.app.utils
import com.google.re2j.Pattern
import android.util.Log
import androidx.core.os.postDelayed
import com.script.SimpleBindings
import io.legado.app.constant.AppConst
import io.legado.app.exception.RegexTimeoutException
import io.legado.app.help.CrashHandler
import io.legado.app.help.coroutine.Coroutine
import kotlinx.coroutines.suspendCancellableCoroutine
import splitties.init.appCtx
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
private val handler by lazy { buildMainHandler() }
/**
* 带有js功能的正则替换
* 采用com.google.re2j.Pattern,不会导致无限执行
* 带有超时检测的正则替换
*/
fun CharSequence.replaceRegex(regex: String, replacement: String): Result<String> {
return kotlin.runCatching {
val charSequence = this
val isJs = replacement.startsWith("@js:")
val replacement1 = if (isJs) replacement.substring(4) else replacement
val pattern = Pattern.compile(regex)
val matcher = pattern.matcher(charSequence)
val stringBuffer = StringBuffer()
while (matcher.find()) {
if (isJs) {
val bindings = SimpleBindings()
bindings["result"] = matcher.group()
val jsResult =
AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
matcher.appendReplacement(stringBuffer, jsResult)
} else {
matcher.appendReplacement(stringBuffer, replacement1)
suspend fun CharSequence.replace(regex: Regex, replacement: String, timeout: Long): String {
val charSequence = this@replace
val isJs = replacement.startsWith("@js:")
val replacement1 = if (isJs) replacement.substring(4) else replacement
return suspendCancellableCoroutine { block ->
val coroutine = Coroutine.async {
try {
val pattern = regex.toPattern()
val matcher = pattern.matcher(charSequence)
val stringBuffer = StringBuffer()
while (matcher.find()) {
if (isJs) {
val bindings = SimpleBindings()
bindings["result"] = matcher.group()
val jsResult =
AppConst.SCRIPT_ENGINE.eval(replacement1, bindings).toString()
matcher.appendReplacement(stringBuffer, jsResult)
} else {
matcher.appendReplacement(stringBuffer, replacement1)
}
}
matcher.appendTail(stringBuffer)
Log.e("regex", "end")
block.resume(stringBuffer.toString())
} catch (e: Exception) {
block.resumeWithException(e)
}
}
handler.postDelayed(timeout) {
if (coroutine.isActive) {
val timeoutMsg = "替换超时,3秒后还未结束将重启应用\n替换规则$regex\n替换内容:${this}"
val exception = RegexTimeoutException(timeoutMsg)
block.cancel(exception)
appCtx.longToastOnUi(timeoutMsg)
CrashHandler.saveCrashInfo2File(exception)
handler.postDelayed(3000) {
if (coroutine.isActive) {
appCtx.restart()
}
}
}
}
matcher.appendTail(stringBuffer)
stringBuffer.toString()
}
}

Loading…
Cancel
Save