Opt KPM module installation to support URL-encoded filenames and extract module IDs for dynamically constructed names.

This will fix the flashback issue due to path issue

Signed-off-by: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
This commit is contained in:
ShirkNeko
2025-04-10 01:25:59 +08:00
parent 865dbd3799
commit 65b1518e26

View File

@@ -39,6 +39,8 @@ import androidx.core.content.edit
import shirkneko.zako.sukisu.ui.theme.ThemeConfig import shirkneko.zako.sukisu.ui.theme.ThemeConfig
import shirkneko.zako.sukisu.ui.component.rememberCustomDialog import shirkneko.zako.sukisu.ui.component.rememberCustomDialog
import shirkneko.zako.sukisu.ui.component.ConfirmDialogHandle import shirkneko.zako.sukisu.ui.component.ConfirmDialogHandle
import java.net.URLDecoder
import java.net.URLEncoder
/** /**
* KPM 管理界面 * KPM 管理界面
@@ -145,8 +147,6 @@ fun KpmScreen(
) )
} }
val selectPatchLauncher = rememberLauncherForActivityResult( val selectPatchLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult() contract = ActivityResultContracts.StartActivityForResult()
) { result -> ) { result ->
@@ -156,7 +156,8 @@ fun KpmScreen(
scope.launch { scope.launch {
val fileName = uri.lastPathSegment ?: "unknown.kpm" val fileName = uri.lastPathSegment ?: "unknown.kpm"
val tempFile = File(context.cacheDir, fileName) val encodedFileName = URLEncoder.encode(fileName, "UTF-8")
val tempFile = File(context.cacheDir, encodedFileName)
context.contentResolver.openInputStream(uri)?.use { input -> context.contentResolver.openInputStream(uri)?.use { input ->
tempFile.outputStream().use { output -> tempFile.outputStream().use { output ->
@@ -281,10 +282,10 @@ fun KpmScreen(
snackBarHost = snackBarHost, snackBarHost = snackBarHost,
kpmUninstallSuccess = kpmUninstallSuccess, kpmUninstallSuccess = kpmUninstallSuccess,
kpmUninstallFailed = kpmUninstallFailed, kpmUninstallFailed = kpmUninstallFailed,
confirmDialog = confirmDialog,
FailedtoCheckModuleFile = FailedtoCheckModuleFile, FailedtoCheckModuleFile = FailedtoCheckModuleFile,
uninstall = uninstall, uninstall = uninstall,
cancel = cancel cancel = cancel,
confirmDialog = confirmDialog
) )
} }
}, },
@@ -307,11 +308,21 @@ private suspend fun handleModuleInstall(
kpmInstallSuccess: String, kpmInstallSuccess: String,
kpmInstallFailed: String kpmInstallFailed: String
) { ) {
val moduleName = tempFile.nameWithoutExtension val moduleId = extractModuleId(tempFile.name)
if (moduleId == null) {
Log.e("KsuCli", "Failed to extract module ID from file: ${tempFile.name}")
snackBarHost.showSnackbar(
message = kpmInstallFailed,
duration = SnackbarDuration.Short
)
tempFile.delete()
return
}
val targetPath = "/data/adb/kpm/$moduleId.kpm"
try { try {
if (isEmbed) { if (isEmbed) {
val targetPath = "/data/adb/kpm/$moduleName.kpm"
Runtime.getRuntime().exec(arrayOf("su", "-c", "mkdir -p /data/adb/kpm")).waitFor() Runtime.getRuntime().exec(arrayOf("su", "-c", "mkdir -p /data/adb/kpm")).waitFor()
Runtime.getRuntime().exec(arrayOf("su", "-c", "cp ${tempFile.absolutePath} $targetPath")).waitFor() Runtime.getRuntime().exec(arrayOf("su", "-c", "cp ${tempFile.absolutePath} $targetPath")).waitFor()
} }
@@ -340,6 +351,18 @@ private suspend fun handleModuleInstall(
tempFile.delete() tempFile.delete()
} }
private fun extractModuleId(fileName: String): String? {
return try {
val decodedFileName = URLDecoder.decode(fileName, "UTF-8")
val pattern = "([^/]*?)\\.kpm$".toRegex()
val matchResult = pattern.find(decodedFileName)
matchResult?.groupValues?.get(1)
} catch (e: Exception) {
Log.e("KsuCli", "Failed to extract module ID: ${e.message}", e)
null
}
}
private suspend fun handleModuleUninstall( private suspend fun handleModuleUninstall(
module: KpmViewModel.ModuleInfo, module: KpmViewModel.ModuleInfo,
viewModel: KpmViewModel, viewModel: KpmViewModel,
@@ -351,7 +374,7 @@ private suspend fun handleModuleUninstall(
cancel: String, cancel: String,
confirmDialog: ConfirmDialogHandle confirmDialog: ConfirmDialogHandle
) { ) {
val moduleFileName = "primary:${module.id}.kpm" val moduleFileName = "${module.id}.kpm"
val moduleFilePath = "/data/adb/kpm/$moduleFileName" val moduleFilePath = "/data/adb/kpm/$moduleFileName"
val fileExists = try { val fileExists = try {