Skip to content

Commit d1fc24b

Browse files
committed
cli: add --rip-lib and --unsigned options
1 parent 6a96904 commit d1fc24b

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

src/main/kotlin/app/morphe/cli/command/PatchCommand.kt

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ import picocli.CommandLine.Help.Visibility.ALWAYS
1515
import picocli.CommandLine.Model.CommandSpec
1616
import picocli.CommandLine.Spec
1717
import java.io.File
18+
import java.io.FileOutputStream
1819
import java.io.PrintWriter
1920
import java.io.StringWriter
2021
import java.util.logging.Logger
22+
import java.util.zip.ZipEntry
23+
import java.util.zip.ZipFile
24+
import java.util.zip.ZipOutputStream
2125

2226
@CommandLine.Command(
2327
name = "patch",
@@ -181,6 +185,19 @@ internal object PatchCommand : Runnable {
181185
)
182186
private var purge: Boolean = false
183187

188+
@CommandLine.Option(
189+
names = ["--rip-lib"],
190+
description = ["Remove native libraries for specific architectures (e.g., x86, x86_64)."],
191+
)
192+
private var ripLibs: List<String> = emptyList()
193+
194+
@CommandLine.Option(
195+
names = ["--unsigned"],
196+
description = ["Don't sign the patched APK file."],
197+
showDefaultValue = ALWAYS,
198+
)
199+
private var unsigned: Boolean = false
200+
184201
@CommandLine.Parameters(
185202
description = ["APK file to patch."],
186203
arity = "1",
@@ -332,7 +349,12 @@ internal object PatchCommand : Runnable {
332349
apk.copyTo(temporaryFilesPath.resolve(apk.name), overwrite = true).apply {
333350
patcherResult.applyTo(this)
334351
}.let { patchedApkFile ->
335-
if (!mount) {
352+
353+
if (ripLibs.isNotEmpty()) {
354+
ripLibraries(patchedApkFile, ripLibs)
355+
}
356+
357+
if (!mount && !unsigned) {
336358
ApkUtils.signApk(
337359
patchedApkFile,
338360
outputFilePath,
@@ -450,4 +472,42 @@ internal object PatchCommand : Runnable {
450472
}
451473
logger.info(result)
452474
}
475+
476+
private fun ripLibraries(apkFile: File, archsToRemove: List<String>) {
477+
if (archsToRemove.isEmpty()) return
478+
479+
logger.info("Ripping libraries for architectures: $archsToRemove")
480+
481+
val tempFile = File.createTempFile("temp-rip", ".apk", apkFile.parentFile)
482+
483+
ZipFile(apkFile).use { zip ->
484+
ZipOutputStream(FileOutputStream(tempFile)).use { out ->
485+
val entries = zip.entries()
486+
while (entries.hasMoreElements()) {
487+
val entry = entries.nextElement()
488+
var shouldRemove = false
489+
490+
for (arch in archsToRemove) {
491+
if (entry.name.startsWith("lib/$arch/")) {
492+
shouldRemove = true
493+
break
494+
}
495+
}
496+
497+
if (!shouldRemove) {
498+
out.putNextEntry(ZipEntry(entry.name))
499+
zip.getInputStream(entry).copyTo(out)
500+
out.closeEntry()
501+
}
502+
}
503+
}
504+
}
505+
506+
if (apkFile.delete()) {
507+
tempFile.renameTo(apkFile)
508+
} else {
509+
tempFile.copyTo(apkFile, overwrite = true)
510+
tempFile.delete()
511+
}
512+
}
453513
}

0 commit comments

Comments
 (0)