Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 43 additions & 16 deletions src/main/kotlin/app/morphe/cli/command/PatchCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,23 @@ import app.morphe.cli.command.model.mergeWith
import app.morphe.cli.command.model.toPatchBundle
import app.morphe.cli.command.model.toSerializablePatch
import app.morphe.cli.command.model.withUpdatedBundle
import app.morphe.engine.PatchEngine
import app.morphe.engine.PatchEngine.Config.Companion.DEFAULT_KEYSTORE_ALIAS
import app.morphe.engine.PatchEngine.Config.Companion.DEFAULT_KEYSTORE_PASSWORD
import app.morphe.engine.PatchEngine.Config.Companion.LEGACY_KEYSTORE_ALIAS
import app.morphe.engine.PatchEngine.Config.Companion.LEGACY_KEYSTORE_PASSWORD
import app.morphe.engine.UpdateChecker
import app.morphe.patcher.apk.ApkUtils
import app.morphe.patcher.apk.ApkUtils.applyTo
import app.morphe.library.installation.installer.*
import app.morphe.library.installation.installer.AdbInstaller
import app.morphe.library.installation.installer.AdbInstallerResult
import app.morphe.library.installation.installer.AdbRootInstaller
import app.morphe.library.installation.installer.DeviceNotFoundException
import app.morphe.library.installation.installer.Installer
import app.morphe.library.installation.installer.RootInstallerResult
import app.morphe.patcher.Patcher
import app.morphe.patcher.PatcherConfig
import app.morphe.patcher.apk.ApkMerger
import app.morphe.patcher.apk.ApkUtils
import app.morphe.patcher.apk.ApkUtils.applyTo
import app.morphe.patcher.logging.toMorpheLogger
import app.morphe.patcher.patch.Patch
import app.morphe.patcher.patch.loadPatchesFromJar
Expand Down Expand Up @@ -196,13 +206,13 @@ internal object PatchCommand : Callable<Int> {
description = ["Alias of the private key and certificate pair keystore entry."],
showDefaultValue = ALWAYS,
)
private var keyStoreEntryAlias = "Morphe Key"
private var keyStoreEntryAlias = PatchEngine.Config.DEFAULT_KEYSTORE_ALIAS

@CommandLine.Option(
names = ["--keystore-entry-password"],
description = ["Password of the keystore entry."],
)
private var keyStoreEntryPassword = "" // Empty password by default
private var keyStoreEntryPassword = PatchEngine.Config.DEFAULT_KEYSTORE_PASSWORD

@CommandLine.Option(
names = ["--signer"],
Expand Down Expand Up @@ -666,17 +676,34 @@ internal object PatchCommand : Callable<Int> {
patchingResult.addStepResult(
PatchingStep.SIGNING,
{
ApkUtils.signApk(
patchedApkFile,
outputFilePath,
signer,
ApkUtils.KeyStoreDetails(
keystoreFilePath,
keyStorePassword,
keyStoreEntryAlias,
keyStoreEntryPassword,
),
)
fun signApk(alias: String, password: String) {
ApkUtils.signApk(
patchedApkFile,
outputFilePath,
signer,
ApkUtils.KeyStoreDetails(
keystoreFilePath,
keyStorePassword,
alias,
password,
)
)
}
try {
signApk(keyStoreEntryAlias, keyStoreEntryPassword)
} catch (e: Exception){
// Retry with legacy keystore defaults.
if (keyStoreEntryAlias == DEFAULT_KEYSTORE_ALIAS &&
keyStoreEntryPassword == DEFAULT_KEYSTORE_PASSWORD &&
keystoreFilePath.exists()
) {
logger.info("Using legacy keystore credentials")

signApk(LEGACY_KEYSTORE_ALIAS, LEGACY_KEYSTORE_PASSWORD)
} else {
throw e
}
}
}
)
} else {
Expand Down
51 changes: 41 additions & 10 deletions src/main/kotlin/app/morphe/engine/PatchEngine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ import java.io.StringWriter
import java.nio.file.Files
import java.util.logging.Logger

/**
/*
* Single patching pipeline shared by CLI and GUI. (Eventually. Right now we are still having 2 pipelines)
*/


object PatchEngine {

enum class PatchStep {
Expand All @@ -54,7 +56,14 @@ object PatchEngine {
val aaptBinaryPath: File? = null,
val tempDir: File? = null,
val failOnError: Boolean = true,
)
) {
companion object {
internal const val DEFAULT_KEYSTORE_ALIAS = "Morphe"
internal const val DEFAULT_KEYSTORE_PASSWORD = "Morphe"
internal const val LEGACY_KEYSTORE_ALIAS = "Morphe Key"
internal const val LEGACY_KEYSTORE_PASSWORD = ""
}
}

data class Result(
val success: Boolean,
Expand Down Expand Up @@ -215,18 +224,40 @@ object PatchEngine {
if (!config.unsigned) {
onProgress("Signing APK...")
try {
fun signApk(details: ApkUtils.KeyStoreDetails) {
ApkUtils.signApk(
rebuiltApk,
tempOutput,
config.signerName,
details,
)
}

val keystoreDetails = config.keystoreDetails ?: ApkUtils.KeyStoreDetails(
File(tempDir, "morphe.keystore"),
null,
"Morphe Key",
"",
)
ApkUtils.signApk(
rebuiltApk,
tempOutput,
config.signerName,
keystoreDetails,
Config.DEFAULT_KEYSTORE_ALIAS,
Config.DEFAULT_KEYSTORE_PASSWORD,
)

try {
signApk(keystoreDetails)
} catch (e: Exception){
// Retry with legacy keystore defaults.
if (config.keystoreDetails == null && keystoreDetails.keyStore.exists()) {
logger.info("Using legacy keystore credentials")

val legacyKeystoreDetails = ApkUtils.KeyStoreDetails(
keystoreDetails.keyStore,
null,
Config.LEGACY_KEYSTORE_ALIAS,
Config.LEGACY_KEYSTORE_PASSWORD,
)
signApk(legacyKeystoreDetails)
} else {
throw e
}
}
stepResults.add(StepResult(PatchStep.SIGNING, true))
} catch (e: Exception) {
stepResults.add(StepResult(PatchStep.SIGNING, false, e.toString()))
Expand Down
Loading