1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-10 05:30:49 +02:00

Compare commits

...

12 Commits

Author SHA1 Message Date
semantic-release-bot
70ca184cf9 chore(release): 1.0.0-dev.15 [skip ci]
# [1.0.0-dev.15](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.14...v1.0.0-dev.15) (2022-05-25)

### Features

* utility functions to get metadata of patch & sigs ([72f16b7](72f16b7785))
2022-05-25 20:55:57 +00:00
Lucaskyy
72f16b7785 feat: utility functions to get metadata of patch & sigs 2022-05-25 22:54:20 +02:00
Lucaskyy
fc03639b26 chore: fix typo 2022-05-25 22:52:57 +02:00
semantic-release-bot
88a85f94e7 chore(release): 1.0.0-dev.14 [skip ci]
# [1.0.0-dev.14](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.13...v1.0.0-dev.14) (2022-05-24)

### Bug Fixes

* reformat (trigger release) ([45a167e](45a167e785))
2022-05-24 18:12:32 +00:00
Lucaskyy
45a167e785 fix: reformat (trigger release) 2022-05-24 20:11:04 +02:00
Lucaskyy
699d8abf59 refactor: use apktool fork
also fixed some compilation issues
2022-05-24 17:43:43 +02:00
semantic-release-bot
b58c718699 chore(release): 1.0.0-dev.13 [skip ci]
# [1.0.0-dev.13](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.12...v1.0.0-dev.13) (2022-05-24)

### Performance Improvements

* decode manifest only when not using resource patcher ([40b1fa4](40b1fa43e1))
2022-05-24 00:11:23 +00:00
oSumAtrIX
266d6810a9 refactor: use resourceData.get(path) instead of a reader/writer
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-24 01:41:48 +02:00
oSumAtrIX
40b1fa43e1 perf: decode manifest only when not using resource patcher
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-24 01:28:31 +02:00
oSumAtrIX
94f9594eed chore: update kotlin jvm
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-24 00:16:57 +02:00
oSumAtrIX
cff58ab180 refactor: improve ExampleResourcePatch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-23 20:58:03 +02:00
oSumAtrIX
989646b0b5 chore: update dependencies
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-23 20:56:17 +02:00
11 changed files with 132 additions and 53 deletions

View File

@@ -1,3 +1,24 @@
# [1.0.0-dev.15](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.14...v1.0.0-dev.15) (2022-05-25)
### Features
* utility functions to get metadata of patch & sigs ([72f16b7](https://github.com/revanced/revanced-patcher/commit/72f16b778587c28d8f8e91da502f197e7dc35d6d))
# [1.0.0-dev.14](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.13...v1.0.0-dev.14) (2022-05-24)
### Bug Fixes
* reformat (trigger release) ([45a167e](https://github.com/revanced/revanced-patcher/commit/45a167e7856da0306f796953775c7b7543d9bec0))
# [1.0.0-dev.13](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.12...v1.0.0-dev.13) (2022-05-24)
### Performance Improvements
* decode manifest only when not using resource patcher ([40b1fa4](https://github.com/revanced/revanced-patcher/commit/40b1fa43e1704ace29d3e349df2f4a8ea828c5c2))
# [1.0.0-dev.12](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.11...v1.0.0-dev.12) (2022-05-22)

View File

@@ -1,5 +1,5 @@
plugins {
kotlin("jvm") version "1.6.20"
kotlin("jvm") version "1.6.21"
java
`maven-publish`
}
@@ -8,15 +8,17 @@ group = "app.revanced"
repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/revanced/multidexlib2")
credentials {
// DO NOT set these variables in the project's gradle.properties.
// Instead, you should set them in:
// Windows: %homepath%\.gradle\gradle.properties
// Linux: ~/.gradle/gradle.properties
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR") // DO NOT CHANGE!
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN") // DO NOT CHANGE!
listOf("multidexlib2", "Apktool").forEach { repo ->
maven {
url = uri("https://maven.pkg.github.com/revanced/$repo")
credentials {
// DO NOT set these variables in the project's gradle.properties.
// Instead, you should set them in:
// Windows: %homepath%\.gradle\gradle.properties
// Linux: ~/.gradle/gradle.properties
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR") // DO NOT CHANGE!
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN") // DO NOT CHANGE!
}
}
}
}
@@ -24,7 +26,8 @@ repositories {
dependencies {
implementation(kotlin("stdlib"))
api("org.apktool:apktool-lib:2.6.1")
api("xpp3:xpp3:1.1.4c")
api("org.apktool:apktool-lib:2.6.2-SNAPSHOT")
api("app.revanced:multidexlib2:2.5.2.r2")
api("org.smali:smali:2.5.2")

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official
version = 1.0.0-dev.12
version = 1.0.0-dev.15

View File

@@ -5,6 +5,7 @@ import app.revanced.patcher.data.PatcherData
import app.revanced.patcher.data.base.Data
import app.revanced.patcher.data.implementation.findIndexed
import app.revanced.patcher.extensions.findAnnotationRecursively
import app.revanced.patcher.extensions.nullOutputStream
import app.revanced.patcher.patch.base.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.ResourcePatch
@@ -14,6 +15,11 @@ import app.revanced.patcher.signature.implementation.method.resolver.MethodSigna
import app.revanced.patcher.util.ListBackedSet
import brut.androlib.Androlib
import brut.androlib.meta.UsesFramework
import brut.androlib.res.AndrolibResources
import brut.androlib.res.data.ResPackage
import brut.androlib.res.decoder.AXmlResourceParser
import brut.androlib.res.decoder.ResAttrDecoder
import brut.androlib.res.decoder.XmlPullStreamDecoder
import brut.directory.ExtFile
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO
@@ -41,12 +47,11 @@ class Patcher(
val packageVersion: String
val packageName: String
private val usesFramework: UsesFramework
private lateinit var usesFramework: UsesFramework
private val patcherData: PatcherData
private val opcodes: Opcodes
private var signaturesResolved = false
init {
val extFileInput = ExtFile(inputFile)
val outDir = File(resourceCacheDirectory)
@@ -54,21 +59,39 @@ class Patcher(
if (outDir.exists()) outDir.deleteRecursively()
outDir.mkdir()
// load the resource table from the input file
val androlib = Androlib()
val resourceTable = androlib.getResTable(extFileInput, true)
// 1. decode resources to cache directory
androlib.decodeManifestWithResources(extFileInput, outDir, resourceTable)
androlib.decodeResourcesFull(extFileInput, outDir, resourceTable)
// 2. read framework ids from the resource table
usesFramework = UsesFramework()
usesFramework.ids = resourceTable.listFramePackages().map { it.id }.sorted()
if (patchResources) {
// 1. decode resources to cache directory
androlib.decodeManifestWithResources(extFileInput, outDir, resourceTable)
androlib.decodeResourcesFull(extFileInput, outDir, resourceTable)
// 2. read package info
packageName = resourceTable.packageOriginal
// 2. read framework ids from the resource table
usesFramework = UsesFramework()
usesFramework.ids = resourceTable.listFramePackages().map { it.id }.sorted()
} else {
// create decoder for the resource table
val decoder = ResAttrDecoder()
decoder.currentPackage = ResPackage(resourceTable, 0, null)
// create xml parser with the decoder
val axmlParser = AXmlResourceParser()
axmlParser.attrDecoder = decoder
// parse package information with the decoder and parser which will set required values in the resource table
// instead of decodeManifest another more low level solution can be created to make it faster/better
XmlPullStreamDecoder(
axmlParser, AndrolibResources().resXmlSerializer
).decodeManifest(
extFileInput.directory.getFileInput("AndroidManifest.xml"), nullOutputStream
)
}
// set package information
packageVersion = resourceTable.versionInfo.versionName
packageName = resourceTable.currentResPackage.name
// read dex files
val dexFile = MultiDexIO.readDexFile(true, inputFile, NAMER, null, null)
opcodes = dexFile.opcodes
@@ -84,9 +107,7 @@ class Patcher(
* @param throwOnDuplicates If this is set to true, the patcher will throw an exception if a duplicate class has been found.
*/
fun addFiles(
files: Iterable<File>,
allowedOverwrites: Iterable<String> = emptyList(),
throwOnDuplicates: Boolean = false
files: Iterable<File>, allowedOverwrites: Iterable<String> = emptyList(), throwOnDuplicates: Boolean = false
) {
for (file in files) {
val dexFile = MultiDexIO.readDexFile(true, file, NAMER, null, null)
@@ -134,9 +155,7 @@ class Patcher(
val output = mutableMapOf<String, MemoryDataStore>()
MultiDexIO.writeDexFile(
true, -1, // core count
output, NAMER, newDexFile,
DexIO.DEFAULT_MAX_DEX_POOL_SIZE,
null
output, NAMER, newDexFile, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null
)
return output
}
@@ -177,8 +196,7 @@ class Patcher(
* If the [Patch] failed to apply, an Exception will always be returned to the wrapping Result object.
*/
fun applyPatches(
stopOnError: Boolean = false,
callback: (String) -> Unit = {}
stopOnError: Boolean = false, callback: (String) -> Unit = {}
): Map<String, Result<PatchResultSuccess>> {
if (!signaturesResolved) {
resolveSignatures()

View File

@@ -14,8 +14,7 @@ class ResourceData(private val resourceCacheDirectory: File) : Data {
private fun resolve(path: String) = resourceCacheDirectory.resolve(path)
fun forEach(action: (File) -> Unit) = resourceCacheDirectory.walkTopDown().forEach(action)
fun reader(path: String) = resolve(path).reader()
fun writer(path: String) = resolve(path).writer()
fun get(path: String) = resolve(path)
fun replace(path: String, oldValue: String, newValue: String, oldValueIsRegex: Boolean = false) {
// TODO: buffer this somehow

View File

@@ -0,0 +1,32 @@
package app.revanced.patcher.extensions
import app.revanced.patcher.annotation.Compatibility
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.patch.base.Patch
import app.revanced.patcher.signature.implementation.method.MethodSignature
import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod
private inline fun <reified T : Annotation> Any.firstAnnotation() =
this::class.annotations.first { it is T } as T
private inline fun <reified T : Annotation> Any.recursiveAnnotation() =
this::class.java.findAnnotationRecursively(T::class.java)!!
object PatchExtensions {
val Patch<*>.name get() = firstAnnotation<Name>().name
val Patch<*>.version get() = firstAnnotation<Version>().version
val Patch<*>.description get() = firstAnnotation<Description>().description
val Patch<*>.compatiblePackages get() = recursiveAnnotation<Compatibility>().compatiblePackages
}
object MethodSignatureExtensions {
val MethodSignature.name get() = firstAnnotation<Name>().name
val MethodSignature.version get() = firstAnnotation<Version>().version
val MethodSignature.description get() = firstAnnotation<Description>().description
val MethodSignature.compatiblePackages get() = recursiveAnnotation<Compatibility>().compatiblePackages
val MethodSignature.matchingMethod get() = firstAnnotation<MatchingMethod>()
val MethodSignature.fuzzyThreshold get() = firstAnnotation<FuzzyPatternScanMethod>().threshold
}

View File

@@ -9,6 +9,7 @@ import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation
import org.jf.dexlib2.util.MethodUtil
import java.io.OutputStream
/**
* Recursively find a given annotation on a class
@@ -105,4 +106,9 @@ internal fun parametersEqual(
)
}
}
}
}
internal val nullOutputStream: OutputStream =
object : OutputStream() {
override fun write(b: Int) {}
}

View File

@@ -10,7 +10,7 @@ import app.revanced.patcher.signature.implementation.method.MethodSignature
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class MatchingMethod(
val definingClass: String = "L<unspecified-class>",
val definingClass: String = "L<unspecified-class>;",
val name: String = "<unspecified-method>"
)

View File

@@ -19,7 +19,11 @@ object PatchLoader {
val entry = entries.nextElement()
if (!entry.name.endsWith(".class") || entry.name.contains("$")) continue
val clazz = classLoader.loadClass(entry.realName.replace('/', '.').replace(".class", ""))
val clazz = classLoader.loadClass(
entry.name
.replace('/', '.')
.replace(".class", "")
)
if (!clazz.isAnnotationPresent(app.revanced.patcher.patch.annotations.Patch::class.java)) continue

View File

@@ -1,4 +1,4 @@
package app.revanced.patcher
package app.revanced.patcher.usage
import org.junit.jupiter.api.Test

View File

@@ -18,21 +18,17 @@ import org.w3c.dom.Element
@Version("0.0.1")
class ExampleResourcePatch : ResourcePatch() {
override fun execute(data: ResourceData): PatchResult {
val editor = data.getXmlEditor("AndroidManifest.xml")
// regular DomFileEditor
val element = editor
.file
.getElementsByTagName("application")
.item(0) as Element
element
.setAttribute(
"exampleAttribute",
"exampleValue"
)
// close the editor to write changes
editor.close()
data.getXmlEditor("AndroidManifest.xml").use { domFileEditor ->
val element = domFileEditor // regular DomFileEditor
.file
.getElementsByTagName("application")
.item(0) as Element
element
.setAttribute(
"exampleAttribute",
"exampleValue"
)
}
// iterate through all available resources
data.forEach {