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) 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) { fun setAutoStart(ctx: Context, v: Boolean) {
val preferences = ctx.getSharedPreferences("config", 0) val preferences = ctx.getSharedPreferences("config", 0)
preferences.edit().putBoolean("enable_auto_start", v).apply() 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 { fun enableSelfMsg(ctx: Context): Boolean {
val preferences = ctx.getSharedPreferences("config", 0) val preferences = ctx.getSharedPreferences("config", 0)
return preferences.getBoolean("enable_self_msg", false) return preferences.getBoolean("enable_self_msg", false)
@ -288,6 +298,7 @@ object ShamrockConfig {
"key_store" to preferences.getString("key_store", ""), "key_store" to preferences.getString("key_store", ""),
"enable_self_msg" to preferences.getBoolean("enable_self_msg", false), "enable_self_msg" to preferences.getBoolean("enable_self_msg", false),
"echo_number" to preferences.getBoolean("echo_number", false), "echo_number" to preferences.getBoolean("echo_number", false),
"shell" to preferences.getBoolean("shell", false),
) )
} }

View File

@ -100,7 +100,7 @@ fun LabFragment() {
Function( Function(
title = "自动清理QQ垃圾", title = "自动清理QQ垃圾",
desc = "也许会导致奇怪的问题", desc = "也许会导致奇怪的问题(无效)",
descColor = it, descColor = it,
isSwitch = ShamrockConfig.isAutoClean(ctx) isSwitch = ShamrockConfig.isAutoClean(ctx)
) { ) {
@ -129,6 +129,16 @@ fun LabFragment() {
ShamrockConfig.setAutoStart(ctx, it) ShamrockConfig.setAutoStart(ctx, it)
return@Function true 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.response.respondText
import io.ktor.server.routing.Routing import io.ktor.server.routing.Routing
import io.ktor.server.routing.post 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.CleanCache
import moe.fuqiuluo.shamrock.remote.action.handlers.DownloadFile import moe.fuqiuluo.shamrock.remote.action.handlers.DownloadFile
import moe.fuqiuluo.shamrock.remote.action.handlers.GetDeviceBattery 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.action.handlers.RestartMe
import moe.fuqiuluo.shamrock.remote.entries.Status import moe.fuqiuluo.shamrock.remote.entries.Status
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig 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.fetchOrNull
import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.fetchOrThrow
import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray
import moe.fuqiuluo.shamrock.tools.getOrPost import moe.fuqiuluo.shamrock.tools.getOrPost
import moe.fuqiuluo.shamrock.tools.isJsonArray
import moe.fuqiuluo.shamrock.tools.respond import moe.fuqiuluo.shamrock.tools.respond
import moe.fuqiuluo.shamrock.utils.FileUtils import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.MD5 import moe.fuqiuluo.shamrock.utils.MD5
import java.io.File
import java.util.concurrent.TimeUnit
fun Routing.otherAction() { 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") { getOrPost("/get_version_info") {
call.respondText(GetVersionInfo()) call.respondText(GetVersionInfo())
} }

View File

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