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

Compare commits

..

15 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
semantic-release-bot
5c3fbaee7a chore(release): 1.0.0-dev.12 [skip ci]
# [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)

### Bug Fixes

* using old instance of `Androlib` when saving ([5630e49](5630e49663))
2022-05-22 15:23:09 +00:00
oSumAtrIX
08525e9c26 Merge remote-tracking branch 'origin/dev' into dev 2022-05-22 17:21:50 +02:00
oSumAtrIX
5630e49663 fix: using old instance of Androlib when saving
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-05-22 17:21:18 +02:00
11 changed files with 144 additions and 55 deletions

View File

@@ -1,3 +1,31 @@
# [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)
### Bug Fixes
* using old instance of `Androlib` when saving ([5630e49](https://github.com/revanced/revanced-patcher/commit/5630e4966310311cdfd53e2ba128255047626adc))
# [1.0.0-dev.11](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-22) # [1.0.0-dev.11](https://github.com/revanced/revanced-patcher/compare/v1.0.0-dev.10...v1.0.0-dev.11) (2022-05-22)

View File

@@ -1,5 +1,5 @@
plugins { plugins {
kotlin("jvm") version "1.6.20" kotlin("jvm") version "1.6.21"
java java
`maven-publish` `maven-publish`
} }
@@ -8,8 +8,9 @@ group = "app.revanced"
repositories { repositories {
mavenCentral() mavenCentral()
listOf("multidexlib2", "Apktool").forEach { repo ->
maven { maven {
url = uri("https://maven.pkg.github.com/revanced/multidexlib2") url = uri("https://maven.pkg.github.com/revanced/$repo")
credentials { credentials {
// DO NOT set these variables in the project's gradle.properties. // DO NOT set these variables in the project's gradle.properties.
// Instead, you should set them in: // Instead, you should set them in:
@@ -20,11 +21,13 @@ repositories {
} }
} }
} }
}
dependencies { dependencies {
implementation(kotlin("stdlib")) 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("app.revanced:multidexlib2:2.5.2.r2")
api("org.smali:smali:2.5.2") api("org.smali:smali:2.5.2")

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 1.0.0-dev.11 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.base.Data
import app.revanced.patcher.data.implementation.findIndexed import app.revanced.patcher.data.implementation.findIndexed
import app.revanced.patcher.extensions.findAnnotationRecursively import app.revanced.patcher.extensions.findAnnotationRecursively
import app.revanced.patcher.extensions.nullOutputStream
import app.revanced.patcher.patch.base.Patch import app.revanced.patcher.patch.base.Patch
import app.revanced.patcher.patch.implementation.BytecodePatch import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.ResourcePatch 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 app.revanced.patcher.util.ListBackedSet
import brut.androlib.Androlib import brut.androlib.Androlib
import brut.androlib.meta.UsesFramework 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 brut.directory.ExtFile
import lanchon.multidexlib2.BasicDexFileNamer import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO import lanchon.multidexlib2.DexIO
@@ -41,21 +47,23 @@ class Patcher(
val packageVersion: String val packageVersion: String
val packageName: String val packageName: String
private val usesFramework: UsesFramework private lateinit var usesFramework: UsesFramework
private val patcherData: PatcherData private val patcherData: PatcherData
private val opcodes: Opcodes private val opcodes: Opcodes
private var signaturesResolved = false private var signaturesResolved = false
private val androlib = Androlib()
init { init {
val extFileInput = ExtFile(inputFile) val extFileInput = ExtFile(inputFile)
val resourceTable = androlib.getResTable(extFileInput, true)
val outDir = File(resourceCacheDirectory) val outDir = File(resourceCacheDirectory)
if (outDir.exists()) outDir.deleteRecursively() if (outDir.exists()) outDir.deleteRecursively()
outDir.mkdir() outDir.mkdir()
// load the resource table from the input file
val androlib = Androlib()
val resourceTable = androlib.getResTable(extFileInput, true)
if (patchResources) {
// 1. decode resources to cache directory // 1. decode resources to cache directory
androlib.decodeManifestWithResources(extFileInput, outDir, resourceTable) androlib.decodeManifestWithResources(extFileInput, outDir, resourceTable)
androlib.decodeResourcesFull(extFileInput, outDir, resourceTable) androlib.decodeResourcesFull(extFileInput, outDir, resourceTable)
@@ -63,11 +71,27 @@ class Patcher(
// 2. read framework ids from the resource table // 2. read framework ids from the resource table
usesFramework = UsesFramework() usesFramework = UsesFramework()
usesFramework.ids = resourceTable.listFramePackages().map { it.id }.sorted() usesFramework.ids = resourceTable.listFramePackages().map { it.id }.sorted()
} else {
// create decoder for the resource table
val decoder = ResAttrDecoder()
decoder.currentPackage = ResPackage(resourceTable, 0, null)
// 3. read package info // create xml parser with the decoder
packageName = resourceTable.packageOriginal 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 packageVersion = resourceTable.versionInfo.versionName
packageName = resourceTable.currentResPackage.name
// read dex files // read dex files
val dexFile = MultiDexIO.readDexFile(true, inputFile, NAMER, null, null) val dexFile = MultiDexIO.readDexFile(true, inputFile, NAMER, null, null)
opcodes = dexFile.opcodes opcodes = dexFile.opcodes
@@ -83,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. * @param throwOnDuplicates If this is set to true, the patcher will throw an exception if a duplicate class has been found.
*/ */
fun addFiles( fun addFiles(
files: Iterable<File>, files: Iterable<File>, allowedOverwrites: Iterable<String> = emptyList(), throwOnDuplicates: Boolean = false
allowedOverwrites: Iterable<String> = emptyList(),
throwOnDuplicates: Boolean = false
) { ) {
for (file in files) { for (file in files) {
val dexFile = MultiDexIO.readDexFile(true, file, NAMER, null, null) val dexFile = MultiDexIO.readDexFile(true, file, NAMER, null, null)
@@ -124,16 +146,16 @@ class Patcher(
// build modified resources // build modified resources
if (patchResources) { if (patchResources) {
val extDir = ExtFile(resourceCacheDirectory) val extDir = ExtFile(resourceCacheDirectory)
androlib.buildResources(extDir, usesFramework)
// TODO: figure out why a new instance of Androlib is necessary here
Androlib().buildResources(extDir, usesFramework)
} }
// write dex modified files // write dex modified files
val output = mutableMapOf<String, MemoryDataStore>() val output = mutableMapOf<String, MemoryDataStore>()
MultiDexIO.writeDexFile( MultiDexIO.writeDexFile(
true, -1, // core count true, -1, // core count
output, NAMER, newDexFile, output, NAMER, newDexFile, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null
DexIO.DEFAULT_MAX_DEX_POOL_SIZE,
null
) )
return output return output
} }
@@ -174,8 +196,7 @@ class Patcher(
* If the [Patch] failed to apply, an Exception will always be returned to the wrapping Result object. * If the [Patch] failed to apply, an Exception will always be returned to the wrapping Result object.
*/ */
fun applyPatches( fun applyPatches(
stopOnError: Boolean = false, stopOnError: Boolean = false, callback: (String) -> Unit = {}
callback: (String) -> Unit = {}
): Map<String, Result<PatchResultSuccess>> { ): Map<String, Result<PatchResultSuccess>> {
if (!signaturesResolved) { if (!signaturesResolved) {
resolveSignatures() resolveSignatures()

View File

@@ -14,8 +14,7 @@ class ResourceData(private val resourceCacheDirectory: File) : Data {
private fun resolve(path: String) = resourceCacheDirectory.resolve(path) private fun resolve(path: String) = resourceCacheDirectory.resolve(path)
fun forEach(action: (File) -> Unit) = resourceCacheDirectory.walkTopDown().forEach(action) fun forEach(action: (File) -> Unit) = resourceCacheDirectory.walkTopDown().forEach(action)
fun reader(path: String) = resolve(path).reader() fun get(path: String) = resolve(path)
fun writer(path: String) = resolve(path).writer()
fun replace(path: String, oldValue: String, newValue: String, oldValueIsRegex: Boolean = false) { fun replace(path: String, oldValue: String, newValue: String, oldValueIsRegex: Boolean = false) {
// TODO: buffer this somehow // 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.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation import org.jf.dexlib2.immutable.ImmutableMethodImplementation
import org.jf.dexlib2.util.MethodUtil import org.jf.dexlib2.util.MethodUtil
import java.io.OutputStream
/** /**
* Recursively find a given annotation on a class * Recursively find a given annotation on a class
@@ -106,3 +107,8 @@ 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) @Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
annotation class MatchingMethod( annotation class MatchingMethod(
val definingClass: String = "L<unspecified-class>", val definingClass: String = "L<unspecified-class>;",
val name: String = "<unspecified-method>" val name: String = "<unspecified-method>"
) )

View File

@@ -19,7 +19,11 @@ object PatchLoader {
val entry = entries.nextElement() val entry = entries.nextElement()
if (!entry.name.endsWith(".class") || entry.name.contains("$")) continue 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 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 import org.junit.jupiter.api.Test

View File

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