Shamrock: support /shell

This commit is contained in:
WhiteChi 2023-11-11 11:48:53 +08:00
parent 08bce05c66
commit 80bb591a1b
4 changed files with 76 additions and 1 deletions

View File

@ -239,11 +239,21 @@ object ShamrockConfig {
return preferences.getBoolean("enable_auto_start", false)
}
fun allowShell(ctx: Context): Boolean {
val preferences = ctx.getSharedPreferences("config", 0)
return preferences.getBoolean("shell", false)
}
fun setAutoStart(ctx: Context, v: Boolean) {
val preferences = ctx.getSharedPreferences("config", 0)
preferences.edit().putBoolean("enable_auto_start", v).apply()
}
fun setShellStatus(ctx: Context, v: Boolean) {
val preferences = ctx.getSharedPreferences("config", 0)
preferences.edit().putBoolean("shell", v).apply()
}
fun enableSelfMsg(ctx: Context): Boolean {
val preferences = ctx.getSharedPreferences("config", 0)
return preferences.getBoolean("enable_self_msg", false)
@ -288,6 +298,7 @@ object ShamrockConfig {
"key_store" to preferences.getString("key_store", ""),
"enable_self_msg" to preferences.getBoolean("enable_self_msg", false),
"echo_number" to preferences.getBoolean("echo_number", false),
"shell" to preferences.getBoolean("shell", false),
)
}

View File

@ -100,7 +100,7 @@ fun LabFragment() {
Function(
title = "自动清理QQ垃圾",
desc = "也许会导致奇怪的问题",
desc = "也许会导致奇怪的问题(无效)",
descColor = it,
isSwitch = ShamrockConfig.isAutoClean(ctx)
) {
@ -129,6 +129,16 @@ fun LabFragment() {
ShamrockConfig.setAutoStart(ctx, it)
return@Function true
}
Function(
title = "开启Shell接口",
desc = "可能导致设备被入侵,请勿随意开启。",
descColor = it,
isSwitch = ShamrockConfig.allowShell(ctx)
) {
ShamrockConfig.setShellStatus(ctx, it)
return@Function true
}
}
}

View File

@ -8,6 +8,11 @@ import io.ktor.server.request.receiveMultipart
import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing
import io.ktor.server.routing.post
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonObject
import moe.fuqiuluo.shamrock.remote.action.handlers.CleanCache
import moe.fuqiuluo.shamrock.remote.action.handlers.DownloadFile
import moe.fuqiuluo.shamrock.remote.action.handlers.GetDeviceBattery
@ -15,15 +20,58 @@ import moe.fuqiuluo.shamrock.remote.action.handlers.GetVersionInfo
import moe.fuqiuluo.shamrock.remote.action.handlers.RestartMe
import moe.fuqiuluo.shamrock.remote.entries.Status
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.fetchOrNull
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray
import moe.fuqiuluo.shamrock.tools.getOrPost
import moe.fuqiuluo.shamrock.tools.isJsonArray
import moe.fuqiuluo.shamrock.tools.respond
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.MD5
import java.io.File
import java.util.concurrent.TimeUnit
fun Routing.otherAction() {
if (ShamrockConfig.allowShell()) {
getOrPost("/shell") {
val runtime = Runtime.getRuntime()
val dir = fetchOrThrow("dir")
val out = StringBuilder()
withTimeoutOrNull(5000L) {
if (isJsonArray("cmd")) {
val cmd = fetchPostJsonArray("cmd").map {
if (it is JsonObject) it.toString() else it.asString
}.toTypedArray()
withContext(Dispatchers.IO) {
runtime.exec(cmd, null, File(dir)).apply { waitFor() }
}
} else {
val cmd = fetchOrThrow("cmd")
withContext(Dispatchers.IO) {
runtime.exec(cmd, null, File(dir)).apply { waitFor() }
}
}
}.also {
if (it == null) {
respond(false, Status.IAmTired, "执行超时")
} else {
it.inputStream.use {
out.append("stdout:\n")
out.append(it.readBytes().toString(Charsets.UTF_8))
}
it.errorStream.use {
out.append("\nstderr:\n")
out.append(it.readBytes().toString(Charsets.UTF_8))
}
}
}
call.respondText(out.toString())
}
}
getOrPost("/get_version_info") {
call.respondText(GetVersionInfo())
}

View File

@ -67,6 +67,7 @@ internal object ShamrockConfig {
putBoolean("auto_clear", intent.getBooleanExtra("auto_clear", false)) // 自动清理
putBoolean("enable_self_msg", intent.getBooleanExtra("enable_self_msg", false)) // 推送自己发的消息
putBoolean("shell", intent.getBooleanExtra("shell", false)) // 开启Shell接口
putBoolean("isInit", true)
}
@ -212,4 +213,9 @@ internal object ShamrockConfig {
fun isAntiTrace(): Boolean {
return Config.antiTrace
}
fun allowShell(): Boolean {
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
return mmkv.getBoolean("shell", false)
}
}