You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-10 05:30:49 +02:00
Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
68d9e9f02c | ||
![]() |
494a9a09ac | ||
![]() |
06a88839de | ||
![]() |
4c41b955df | ||
![]() |
614e555f4c | ||
![]() |
d6ed06a327 | ||
![]() |
2fc4ec4021 | ||
![]() |
f565c4f6a7 | ||
![]() |
35749454ab | ||
![]() |
2b492e7a5e | ||
![]() |
081a5a6849 | ||
![]() |
852ae7d8d1 |
@@ -7,7 +7,11 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"@semantic-release/commit-analyzer",
|
["@semantic-release/commit-analyzer", {
|
||||||
|
"releaseRules": [
|
||||||
|
{"type": "build", "release": "patch"}
|
||||||
|
]
|
||||||
|
}],
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
"@semantic-release/changelog",
|
"@semantic-release/changelog",
|
||||||
"gradle-semantic-release-plugin",
|
"gradle-semantic-release-plugin",
|
||||||
|
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,3 +1,14 @@
|
|||||||
|
## [2.0.3](https://github.com/revanced/revanced-patcher/compare/v2.0.2...v2.0.3) (2022-06-27)
|
||||||
|
|
||||||
|
## [2.0.2](https://github.com/revanced/revanced-patcher/compare/v2.0.1...v2.0.2) (2022-06-27)
|
||||||
|
|
||||||
|
## [2.0.1](https://github.com/revanced/revanced-patcher/compare/v2.0.0...v2.0.1) (2022-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use `Exception` instead of `MethodNotFoundException` ([2fc4ec4](https://github.com/revanced/revanced-patcher/commit/2fc4ec40217a917ea6106ddc87be332f725aa13c))
|
||||||
|
|
||||||
# [2.0.0](https://github.com/revanced/revanced-patcher/compare/v1.11.0...v2.0.0) (2022-06-26)
|
# [2.0.0](https://github.com/revanced/revanced-patcher/compare/v1.11.0...v2.0.0) (2022-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -21,11 +21,10 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("app.revanced:multidexlib2:2.5.2.r2")
|
|
||||||
|
|
||||||
implementation("xpp3:xpp3:1.1.4c")
|
implementation("xpp3:xpp3:1.1.4c")
|
||||||
implementation("org.smali:smali:2.5.2")
|
implementation("org.smali:smali:2.5.2")
|
||||||
implementation("org.apktool:apktool-lib:2.6.5-SNAPSHOT")
|
implementation("app.revanced:multidexlib2:2.5.2.r2")
|
||||||
|
implementation("org.apktool:apktool-lib:2.6.7-SNAPSHOT")
|
||||||
|
|
||||||
testImplementation(kotlin("test"))
|
testImplementation(kotlin("test"))
|
||||||
}
|
}
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
version = 2.0.0
|
version = 2.0.3
|
||||||
|
@@ -13,9 +13,7 @@ data class PatcherData(
|
|||||||
internal val resourceCacheDirectory: String,
|
internal val resourceCacheDirectory: String,
|
||||||
val packageMetadata: PackageMetadata
|
val packageMetadata: PackageMetadata
|
||||||
) {
|
) {
|
||||||
|
|
||||||
internal val patches = mutableListOf<Class<out Patch<Data>>>()
|
internal val patches = mutableListOf<Class<out Patch<Data>>>()
|
||||||
|
|
||||||
internal val bytecodeData = BytecodeData(internalClasses)
|
internal val bytecodeData = BytecodeData(internalClasses)
|
||||||
internal val resourceData = ResourceData(File(resourceCacheDirectory))
|
internal val resourceData = ResourceData(File(resourceCacheDirectory))
|
||||||
}
|
}
|
@@ -28,6 +28,15 @@ class BytecodeData(
|
|||||||
classes.proxies.firstOrNull { predicate(it.immutableClass) } ?:
|
classes.proxies.firstOrNull { predicate(it.immutableClass) } ?:
|
||||||
// else resolve the class to a proxy and return it, if the predicate is matching a class
|
// else resolve the class to a proxy and return it, if the predicate is matching a class
|
||||||
classes.find(predicate)?.let { proxy(it) }
|
classes.find(predicate)?.let { proxy(it) }
|
||||||
|
|
||||||
|
fun proxy(classDef: ClassDef): app.revanced.patcher.util.proxy.ClassProxy {
|
||||||
|
var proxy = this.classes.proxies.find { it.immutableClass.type == classDef.type }
|
||||||
|
if (proxy == null) {
|
||||||
|
proxy = app.revanced.patcher.util.proxy.ClassProxy(classDef)
|
||||||
|
this.classes.add(proxy)
|
||||||
|
}
|
||||||
|
return proxy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class MethodNotFoundException(s: String) : Exception(s)
|
internal class MethodNotFoundException(s: String) : Exception(s)
|
||||||
@@ -57,13 +66,4 @@ internal inline fun <T> Iterable<T>.findIndexed(predicate: (T) -> Boolean): Pair
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
|
||||||
|
|
||||||
fun BytecodeData.proxy(classDef: ClassDef): app.revanced.patcher.util.proxy.ClassProxy {
|
|
||||||
var proxy = this.classes.proxies.find { it.immutableClass.type == classDef.type }
|
|
||||||
if (proxy == null) {
|
|
||||||
proxy = app.revanced.patcher.util.proxy.ClassProxy(classDef)
|
|
||||||
this.classes.add(proxy)
|
|
||||||
}
|
|
||||||
return proxy
|
|
||||||
}
|
}
|
@@ -9,37 +9,25 @@ import javax.xml.transform.TransformerFactory
|
|||||||
import javax.xml.transform.dom.DOMSource
|
import javax.xml.transform.dom.DOMSource
|
||||||
import javax.xml.transform.stream.StreamResult
|
import javax.xml.transform.stream.StreamResult
|
||||||
|
|
||||||
class ResourceData(private val resourceCacheDirectory: File) : Data {
|
class ResourceData(private val resourceCacheDirectory: File) : Data, Iterable<File> {
|
||||||
private fun resolve(path: String) = resourceCacheDirectory.resolve(path)
|
operator fun get(path: String) = resourceCacheDirectory.resolve(path)
|
||||||
|
val xmlEditor = XmlFileHolder()
|
||||||
|
override fun iterator() = resourceCacheDirectory.walkTopDown().iterator()
|
||||||
|
|
||||||
fun forEach(action: (File) -> Unit) = resourceCacheDirectory.walkTopDown().forEach(action)
|
inner class XmlFileHolder {
|
||||||
fun get(path: String) = resolve(path)
|
operator fun get(path: String) = DomFileEditor(this@ResourceData[path])
|
||||||
|
|
||||||
fun replace(path: String, oldValue: String, newValue: String, oldValueIsRegex: Boolean = false) {
|
|
||||||
// TODO: buffer this somehow
|
|
||||||
val content = resolve(path).readText()
|
|
||||||
|
|
||||||
if (oldValueIsRegex) {
|
|
||||||
content.replace(Regex(oldValue), newValue)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getXmlEditor(path: String) = DomFileEditor(resolve(path))
|
@Deprecated("Use operator getter instead of resolve function", ReplaceWith("get(path)"))
|
||||||
|
fun resolve(path: String) = get(path)
|
||||||
|
|
||||||
|
@Deprecated("Use operator getter on xmlEditor instead of getXmlEditor function", ReplaceWith("xmlEditor[path]"))
|
||||||
|
fun getXmlEditor(path: String) = xmlEditor[path]
|
||||||
}
|
}
|
||||||
|
|
||||||
class DomFileEditor internal constructor(private val domFile: File) : Closeable {
|
class DomFileEditor internal constructor(private val domFile: File) : Closeable {
|
||||||
val file: Document
|
val file: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||||
|
.parse(domFile).also(Document::normalize)
|
||||||
init {
|
|
||||||
val factory = DocumentBuilderFactory.newInstance()
|
|
||||||
|
|
||||||
val builder = factory.newDocumentBuilder()
|
|
||||||
|
|
||||||
// this will expectedly throw
|
|
||||||
file = builder.parse(domFile)
|
|
||||||
file.normalize()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun close() = TransformerFactory.newInstance().newTransformer()
|
override fun close() = TransformerFactory.newInstance().newTransformer()
|
||||||
.transform(DOMSource(file), StreamResult(domFile.outputStream()))
|
.transform(DOMSource(file), StreamResult(domFile.outputStream()))
|
||||||
|
@@ -2,7 +2,6 @@ package app.revanced.patcher.fingerprint.method.impl
|
|||||||
|
|
||||||
import app.revanced.patcher.data.impl.BytecodeData
|
import app.revanced.patcher.data.impl.BytecodeData
|
||||||
import app.revanced.patcher.data.impl.MethodNotFoundException
|
import app.revanced.patcher.data.impl.MethodNotFoundException
|
||||||
import app.revanced.patcher.data.impl.proxy
|
|
||||||
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
import app.revanced.patcher.extensions.MethodFingerprintExtensions.name
|
||||||
import app.revanced.patcher.extensions.softCompareTo
|
import app.revanced.patcher.extensions.softCompareTo
|
||||||
import app.revanced.patcher.fingerprint.Fingerprint
|
import app.revanced.patcher.fingerprint.Fingerprint
|
||||||
@@ -35,7 +34,7 @@ abstract class MethodFingerprint(
|
|||||||
* @throws MethodNotFoundException If the resolution of the [Method] has not happened.
|
* @throws MethodNotFoundException If the resolution of the [Method] has not happened.
|
||||||
*/
|
*/
|
||||||
var result: MethodFingerprintResult? = null
|
var result: MethodFingerprintResult? = null
|
||||||
get() = field ?: throw MethodNotFoundException("${this.name} has not been resolved yet.")
|
get() = field ?: throw Exception("${this.name} has not been resolved yet.")
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -36,12 +36,7 @@ import org.jf.dexlib2.util.Preconditions
|
|||||||
@Description("Example demonstration of a bytecode patch.")
|
@Description("Example demonstration of a bytecode patch.")
|
||||||
@ExampleResourceCompatibility
|
@ExampleResourceCompatibility
|
||||||
@Version("0.0.1")
|
@Version("0.0.1")
|
||||||
class ExampleBytecodePatch : BytecodePatch(
|
class ExampleBytecodePatch : BytecodePatch(listOf(ExampleFingerprint)) {
|
||||||
|
|
||||||
listOf(
|
|
||||||
ExampleFingerprint
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// This function will be executed by the patcher.
|
// This function will be executed by the patcher.
|
||||||
// You can treat it as a constructor
|
// You can treat it as a constructor
|
||||||
override fun execute(data: BytecodeData): PatchResult {
|
override fun execute(data: BytecodeData): PatchResult {
|
||||||
|
@@ -18,8 +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 {
|
||||||
data.getXmlEditor("AndroidManifest.xml").use { domFileEditor ->
|
data.xmlEditor["AndroidManifest.xml"].use { editor ->
|
||||||
val element = domFileEditor // regular DomFileEditor
|
val element = editor // regular DomFileEditor
|
||||||
.file
|
.file
|
||||||
.getElementsByTagName("application")
|
.getElementsByTagName("application")
|
||||||
.item(0) as Element
|
.item(0) as Element
|
||||||
@@ -30,18 +30,6 @@ class ExampleResourcePatch : ResourcePatch() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate through all available resources
|
|
||||||
data.forEach {
|
|
||||||
if (it.extension.lowercase() != "xml") return@forEach
|
|
||||||
|
|
||||||
data.replace(
|
|
||||||
it.path,
|
|
||||||
"\\ddip", // regex supported
|
|
||||||
"0dip",
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PatchResultSuccess()
|
return PatchResultSuccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user