diff --git a/build.gradle.kts b/build.gradle.kts index 8a3149d6c..88bcaec7b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,17 +4,15 @@ plugins { group = "app.revanced" -val githubUsername: String = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR") -val githubPassword: String = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN") - repositories { mavenCentral() mavenLocal() + google() maven { url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") credentials { - username = githubUsername - password = githubPassword + username = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR") + password = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN") } } // Required for FlexVer-Java @@ -27,15 +25,15 @@ repositories { } dependencies { - implementation("app.revanced:revanced-patcher:11.0.4") - implementation("app.revanced:multidexlib2:2.5.3-a3836654") - // Required for meta + implementation("app.revanced:revanced-patcher:14.0.0") + implementation("com.android.tools.smali:smali:3.0.3") + // Required because build fails without it. + // TODO: Find a way to remove this dependency. + implementation("com.google.guava:guava:32.1.2-jre") + // Used in JsonGenerator. implementation("com.google.code.gson:gson:2.10.1") - // Required for FlexVer-Java - implementation("com.unascribed:flexver-java:1.0.2") - // A dependency to the Android library unfortunately fails the build, - // which is why this is required for the patch change-oauth-client-id + // which is why this is required for the patch change-oauth-client-id. compileOnly(project("dummy")) } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 62f495dfe..ac72c34e8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt index e90fbdcfe..226f4b143 100644 --- a/src/main/kotlin/app/revanced/extensions/Extensions.kt +++ b/src/main/kotlin/app/revanced/extensions/Extensions.kt @@ -1,25 +1,26 @@ package app.revanced.extensions -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name +import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.extensions.InstructionExtensions.addInstruction +import app.revanced.patcher.extensions.MethodFingerprintExtensions.name import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.patch.PatchResultError +import app.revanced.patcher.patch.PatchException import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.Method -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction -import org.jf.dexlib2.util.MethodUtil +import com.android.tools.smali.dexlib2.Opcode +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.WideLiteralInstruction +import com.android.tools.smali.dexlib2.util.MethodUtil import org.w3c.dom.Node -// TODO: populate this to all patches /** - * Convert a [MethodFingerprint] to a [PatchResultError]. + * The [PatchException] of failing to resolve a [MethodFingerprint]. * - * @return A [PatchResultError] for the [MethodFingerprint]. + * @return The [PatchException]. */ -internal fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to resolve $name") +val MethodFingerprint.exception + get() = PatchException("Failed to resolve $name") /** * Find the [MutableMethod] from a given [Method] in a [MutableClass]. @@ -27,27 +28,27 @@ internal fun MethodFingerprint.toErrorResult() = PatchResultError("Failed to res * @param method The [Method] to find. * @return The [MutableMethod]. */ -internal fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first { +fun MutableClass.findMutableMethodOf(method: Method) = this.methods.first { MethodUtil.methodSignaturesMatch(it, method) } /** - * apply a transform to all methods of the class + * apply a transform to all methods of the class. * - * @param transform the transformation function. original method goes in, transformed method goes out + * @param transform the transformation function. original method goes in, transformed method goes out. */ -internal fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { +fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { val transformedMethods = methods.map { it.transform() } methods.clear() methods.addAll(transformedMethods) } -internal fun Node.doRecursively(action: (Node) -> Unit) { +fun Node.doRecursively(action: (Node) -> Unit) { action(this) for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action) } -internal fun MutableMethod.injectHideViewCall( +fun MutableMethod.injectHideViewCall( insertIndex: Int, viewRegister: Int, classDescriptor: String, @@ -57,7 +58,13 @@ internal fun MutableMethod.injectHideViewCall( "invoke-static { v$viewRegister }, $classDescriptor->$targetMethod(Landroid/view/View;)V" ) -internal fun Method.findIndexForIdResource(resourceName: String): Int { +/** + * Find the index of the first constant instruction with the id of the given resource name. + * + * @param resourceName the name of the resource to find the id for. + * @return the index of the first constant instruction with the id of the given resource name, or -1 if not found. + */ +fun Method.findIndexForIdResource(resourceName: String): Int { fun getIdResourceId(resourceName: String) = ResourceMappingPatch.resourceMappings.single { it.type == "id" && it.name == resourceName }.id @@ -66,6 +73,8 @@ internal fun Method.findIndexForIdResource(resourceName: String): Int { } /** + * Find the index of the first constant instruction with the given value. + * * @return the first constant instruction with the value, or -1 if not found. */ fun Method.indexOfFirstConstantInstructionValue(constantValue: Long): Int { @@ -77,8 +86,23 @@ fun Method.indexOfFirstConstantInstructionValue(constantValue: Long): Int { } /** + * Check if the method contains a constant with the given value. + * * @return if the method contains a constant with the given value. */ fun Method.containsConstantInstructionValue(constantValue: Long): Boolean { return indexOfFirstConstantInstructionValue(constantValue) >= 0 } + +/** + * Traverse the class hierarchy starting from the given root class. + * + * @param targetClass the class to start traversing the class hierarchy from. + * @param callback function that is called for every class in the hierarchy. + */ +fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) { + callback(targetClass) + this.findClass(targetClass.superclass ?: return)?.mutableClass?.let { + traverseClassHierarchy(it, callback) + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/meta/JsonGenerator.kt b/src/main/kotlin/app/revanced/meta/JsonGenerator.kt index cebf57d91..3be7793f8 100644 --- a/src/main/kotlin/app/revanced/meta/JsonGenerator.kt +++ b/src/main/kotlin/app/revanced/meta/JsonGenerator.kt @@ -6,7 +6,6 @@ import app.revanced.patcher.extensions.PatchExtensions.description import app.revanced.patcher.extensions.PatchExtensions.include import app.revanced.patcher.extensions.PatchExtensions.options import app.revanced.patcher.extensions.PatchExtensions.patchName -import app.revanced.patcher.extensions.PatchExtensions.version import app.revanced.patcher.patch.PatchOption import com.google.gson.GsonBuilder import java.io.File @@ -17,7 +16,6 @@ internal class JsonGenerator : PatchesFileGenerator { JsonPatch( it.patchName, it.description ?: "This patch has no description.", - it.version ?: "0.0.0", !it.include, it.options?.map { option -> JsonPatch.Option( @@ -48,7 +46,6 @@ internal class JsonGenerator : PatchesFileGenerator { private class JsonPatch( val name: String, val description: String, - val version: String, val excluded: Boolean, val options: Array