This commit is contained in:
kunfei
2023-04-20 21:22:24 +08:00
parent f1eccda865
commit 863b41ac4f
8 changed files with 146 additions and 21 deletions

View File

@@ -1,11 +1,11 @@
package io.legado.app
import io.legado.app.constant.SCRIPT_ENGINE
import io.legado.app.rhino.Rhino
import org.intellij.lang.annotations.Language
import org.junit.Assert
import org.junit.Test
class JsTest {
class AndroidJsTest {
@Test
fun testPackages() {
@@ -35,14 +35,26 @@ class JsTest {
var queryStringWithSign = "Signature=" + signStr + "&" + query;
queryStringWithSign
""".trimIndent()
SCRIPT_ENGINE.eval(js)
Rhino.use {
evaluateString(initStandardObjects(), js, "yy", 1, null)
}
@Language("js")
val js1 = """
var returnData = new Packages.io.legado.app.api.ReturnData()
returnData.getErrorMsg()
""".trimIndent()
val result1 = SCRIPT_ENGINE.eval(js1)
val result1 = Rhino.use {
evaluateString(initStandardObjects(), js1, "xx", 1, null)
}
Assert.assertEquals(result1, "未知错误,请联系开发者!")
}
@Test
fun testReturnNull() {
val result = Rhino.use {
evaluateString(initStandardObjects(), "null", "xx", 1, null)
}
Assert.assertEquals(null, result)
}
}

View File

@@ -6,10 +6,10 @@ import io.legado.app.constant.SCRIPT_ENGINE
import io.legado.app.exception.NoStackTraceException
import io.legado.app.help.http.newCallStrResponse
import io.legado.app.help.http.okHttpClient
import io.legado.app.rhino.Rhino
import io.legado.app.utils.ACache
import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.Rhino
import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.isJsonObject
import kotlinx.coroutines.runBlocking

View File

@@ -0,0 +1,44 @@
package io.legado.app.rhino
import com.script.RhinoContextFactory
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContextFactory
import org.mozilla.javascript.Undefined
import org.mozilla.javascript.Wrapper
object Rhino {
inline fun use(block: Context.() -> Any?): Any? {
return try {
val cx = Context.enter()
val result = block.invoke(cx)
unwrapReturnValue(result)
} finally {
Context.exit()
}
}
fun unwrapReturnValue(result: Any?): Any? {
var result1 = result
if (result1 is Wrapper) {
result1 = result1.unwrap()
}
return if (result1 is Undefined) null else result1
}
init {
ContextFactory.initGlobal(object : RhinoContextFactory() {
override fun makeContext(): Context {
val cx = super.makeContext()
cx.languageVersion = 200
cx.optimizationLevel = -1
cx.setClassShutter(RhinoClassShutter)
//cx.wrapFactory = RhinoWrapFactory
return cx
}
})
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package io.legado.app.rhino
import org.mozilla.javascript.ClassShutter
/**
* This class prevents script access to certain sensitive classes.
* Note that this class checks over and above SecurityManager. i.e., although
* a SecurityManager would pass, class shutter may still prevent access.
*
* @author A. Sundararajan
* @since 1.6
*/
object RhinoClassShutter : ClassShutter {
private val protectedClasses by lazy {
val protectedClasses = HashMap<Any, Any>()
protectedClasses["java.lang.Runtime"] = java.lang.Boolean.TRUE
protectedClasses["java.io.File"] = java.lang.Boolean.TRUE
protectedClasses["java.security.AccessController"] = java.lang.Boolean.TRUE
protectedClasses
}
override fun visibleToScripts(fullClassName: String): Boolean {
val sm = System.getSecurityManager()
if (sm != null) {
val i = fullClassName.lastIndexOf(".")
if (i != -1) {
try {
sm.checkPackageAccess(fullClassName.substring(0, i))
} catch (e: SecurityException) {
return false
}
}
}
return protectedClasses[fullClassName] == null
}
}

View File

@@ -1,15 +0,0 @@
package io.legado.app.utils
import org.mozilla.javascript.Context
object Rhino {
inline fun <R> use(block: Context.() -> R): R {
return try {
block.invoke(Context.enter())
} finally {
Context.exit()
}
}
}

View File

@@ -0,0 +1,7 @@
package com.script
import org.mozilla.javascript.ContextFactory
open class RhinoContextFactory : ContextFactory() {
}

View File

@@ -0,0 +1,15 @@
package com.script
import org.mozilla.javascript.Context
import org.mozilla.javascript.ContextFactory
open class RhinoContextFactory : ContextFactory() {
override fun hasFeature(cx: Context, featureIndex: Int): Boolean {
return when (featureIndex) {
Context.FEATURE_ENABLE_JAVA_MAP_ACCESS -> true
else -> super.hasFeature(cx, featureIndex)
}
}
}

View File

@@ -51,7 +51,7 @@ object RhinoClassShutter : ClassShutter {
if (i != -1) {
try {
sm.checkPackageAccess(fullClassName.substring(0, i))
} catch (var5: SecurityException) {
} catch (e: SecurityException) {
return false
}
}