refactor: clean up usages of ~/Aliucord
This commit is contained in:
parent
0cdf2ee743
commit
8d295979be
4 changed files with 49 additions and 30 deletions
|
|
@ -6,7 +6,6 @@
|
|||
package com.aliucord.manager
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.setContent
|
||||
|
|
@ -27,9 +26,6 @@ import com.aliucord.manager.ui.widgets.updater.UpdaterDialog
|
|||
import com.aliucord.manager.util.IS_CUSTOM_BUILD
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
// TODO: move to a path provider in DI
|
||||
val aliucordDir = Environment.getExternalStorageDirectory().resolve("Aliucord")
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private val preferences: PreferencesManager by inject()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@
|
|||
|
||||
package com.aliucord.manager.installer.util
|
||||
|
||||
import com.aliucord.manager.aliucordDir
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
import com.android.apksig.ApkSigner
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
||||
import org.bouncycastle.cert.X509v3CertificateBuilder
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.get
|
||||
import java.io.File
|
||||
import java.math.BigInteger
|
||||
import java.security.*
|
||||
|
|
@ -20,21 +22,22 @@ import java.security.cert.X509Certificate
|
|||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
object Signer {
|
||||
object Signer : KoinComponent {
|
||||
private val paths = get<PathManager>()
|
||||
private val password = "password".toCharArray()
|
||||
|
||||
private val signerConfig: ApkSigner.SignerConfig by lazy {
|
||||
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
|
||||
|
||||
aliucordDir.resolve("ks.keystore").also {
|
||||
if (!it.exists()) {
|
||||
aliucordDir.mkdir()
|
||||
newKeystore(it)
|
||||
}
|
||||
}.inputStream().use { stream ->
|
||||
keyStore.load(stream, null)
|
||||
// Create new keystore if it doesn't exist
|
||||
if (!paths.keystoreFile.exists()) {
|
||||
paths.aliucordDir.mkdirs()
|
||||
newKeystore(paths.keystoreFile)
|
||||
}
|
||||
|
||||
paths.keystoreFile.inputStream()
|
||||
.use { keyStore.load(it, /* password = */ null) }
|
||||
|
||||
val alias = keyStore.aliases().nextElement()
|
||||
val certificate = keyStore.getCertificate(alias) as X509Certificate
|
||||
|
||||
|
|
@ -45,13 +48,13 @@ object Signer {
|
|||
).build()
|
||||
}
|
||||
|
||||
private fun newKeystore(out: File?) {
|
||||
private fun newKeystore(out: File) {
|
||||
val key = createKey()
|
||||
|
||||
with(KeyStore.getInstance(KeyStore.getDefaultType())) {
|
||||
load(null, password)
|
||||
setKeyEntry("alias", key.privateKey, password, arrayOf<Certificate>(key.publicKey))
|
||||
store(out?.outputStream(), password)
|
||||
store(out.outputStream(), password)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,18 +84,18 @@ object Signer {
|
|||
}
|
||||
|
||||
fun signApk(apkFile: File) {
|
||||
val outputApk = aliucordDir.resolve(apkFile.name)
|
||||
val tmpApk = apkFile.resolveSibling(apkFile.name + ".tmp")
|
||||
|
||||
ApkSigner.Builder(listOf(signerConfig))
|
||||
.setV1SigningEnabled(false) // TODO: enable so api <24 devices can work, however zip-alignment breaks
|
||||
.setV2SigningEnabled(true)
|
||||
.setV3SigningEnabled(true)
|
||||
.setInputApk(apkFile)
|
||||
.setOutputApk(outputApk)
|
||||
.setOutputApk(tmpApk)
|
||||
.build()
|
||||
.sign()
|
||||
|
||||
outputApk.renameTo(apkFile)
|
||||
tmpApk.renameTo(apkFile)
|
||||
}
|
||||
|
||||
private class KeySet(val publicKey: X509Certificate, val privateKey: PrivateKey)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,34 @@
|
|||
package com.aliucord.manager.manager
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Environment
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* A central place to provide all system paths that are used.
|
||||
*/
|
||||
class PathManager(context: Context) {
|
||||
/**
|
||||
* The Aliucord folder in which plugins/settings/themes are stored.
|
||||
* Standard path: `~/Aliucord`
|
||||
*/
|
||||
val aliucordDir = Environment.getExternalStorageDirectory().resolve("Aliucord")
|
||||
|
||||
/**
|
||||
* The directory in external storage in which plugins are stored by Aliucord.
|
||||
*/
|
||||
val pluginsDir = aliucordDir.resolve("plugins")
|
||||
|
||||
/**
|
||||
* The settings file in which Aliucord's core uses.
|
||||
*/
|
||||
val coreSettingsFile = aliucordDir.resolve("settings/Aliucord.json")
|
||||
|
||||
/**
|
||||
* Global keystore used for signing APKs.
|
||||
*/
|
||||
val keystoreFile = aliucordDir.resolve("ks.keystore")
|
||||
|
||||
private val externalCacheDir = context.externalCacheDir
|
||||
?: throw Error("External cache directory isn't supported")
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@ import androidx.compose.runtime.*
|
|||
import cafe.adriel.voyager.core.model.ScreenModel
|
||||
import cafe.adriel.voyager.core.model.screenModelScope
|
||||
import com.aliucord.manager.BuildConfig
|
||||
import com.aliucord.manager.aliucordDir
|
||||
import com.aliucord.manager.domain.model.Plugin
|
||||
import com.aliucord.manager.manager.PathManager
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.*
|
||||
|
||||
class PluginsModel : ScreenModel {
|
||||
class PluginsModel(
|
||||
private val paths: PathManager,
|
||||
) : ScreenModel {
|
||||
var showChangelogDialog by mutableStateOf(false)
|
||||
private set
|
||||
|
||||
|
|
@ -57,8 +59,6 @@ class PluginsModel : ScreenModel {
|
|||
plugins.remove(plugin)
|
||||
}
|
||||
|
||||
private val settingsFile = aliucordDir.resolve("settings/Aliucord.json")
|
||||
|
||||
fun setPluginEnabled(plugin: String, enable: Boolean) {
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Main) {
|
||||
|
|
@ -69,13 +69,13 @@ class PluginsModel : ScreenModel {
|
|||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
try {
|
||||
val settings = settingsFile.inputStream()
|
||||
val settings = paths.coreSettingsFile.inputStream()
|
||||
.use { Json.decodeFromStream<Map<String, JsonElement>>(it) }
|
||||
.toMutableMap()
|
||||
|
||||
settings["AC_PM_$plugin"] = JsonPrimitive(enable)
|
||||
|
||||
settingsFile.outputStream()
|
||||
paths.coreSettingsFile.outputStream()
|
||||
.use { Json.encodeToStream(settings, it) }
|
||||
} catch (t: Throwable) {
|
||||
Log.e(BuildConfig.TAG, "Failed to write Aliucord.json: ${Log.getStackTraceString(t)}")
|
||||
|
|
@ -85,11 +85,11 @@ class PluginsModel : ScreenModel {
|
|||
}
|
||||
|
||||
private suspend fun loadEnabled(): Map<String, Boolean> = withContext(Dispatchers.IO) {
|
||||
if (!settingsFile.exists()) return@withContext emptyMap()
|
||||
if (!paths.coreSettingsFile.exists()) return@withContext emptyMap()
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
try {
|
||||
settingsFile.inputStream()
|
||||
paths.coreSettingsFile.inputStream()
|
||||
.use { Json.decodeFromStream<Map<String, JsonElement>>(it) }
|
||||
.filterKeys { it.startsWith("AC_PM_") }
|
||||
.mapKeys { it.key.substring("AC_PM_".length) }
|
||||
|
|
@ -107,14 +107,12 @@ class PluginsModel : ScreenModel {
|
|||
}
|
||||
|
||||
screenModelScope.launch(Dispatchers.IO) {
|
||||
val pluginsDir = aliucordDir.resolve("plugins")
|
||||
|
||||
if (!pluginsDir.exists() && !pluginsDir.mkdirs()) {
|
||||
if (!paths.pluginsDir.exists() && !paths.pluginsDir.mkdirs()) {
|
||||
Log.e(BuildConfig.TAG, "Failed to create plugins dir. Missing Permissions?")
|
||||
return@launch
|
||||
}
|
||||
|
||||
val files = pluginsDir.listFiles { file -> file.extension == "zip" } ?: return@launch
|
||||
val files = paths.pluginsDir.listFiles { file -> file.extension == "zip" } ?: return@launch
|
||||
val loadedPlugins = files.mapNotNull { file ->
|
||||
try {
|
||||
Plugin(file)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue