manager: Modify Dynamic Signature Configuration Input Verification

- Allow sizes beginning with 0x
This commit is contained in:
ShirkNeko
2025-07-05 17:39:24 +08:00
parent 7bfb37a11e
commit 4840540038
3 changed files with 61 additions and 35 deletions

View File

@@ -29,6 +29,8 @@ object Natives {
const val MINIMAL_SUPPORTED_KPM = 12800 const val MINIMAL_SUPPORTED_KPM = 12800
const val MINIMAL_SUPPORTED_DYNAMIC_SIGN = 13215
const val ROOT_UID = 0 const val ROOT_UID = 0
const val ROOT_GID = 0 const val ROOT_GID = 0

View File

@@ -122,11 +122,11 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
// 配置卡片 // 配置卡片
KsuIsValid {
SettingsGroupCard( SettingsGroupCard(
title = stringResource(R.string.configuration), title = stringResource(R.string.configuration),
content = { content = {
// 配置文件模板入口 // 配置文件模板入口
KsuIsValid {
SettingItem( SettingItem(
icon = Icons.Filled.Fence, icon = Icons.Filled.Fence,
title = stringResource(R.string.settings_profile_template), title = stringResource(R.string.settings_profile_template),
@@ -135,14 +135,12 @@ fun SettingScreen(navigator: DestinationsNavigator) {
navigator.navigate(AppProfileTemplateScreenDestination) navigator.navigate(AppProfileTemplateScreenDestination)
} }
) )
}
// 卸载模块开关 // 卸载模块开关
var umountChecked by rememberSaveable { var umountChecked by rememberSaveable {
mutableStateOf(Natives.isDefaultUmountModules()) mutableStateOf(Natives.isDefaultUmountModules())
} }
KsuIsValid {
SwitchItem( SwitchItem(
icon = Icons.Filled.FolderDelete, icon = Icons.Filled.FolderDelete,
title = stringResource(R.string.settings_umount_modules_default), title = stringResource(R.string.settings_umount_modules_default),
@@ -154,10 +152,8 @@ fun SettingScreen(navigator: DestinationsNavigator) {
} }
} }
) )
}
// SU 禁用开关 // SU 禁用开关
KsuIsValid {
if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) { if (Natives.version >= Natives.MINIMAL_SUPPORTED_SU_COMPAT) {
var isSuDisabled by rememberSaveable { var isSuDisabled by rememberSaveable {
mutableStateOf(!Natives.isSuEnabled()) mutableStateOf(!Natives.isSuEnabled())
@@ -176,8 +172,8 @@ fun SettingScreen(navigator: DestinationsNavigator) {
) )
} }
} }
}
) )
}
// 应用设置卡片 // 应用设置卡片
SettingsGroupCard( SettingsGroupCard(

View File

@@ -73,11 +73,13 @@ import kotlin.math.roundToInt
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.NavigateNext import androidx.compose.material.icons.automirrored.filled.NavigateNext
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
@@ -86,6 +88,7 @@ import com.sukisu.ultra.ui.theme.getCardElevation
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.sukisu.ultra.ksuApp import com.sukisu.ultra.ksuApp
@@ -671,6 +674,17 @@ fun MoreSettingsScreen(
} }
} }
fun parseDynamicSignSize(input: String): Int? {
return try {
when {
input.startsWith("0x", true) -> input.substring(2).toInt(16)
else -> input.toInt()
}
} catch (_: NumberFormatException) {
null
}
}
// 动态签名配置对话框 // 动态签名配置对话框
if (showDynamicSignDialog) { if (showDynamicSignDialog) {
AlertDialog( AlertDialog(
@@ -699,25 +713,34 @@ fun MoreSettingsScreen(
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
// 签名大小输入 // 签名大小输入
androidx.compose.material3.OutlinedTextField( OutlinedTextField(
value = dynamicSignSize, value = dynamicSignSize,
onValueChange = { dynamicSignSize = it }, onValueChange = { input ->
val isValid = when {
input.isEmpty() -> true
input.matches(Regex("^\\d+$")) -> true
input.matches(Regex("^0[xX][0-9a-fA-F]*$")) -> true
else -> false
}
if (isValid) {
dynamicSignSize = input
}
},
label = { Text(stringResource(R.string.signature_size)) }, label = { Text(stringResource(R.string.signature_size)) },
enabled = isDynamicSignEnabled, enabled = isDynamicSignEnabled,
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
singleLine = true, singleLine = true,
keyboardOptions = androidx.compose.foundation.text.KeyboardOptions( keyboardOptions = KeyboardOptions(
keyboardType = androidx.compose.ui.text.input.KeyboardType.Number keyboardType = KeyboardType.Text
) )
) )
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
// 签名哈希输入 // 签名哈希输入
androidx.compose.material3.OutlinedTextField( OutlinedTextField(
value = dynamicSignHash, value = dynamicSignHash,
onValueChange = { hash -> onValueChange = { hash ->
// 只允许十六进制字符
if (hash.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) { if (hash.all { it in '0'..'9' || it in 'a'..'f' || it in 'A'..'F' }) {
dynamicSignHash = hash dynamicSignHash = hash
} }
@@ -737,7 +760,7 @@ fun MoreSettingsScreen(
Button( Button(
onClick = { onClick = {
if (isDynamicSignEnabled) { if (isDynamicSignEnabled) {
val size = dynamicSignSize.toIntOrNull() val size = parseDynamicSignSize(dynamicSignSize)
if (size != null && size > 0 && dynamicSignHash.length == 64) { if (size != null && size > 0 && dynamicSignHash.length == 64) {
val success = Natives.setDynamicSign(size, dynamicSignHash) val success = Natives.setDynamicSign(size, dynamicSignHash)
if (success) { if (success) {
@@ -785,7 +808,7 @@ fun MoreSettingsScreen(
showDynamicSignDialog = false showDynamicSignDialog = false
}, },
enabled = if (isDynamicSignEnabled) { enabled = if (isDynamicSignEnabled) {
dynamicSignSize.toIntOrNull()?.let { it > 0 } == true && parseDynamicSignSize(dynamicSignSize)?.let { it > 0 } == true &&
dynamicSignHash.length == 64 dynamicSignHash.length == 64
} else true } else true
) { ) {
@@ -1375,11 +1398,15 @@ fun MoreSettingsScreen(
) )
} }
// 动态签名设置 // 动态签名设置
if (Natives.version >= Natives.MINIMAL_SUPPORTED_DYNAMIC_SIGN) {
SettingItem( SettingItem(
icon = Icons.Filled.Security, icon = Icons.Filled.Security,
title = stringResource(R.string.dynamic_sign_title), title = stringResource(R.string.dynamic_sign_title),
subtitle = if (isDynamicSignEnabled) { subtitle = if (isDynamicSignEnabled) {
stringResource(R.string.dynamic_sign_enabled_summary, dynamicSignSize) stringResource(
R.string.dynamic_sign_enabled_summary,
dynamicSignSize
)
} else { } else {
stringResource(R.string.dynamic_sign_disabled) stringResource(R.string.dynamic_sign_disabled)
}, },
@@ -1390,6 +1417,7 @@ fun MoreSettingsScreen(
} }
} }
} }
}