diff --git a/.idea/misc.xml b/.idea/misc.xml
index fd01dff6..6a8d183f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,7 +4,7 @@
-
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30810c4b..103a0af8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,16 @@
-# [1.1.0](https://github.com/revanced/revanced-cli/compare/v1.0.1...v1.1.0) (2022-05-07)
+# [1.1.0-dev.3](https://github.com/revanced/revanced-cli/compare/v1.1.0-dev.2...v1.1.0-dev.3) (2022-05-15)
### Bug Fixes
-* ClassLoader not working with Java 9+ ([3a11e11](https://github.com/revanced/revanced-cli/commit/3a11e1135bd1e8958dd21247622d549440725ead))
-* leftover TODOs ([5b1139c](https://github.com/revanced/revanced-cli/commit/5b1139ce43df1f5c2c848a8209a9e618857031ce))
+* wrong use of variable substitution / typo ([81d53b5](https://github.com/revanced/revanced-cli/commit/81d53b5518454e479b7a8f2e9be934bee30702af)), closes [revanced/revanced-cli#12](https://github.com/revanced/revanced-cli/issues/12)
+# [1.1.0-dev.2](https://github.com/revanced/revanced-cli/compare/v1.1.0-dev.1...v1.1.0-dev.2) (2022-05-07)
-### Features
-* run `release.yml` workflow on branch `dev` ([9a64730](https://github.com/revanced/revanced-cli/commit/9a6473056b940c6df4860dd09c09d7ac61545f7d))
+### Bug Fixes
+
+* wrong use of dependency to `revanced-patches` ([351de6c](https://github.com/revanced/revanced-cli/commit/351de6cb90aa0f2ec93e8b8f6c10d7d312082079))
# [1.1.0-dev.1](https://github.com/revanced/revanced-cli/compare/v1.0.1...v1.1.0-dev.1) (2022-05-07)
diff --git a/build.gradle.kts b/build.gradle.kts
index acc59605..52945306 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -22,17 +22,16 @@ repositories {
}
}
-val patchesDependency = "app.revanced:revanced-patches:1.+"
-
dependencies {
implementation(kotlin("stdlib"))
implementation("app.revanced:revanced-patcher:+")
- implementation(patchesDependency)
+ implementation("app.revanced:revanced-patches:+")
+
implementation("info.picocli:picocli:+")
- implementation("me.tongfei:progressbar:+")
implementation("com.github.li-wjohnson:jadb:master-SNAPSHOT") // using a fork instead.
implementation("org.bouncycastle:bcpkix-jdk15on:+")
+ implementation(kotlin("reflect"))
}
java {
@@ -45,9 +44,6 @@ tasks {
dependsOn(shadowJar)
}
shadowJar {
- dependencies {
- exclude(dependency(patchesDependency))
- }
manifest {
attributes("Main-Class" to "app.revanced.cli.MainKt")
attributes("Implementation-Title" to project.name)
diff --git a/gradle.properties b/gradle.properties
index cfc5d104..a7ce2f22 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,2 +1,2 @@
kotlin.code.style = official
-version = 1.1.0
+version = 1.1.0-dev.3
diff --git a/src/main/kotlin/app/revanced/cli/MainCommand.kt b/src/main/kotlin/app/revanced/cli/MainCommand.kt
index 0bed6d28..2236fad3 100644
--- a/src/main/kotlin/app/revanced/cli/MainCommand.kt
+++ b/src/main/kotlin/app/revanced/cli/MainCommand.kt
@@ -1,7 +1,11 @@
package app.revanced.cli
-import app.revanced.patch.Patches
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.extensions.findAnnotationRecursively
+import app.revanced.patcher.util.patch.PatchLoader
import app.revanced.utils.adb.Adb
+import app.revanced.utils.patcher.addPatchesFiltered
+import app.revanced.utils.signature.Signature
import picocli.CommandLine.*
import java.io.File
@@ -33,6 +37,9 @@ internal object MainCommand : Runnable {
@Option(names = ["-l", "--list"], description = ["List patches only"])
internal var listOnly: Boolean = false
+ @Option(names = ["-s", "--signature-checker"], description = ["Check signatures of all patches"])
+ internal var signatureCheck: Boolean = false
+
@Option(names = ["-m", "--merge"], description = ["One or more dex file containers to merge"])
internal var mergeFiles = listOf()
@@ -47,36 +54,44 @@ internal object MainCommand : Runnable {
override fun run() {
if (listOnly) {
- patchBundles.forEach {
- Patches.load(it).forEach {
- println(it().metadata)
- }
- }
+ for (patchBundle in patchBundles)
+ for (it in PatchLoader.loadFromFile(patchBundle))
+ println(
+ "[available] ${
+ it.javaClass.findAnnotationRecursively(
+ Name::class.java
+ )?.name ?: Name::class.java.name
+ }"
+ )
return
}
val patcher = app.revanced.patcher.Patcher(
- inputFile,
- cacheDirectory,
- patchResources
+ inputFile, cacheDirectory, patchResources
)
- Patcher.start(patcher)
-
- if (clean) {
- File(cacheDirectory).deleteRecursively()
+ if (signatureCheck) {
+ patcher.addPatchesFiltered()
+ Signature.checkSignatures(patcher)
+ return
}
val outputFile = File(outputPath)
+ var adb: Adb? = null
deploy?.let {
- Adb(
- outputFile,
- patcher.packageName,
- deploy!!
- ).deploy()
+ adb = Adb(
+ outputFile, patcher.packageName, deploy!!
+ )
+ }
+
+ Patcher.start(patcher)
+
+ if (clean) {
+ File(cacheDirectory).deleteRecursively()
+ outputFile.delete()
}
- if (clean) outputFile.delete()
+ adb?.deploy()
}
}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/cli/Patcher.kt b/src/main/kotlin/app/revanced/cli/Patcher.kt
index c20d7964..0eac7b9e 100644
--- a/src/main/kotlin/app/revanced/cli/Patcher.kt
+++ b/src/main/kotlin/app/revanced/cli/Patcher.kt
@@ -1,9 +1,9 @@
package app.revanced.cli
-import app.revanced.patch.Patches
-import app.revanced.patcher.data.base.Data
-import app.revanced.patcher.patch.base.Patch
import app.revanced.utils.filesystem.FileSystemUtils
+import app.revanced.utils.patcher.addPatchesFiltered
+import app.revanced.utils.patcher.applyPatchesPrint
+import app.revanced.utils.patcher.mergeFiles
import app.revanced.utils.signing.Signer
import java.io.File
@@ -11,15 +11,11 @@ internal class Patcher {
internal companion object {
internal fun start(patcher: app.revanced.patcher.Patcher) {
// merge files like necessary integrations
- patcher.addFiles(MainCommand.mergeFiles)
+ patcher.mergeFiles()
// add patches, but filter incompatible or excluded patches
- patcher.addPatchesFiltered()
+ patcher.addPatchesFiltered(includeFilter = MainCommand.includedPatches.isNotEmpty())
// apply patches
- for ((meta, result) in patcher.applyPatches {
- println("Applying $it.")
- }) {
- println("Applied ${meta.name}. The result was $result.")
- }
+ patcher.applyPatchesPrint()
// write output file
val outFile = File(MainCommand.outputPath)
@@ -34,7 +30,7 @@ internal class Patcher {
}
if (MainCommand.patchResources) {
- for (file in File(MainCommand.cacheDirectory).resolve("build/").listFiles().first().listFiles()) {
+ for (file in File(MainCommand.cacheDirectory).resolve("build/").listFiles()?.first()?.listFiles()!!) {
if (!file.isDirectory) {
zipFileSystem.replaceFile(file.name, file.readBytes())
continue
@@ -48,40 +44,10 @@ internal class Patcher {
// and sign the apk file
Signer.signApk(outFile)
- }
-
- private fun app.revanced.patcher.Patcher.addPatchesFiltered() {
- val packageName = this.packageName
- val packageVersion = this.packageVersion
-
- val checkInclude = MainCommand.includedPatches.isNotEmpty()
- MainCommand.patchBundles.forEach { bundle ->
- val includedPatches = mutableListOf>()
- Patches.load(bundle).forEach patch@{
- val patch = it()
-
- val filterOutPatches = true
- if (filterOutPatches && !patch.metadata.compatiblePackages.any { packageMetadata ->
- packageMetadata.name == packageName && packageMetadata.versions.any {
- it == packageVersion
- }
- }) {
-
- println("Skipping ${patch.metadata.name} due to incompatibility with current package $packageName.")
- return@patch
- }
-
- if (checkInclude && !MainCommand.includedPatches.contains(patch.metadata.shortName)) {
- return@patch
- }
+ println("[done]")
+ }
- println("Adding ${patch.metadata.name}.")
- includedPatches.add(patch)
- }
- this.addPatches(includedPatches)
- }
- }
}
}
diff --git a/src/main/kotlin/app/revanced/patch/PatchLoader.kt b/src/main/kotlin/app/revanced/patch/PatchLoader.kt
deleted file mode 100644
index 088076f4..00000000
--- a/src/main/kotlin/app/revanced/patch/PatchLoader.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package app.revanced.patch
-
-import java.io.File
-import java.net.URLClassLoader
-
-internal class PatchLoader {
- internal companion object {
-
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patch/Patches.kt b/src/main/kotlin/app/revanced/patch/Patches.kt
index b302c900..add204a9 100644
--- a/src/main/kotlin/app/revanced/patch/Patches.kt
+++ b/src/main/kotlin/app/revanced/patch/Patches.kt
@@ -1,26 +1,2 @@
package app.revanced.patch
-import app.revanced.patcher.data.base.Data
-import app.revanced.patcher.patch.base.Patch
-import app.revanced.patches.Index
-import java.io.File
-import java.net.URLClassLoader
-
-internal object Patches {
-
-
- /**
- * This method loads patches from a given patch file
- * @return the loaded patches represented as a list of functions returning instances of [Patch]
- */
- internal fun load(patchFile: File): List<() -> Patch> {
- val url = patchFile.toURI().toURL()
- val classLoader = URLClassLoader(arrayOf(url))
- return loadIndex(classLoader).patches
- }
- private fun loadIndex(classLoader: ClassLoader) = classLoader
- .loadClass(Index::class.java.canonicalName)
- .fields
- .first()
- .get(null) as Index
-}
diff --git a/src/main/kotlin/app/revanced/utils/adb/Constants.kt b/src/main/kotlin/app/revanced/utils/adb/Constants.kt
index 0710ef89..1b27e3d7 100644
--- a/src/main/kotlin/app/revanced/utils/adb/Constants.kt
+++ b/src/main/kotlin/app/revanced/utils/adb/Constants.kt
@@ -8,7 +8,7 @@ internal object Constants {
private const val COMMAND_CHMOD_MOUNT = "chmod +x"
internal const val COMMAND_PID_OF = "pidof -s"
internal const val COMMAND_CREATE_DIR = "mkdir -p"
- internal const val COMMAND_LOGCAT = "logcat -c && logcat --pid=$($COMMAND_PID_OF $PLACEHOLDER)"
+ internal const val COMMAND_LOGCAT = "logcat -c && logcat | grep AndroidRuntime"
internal const val COMMAND_RESTART = "monkey -p $PLACEHOLDER 1 && kill ${'$'}($COMMAND_PID_OF $PLACEHOLDER)"
// default mount file name
@@ -42,7 +42,7 @@ internal object Constants {
"""
#!/system/bin/sh
- stock_path=${'$'}{ pm path $PLACEHOLDER | grep base | sed 's/package://g' }
+ stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
umount -l ${'$'}stock_path
""".trimIndent()
@@ -53,7 +53,7 @@ internal object Constants {
while [ "${'$'}(getprop sys.boot_completed | tr -d '\r')" != "1" ]; do sleep 1; done
base_path="$PATH_REVANCED_APP"
- stock_path=${'$'}{ pm path $PLACEHOLDER | grep base | sed 's/package://g' }
+ stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
mount -o bind ${'$'}base_path ${'$'}stock_path
""".trimIndent()
}
diff --git a/src/main/kotlin/app/revanced/utils/patcher/Patcher.kt b/src/main/kotlin/app/revanced/utils/patcher/Patcher.kt
new file mode 100644
index 00000000..fc2cf62a
--- /dev/null
+++ b/src/main/kotlin/app/revanced/utils/patcher/Patcher.kt
@@ -0,0 +1,71 @@
+package app.revanced.utils.patcher
+
+import app.revanced.cli.MainCommand
+import app.revanced.patcher.Patcher
+import app.revanced.patcher.annotation.Compatibility
+import app.revanced.patcher.annotation.Name
+import app.revanced.patcher.data.base.Data
+import app.revanced.patcher.extensions.findAnnotationRecursively
+import app.revanced.patcher.patch.base.Patch
+import app.revanced.patcher.util.patch.PatchLoader
+
+fun Patcher.addPatchesFiltered(
+ packageCompatibilityFilter: Boolean = true,
+ packageVersionCompatibilityFilter: Boolean = true,
+ includeFilter: Boolean = false
+) {
+ val packageName = this.packageName
+ val packageVersion = this.packageVersion
+
+ MainCommand.patchBundles.forEach { bundle ->
+ val includedPatches = mutableListOf>()
+ PatchLoader.loadFromFile(bundle).forEach patch@{ p ->
+ val patch = p.getDeclaredConstructor().newInstance()
+
+ val compatibilityAnnotation = patch.javaClass.findAnnotationRecursively(Compatibility::class.java)
+
+ val patchName = patch.javaClass.findAnnotationRecursively(Name::class.java)?.name ?: Name::class.java.name
+
+ val prefix = "[skipped] $patchName"
+
+ if (includeFilter && !MainCommand.includedPatches.contains(patchName)) {
+ println(prefix)
+ return@patch
+ }
+
+ if (packageVersionCompatibilityFilter || packageCompatibilityFilter) {
+
+ if (compatibilityAnnotation == null) {
+ println("$prefix: Missing compatibility annotation.")
+ return@patch
+ }
+
+
+ for (compatiblePackage in compatibilityAnnotation.compatiblePackages) {
+ if (packageCompatibilityFilter && compatiblePackage.name != packageName) {
+ println("$prefix: Package name not matching ${compatiblePackage.name}.")
+ return@patch
+ }
+
+ if (!packageVersionCompatibilityFilter || compatiblePackage.versions.any { it == packageVersion }) continue
+ println("$prefix: Unsupported version.")
+ return@patch
+ }
+ }
+
+ includedPatches.add(patch)
+ println("[added] $patchName")
+ }
+ this.addPatches(includedPatches)
+ }
+}
+
+fun Patcher.applyPatchesPrint() {
+ for ((patch, result) in this.applyPatches()) {
+ println("[${if (result.isFailure) "error" else "success"}] $patch")
+ }
+}
+
+fun Patcher.mergeFiles() {
+ this.addFiles(MainCommand.mergeFiles)
+}
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/utils/signature/Signature.kt b/src/main/kotlin/app/revanced/utils/signature/Signature.kt
new file mode 100644
index 00000000..24afe9df
--- /dev/null
+++ b/src/main/kotlin/app/revanced/utils/signature/Signature.kt
@@ -0,0 +1,58 @@
+package app.revanced.utils.signature
+
+import app.revanced.patcher.Patcher
+import app.revanced.patcher.extensions.findAnnotationRecursively
+import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
+import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
+import org.jf.dexlib2.iface.Method
+
+object Signature {
+
+ fun checkSignatures(patcher: Patcher) {
+ val failed = mutableListOf()
+ for (signature in patcher.resolveSignatures()) {
+ val signatureClass = signature::class.java
+ val signatureName =
+ signatureClass.findAnnotationRecursively(app.revanced.patcher.annotation.Name::class.java)?.name
+ ?: signatureClass.name
+ if (!signature.resolved) {
+ failed.add(signatureName)
+ continue
+ }
+
+ val method = signature.result!!.method
+ val matchingMethod =
+ signatureClass.findAnnotationRecursively(MatchingMethod::class.java) ?: MatchingMethod()
+
+ println(
+ """
+ [Signature] $signatureName
+ [Method] ${matchingMethod.definingClass}->${matchingMethod.name}
+ [Match] ${method.definingClass}->${method.toStr()}
+ """.trimIndent()
+ )
+
+ signatureClass.findAnnotationRecursively(FuzzyPatternScanMethod::class.java)?.let {
+ val warnings = signature.result!!.scanResult.warnings!!
+ println(
+ """
+ [Warnings: ${warnings.count()}]
+ ${warnings.joinToString(separator = "\n") { warning -> "${warning.instructionIndex} / ${warning.patternIndex}: ${warning.wrongOpcode} (expected: ${warning.correctOpcode})" }}
+ """.trimIndent()
+ )
+ }
+ }
+
+ println(
+ """
+ ${"=".repeat(50)}
+ [Failed signatures: ${failed.size}]
+ ${failed.joinToString(separator = "\n") { it }}
+ """.trimIndent()
+ )
+ }
+
+ private fun Method.toStr(): String {
+ return "${this.name}(${this.parameterTypes.joinToString("")})${this.returnType}"
+ }
+}
\ No newline at end of file