1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-06 16:38:50 +02:00

Compare commits

..

22 Commits

Author SHA1 Message Date
semantic-release-bot
4cc2fa17f5 chore(release): 2.2.2 [skip ci]
## [2.2.2](https://github.com/revanced/revanced-patcher/compare/v2.2.1...v2.2.2) (2022-07-04)

### Bug Fixes

* `MethodWalker` not accounting for all reference instructions ([48068cb](48068cb3d7))
2022-07-04 19:36:34 +00:00
oSumAtrIX
48068cb3d7 fix: MethodWalker not accounting for all reference instructions 2022-07-03 22:51:04 +02:00
semantic-release-bot
d107c7245c chore(release): 2.2.1 [skip ci]
## [2.2.1](https://github.com/revanced/revanced-patcher/compare/v2.2.0...v2.2.1) (2022-07-03)

### Bug Fixes

* more useful error message ([4b2e323](4b2e3230ec))
2022-07-03 14:46:19 +00:00
oSumAtrIX
4b2e3230ec fix: more useful error message 2022-07-03 15:37:48 +02:00
semantic-release-bot
fb5b82da4e chore(release): 2.2.0 [skip ci]
# [2.2.0](https://github.com/revanced/revanced-patcher/compare/v2.1.2...v2.2.0) (2022-07-02)

### Bug Fixes

* DomFileEditor opening in- and output streams on the same file ([83187c9](83187c9edd))

### Features

* remove deprecated functions ([ada5a03](ada5a033de))
* streams overload for `XmlFileHolder` ([6f72c4c](6f72c4c4c0))
2022-07-02 22:59:27 +00:00
oSumAtrIX
5970e32aa5 Merge pull request #57 from revanced/dev
Merge `dev` to `main`
2022-07-03 00:30:37 +02:00
semantic-release-bot
0f00d33f4e chore(release): 2.2.0-dev.3 [skip ci]
# [2.2.0-dev.3](https://github.com/revanced/revanced-patcher/compare/v2.2.0-dev.2...v2.2.0-dev.3) (2022-07-02)

### Bug Fixes

* DomFileEditor opening in- and output streams on the same file ([83187c9](83187c9edd))
2022-07-02 22:21:19 +00:00
oSumAtrIX
83187c9edd fix: DomFileEditor opening in- and output streams on the same file 2022-07-03 00:19:39 +02:00
semantic-release-bot
79d70cff4b chore(release): 2.2.0-dev.2 [skip ci]
# [2.2.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v2.2.0-dev.1...v2.2.0-dev.2) (2022-07-02)

### Features

* streams overload for `XmlFileHolder` ([6f72c4c](6f72c4c4c0))
2022-07-02 15:46:16 +00:00
oSumAtrIX
6f72c4c4c0 feat: streams overload for XmlFileHolder 2022-07-02 17:44:08 +02:00
oSumAtrIX
c8eedac4d9 refactor: members of ResourceData 2022-07-02 16:22:19 +02:00
semantic-release-bot
60a8278ae8 chore(release): 2.2.0-dev.1 [skip ci]
# [2.2.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v2.1.2...v2.2.0-dev.1) (2022-07-02)

### Features

* remove deprecated functions ([ada5a03](ada5a033de))
2022-07-02 02:23:32 +00:00
oSumAtrIX
ada5a033de feat: remove deprecated functions 2022-07-02 04:21:20 +02:00
semantic-release-bot
109b8a296d chore(release): 2.1.2 [skip ci]
## [2.1.2](https://github.com/revanced/revanced-patcher/compare/v2.1.1...v2.1.2) (2022-06-29)

### Bug Fixes

* invert fingerprint resolution condition of `customFingerprint` ([e2faf4c](e2faf4ca9b))
2022-06-29 23:37:37 +00:00
oSumAtrIX
e2faf4ca9b fix: invert fingerprint resolution condition of customFingerprint 2022-06-30 01:36:25 +02:00
oSumAtrIX
2134182a0e refactor: declare data parameter internal 2022-06-29 19:55:23 +02:00
semantic-release-bot
d8b5b8bb7c chore(release): 2.1.1 [skip ci]
## [2.1.1](https://github.com/revanced/revanced-patcher/compare/v2.1.0...v2.1.1) (2022-06-28)
2022-06-28 17:47:39 +00:00
Sculas
49970b5926 build: update Apktool to re-enable 9patch decoder 2022-06-28 19:45:45 +02:00
semantic-release-bot
c1fbd8cf8c chore(release): 2.1.0 [skip ci]
# [2.1.0](https://github.com/revanced/revanced-patcher/compare/v2.0.4...v2.1.0) (2022-06-28)

### Features

* log failed patches due to failed dependencies ([a467fbb](a467fbb704))
2022-06-28 01:27:05 +00:00
oSumAtrIX
a467fbb704 feat: log failed patches due to failed dependencies 2022-06-28 03:25:49 +02:00
semantic-release-bot
5a4bd7a76e chore(release): 2.0.4 [skip ci]
## [2.0.4](https://github.com/revanced/revanced-patcher/compare/v2.0.3...v2.0.4) (2022-06-27)
2022-06-27 22:38:36 +00:00
Sculas
e5ca86fac6 build: update Apktool to disable 9patch decoder
for real for real, this time
2022-06-28 00:36:50 +02:00
8 changed files with 109 additions and 32 deletions

View File

@@ -1,3 +1,69 @@
## [2.2.2](https://github.com/revanced/revanced-patcher/compare/v2.2.1...v2.2.2) (2022-07-04)
### Bug Fixes
* `MethodWalker` not accounting for all reference instructions ([48068cb](https://github.com/revanced/revanced-patcher/commit/48068cb3d79e283ff1cad9f3f78dc1d0fcd14f83))
## [2.2.1](https://github.com/revanced/revanced-patcher/compare/v2.2.0...v2.2.1) (2022-07-03)
### Bug Fixes
* more useful error message ([4b2e323](https://github.com/revanced/revanced-patcher/commit/4b2e3230ec74fa3a57ae86067e5cb7cecbe45013))
# [2.2.0](https://github.com/revanced/revanced-patcher/compare/v2.1.2...v2.2.0) (2022-07-02)
### Bug Fixes
* DomFileEditor opening in- and output streams on the same file ([83187c9](https://github.com/revanced/revanced-patcher/commit/83187c9edd7b088bc18960c5eb9a2042ca536b5f))
### Features
* remove deprecated functions ([ada5a03](https://github.com/revanced/revanced-patcher/commit/ada5a033de3cf94e7255ec2d522520f86431f001))
* streams overload for `XmlFileHolder` ([6f72c4c](https://github.com/revanced/revanced-patcher/commit/6f72c4c4c051e48c8d03d2a7b2cfc1c53028ed86))
# [2.2.0-dev.3](https://github.com/revanced/revanced-patcher/compare/v2.2.0-dev.2...v2.2.0-dev.3) (2022-07-02)
### Bug Fixes
* DomFileEditor opening in- and output streams on the same file ([83187c9](https://github.com/revanced/revanced-patcher/commit/83187c9edd7b088bc18960c5eb9a2042ca536b5f))
# [2.2.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v2.2.0-dev.1...v2.2.0-dev.2) (2022-07-02)
### Features
* streams overload for `XmlFileHolder` ([6f72c4c](https://github.com/revanced/revanced-patcher/commit/6f72c4c4c051e48c8d03d2a7b2cfc1c53028ed86))
# [2.2.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v2.1.2...v2.2.0-dev.1) (2022-07-02)
### Features
* remove deprecated functions ([ada5a03](https://github.com/revanced/revanced-patcher/commit/ada5a033de3cf94e7255ec2d522520f86431f001))
## [2.1.2](https://github.com/revanced/revanced-patcher/compare/v2.1.1...v2.1.2) (2022-06-29)
### Bug Fixes
* invert fingerprint resolution condition of `customFingerprint` ([e2faf4c](https://github.com/revanced/revanced-patcher/commit/e2faf4ca9b6de23300b20ab471ee9dc365b04339))
## [2.1.1](https://github.com/revanced/revanced-patcher/compare/v2.1.0...v2.1.1) (2022-06-28)
# [2.1.0](https://github.com/revanced/revanced-patcher/compare/v2.0.4...v2.1.0) (2022-06-28)
### Features
* log failed patches due to failed dependencies ([a467fbb](https://github.com/revanced/revanced-patcher/commit/a467fbb704eebe812cdec14025398dab2af43959))
## [2.0.4](https://github.com/revanced/revanced-patcher/compare/v2.0.3...v2.0.4) (2022-06-27)
## [2.0.3](https://github.com/revanced/revanced-patcher/compare/v2.0.2...v2.0.3) (2022-06-27) ## [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.2](https://github.com/revanced/revanced-patcher/compare/v2.0.1...v2.0.2) (2022-06-27)

View File

@@ -24,7 +24,7 @@ dependencies {
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("app.revanced:multidexlib2:2.5.2.r2") implementation("app.revanced:multidexlib2:2.5.2.r2")
implementation("org.apktool:apktool-lib:2.6.7-SNAPSHOT") implementation("org.apktool:apktool-lib:2.6.9-SNAPSHOT")
testImplementation(kotlin("test")) testImplementation(kotlin("test"))
} }

View File

@@ -1,2 +1,2 @@
kotlin.code.style = official kotlin.code.style = official
version = 2.0.3 version = 2.2.2

View File

@@ -241,31 +241,35 @@ class Patcher(private val options: PatcherOptions) {
/** /**
* Apply a [patch] and its dependencies recursively. * Apply a [patch] and its dependencies recursively.
* @param patch The [patch] to apply. * @param patch The [patch] to apply.
* @param appliedPatches A list of [patch] names, to prevent applying [patch]es twice. * @param appliedPatches A map of [patch]es paired to a boolean indicating their success, to prevent infinite recursion.
* @return The result of executing the [patch]. * @return The result of executing the [patch].
*/ */
private fun applyPatch( private fun applyPatch(
patch: Class<out Patch<Data>>, appliedPatches: MutableList<String> patch: Class<out Patch<Data>>,
appliedPatches: MutableMap<String, Boolean>
): PatchResult { ): PatchResult {
val patchName = patch.patchName val patchName = patch.patchName
// if the patch has already applied silently skip it // if the patch has already applied silently skip it
if (appliedPatches.contains(patchName)) { if (appliedPatches.contains(patchName)) {
logger.trace("Skipping patch $patchName because it has already been applied") if (!appliedPatches[patchName]!!)
return PatchResultError("'$patchName' did not succeed previously")
logger.trace("Skipping '$patchName' because it has already been applied")
return PatchResultSuccess() return PatchResultSuccess()
} }
appliedPatches.add(patchName)
// recursively apply all dependency patches // recursively apply all dependency patches
patch.dependencies?.forEach { patch.dependencies?.forEach {
val patchDependency = it.java val patchDependency = it.java
val result = applyPatch(patchDependency, appliedPatches) val result = applyPatch(patchDependency, appliedPatches)
if (result.isSuccess()) return@forEach if (result.isSuccess()) return@forEach
val errorMessage = result.error()!!.message val errorMessage = result.error()!!.cause
return PatchResultError("$patchName depends on ${patchDependency.patchName} but the following error was raised: $errorMessage") return PatchResultError("'$patchName' depends on '${patchDependency.patchName}' but the following error was raised: $errorMessage")
} }
val patchInstance = patch.getDeclaredConstructor().newInstance() val patchInstance = patch.getDeclaredConstructor().newInstance()
@@ -273,7 +277,7 @@ class Patcher(private val options: PatcherOptions) {
// if the current patch is a resource patch but resource patching is disabled, return an error // if the current patch is a resource patch but resource patching is disabled, return an error
val isResourcePatch = patchInstance is ResourcePatch val isResourcePatch = patchInstance is ResourcePatch
if (!options.patchResources && isResourcePatch) { if (!options.patchResources && isResourcePatch) {
return PatchResultError("$patchName is a resource patch, but resource patching is disabled.") return PatchResultError("'$patchName' is a resource patch, but resource patching is disabled")
} }
// TODO: find a solution for this // TODO: find a solution for this
@@ -285,11 +289,14 @@ class Patcher(private val options: PatcherOptions) {
bytecodeData bytecodeData
} }
logger.trace("Executing patch $patchName of type: ${if (isResourcePatch) "resource" else "bytecode"}") logger.trace("Executing '$patchName' of type: ${if (isResourcePatch) "resource" else "bytecode"}")
return try { return try {
patchInstance.execute(data) val result = patchInstance.execute(data)
appliedPatches[patchName] = result.isSuccess()
result
} catch (e: Exception) { } catch (e: Exception) {
appliedPatches[patchName] = false
PatchResultError(e) PatchResultError(e)
} }
} }
@@ -301,7 +308,7 @@ class Patcher(private val options: PatcherOptions) {
*/ */
fun applyPatches(stopOnError: Boolean = false) = sequence { fun applyPatches(stopOnError: Boolean = false) = sequence {
logger.trace("Applying all patches") logger.trace("Applying all patches")
val appliedPatches = mutableListOf<String>() val appliedPatches = mutableMapOf<String, Boolean>() // first is success, second is name
for (patch in data.patches) { for (patch in data.patches) {
val patchResult = applyPatch(patch, appliedPatches) val patchResult = applyPatch(patch, appliedPatches)

View File

@@ -4,31 +4,39 @@ import app.revanced.patcher.data.Data
import org.w3c.dom.Document import org.w3c.dom.Document
import java.io.Closeable import java.io.Closeable
import java.io.File import java.io.File
import java.io.InputStream
import java.io.OutputStream
import javax.xml.parsers.DocumentBuilderFactory import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.TransformerFactory 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, Iterable<File> { class ResourceData(private val resourceCacheDirectory: File) : Data, Iterable<File> {
operator fun get(path: String) = resourceCacheDirectory.resolve(path)
val xmlEditor = XmlFileHolder() val xmlEditor = XmlFileHolder()
operator fun get(path: String) = resourceCacheDirectory.resolve(path)
override fun iterator() = resourceCacheDirectory.walkTopDown().iterator() override fun iterator() = resourceCacheDirectory.walkTopDown().iterator()
inner class XmlFileHolder { inner class XmlFileHolder {
operator fun get(inputStream: InputStream, outputStream: OutputStream) =
DomFileEditor(inputStream, lazyOf(outputStream))
operator fun get(path: String) = DomFileEditor(this@ResourceData[path]) operator fun get(path: String) = DomFileEditor(this@ResourceData[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(inputStream: InputStream, private val outputStream: Lazy<OutputStream>) : Closeable {
val file: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(domFile).also(Document::normalize) // lazily open an output stream
// this is required because when constructing a DomFileEditor the output stream is created along with the input stream, which is not allowed
// the workaround is to lazily create the output stream. This way it would be used after the input stream is closed, which happens in the constructor
constructor(file: File) : this(file.inputStream(), lazy { file.outputStream() })
val file: Document =
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream).also(Document::normalize)
override fun close() =
TransformerFactory.newInstance().newTransformer().transform(DOMSource(file), StreamResult(outputStream.value))
override fun close() = TransformerFactory.newInstance().newTransformer()
.transform(DOMSource(file), StreamResult(domFile.outputStream()))
} }

View File

@@ -48,7 +48,7 @@ data class MethodFingerprintResult(
val method: Method, val method: Method,
val classDef: ClassDef, val classDef: ClassDef,
val patternScanResult: PatternScanResult?, val patternScanResult: PatternScanResult?,
val data: BytecodeData internal val data: BytecodeData
) { ) {
/** /**
* Returns a mutable clone of [classDef] * Returns a mutable clone of [classDef]

View File

@@ -68,7 +68,7 @@ object MethodFingerprintUtils {
) )
) return false ) return false
if (methodFingerprint.customFingerprint != null && methodFingerprint.customFingerprint!!(context)) if (methodFingerprint.customFingerprint != null && !methodFingerprint.customFingerprint!!(context))
return false return false
if (methodFingerprint.strings != null) { if (methodFingerprint.strings != null) {

View File

@@ -4,11 +4,9 @@ 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.extensions.softCompareTo import app.revanced.patcher.extensions.softCompareTo
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import org.jf.dexlib2.Format
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.formats.Instruction35c import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.MethodReference import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.util.Preconditions
/** /**
* Find a method from another method via instruction offsets. * Find a method from another method via instruction offsets.
@@ -37,9 +35,7 @@ class MethodWalker internal constructor(
currentMethod.implementation?.instructions?.let { instructions -> currentMethod.implementation?.instructions?.let { instructions ->
val instruction = instructions.elementAt(offset) val instruction = instructions.elementAt(offset)
Preconditions.checkFormat(instruction.opcode, Format.Format35c) val newMethod = (instruction as ReferenceInstruction).reference as MethodReference
val newMethod = (instruction as Instruction35c).reference as MethodReference
val proxy = bytecodeData.findClass(newMethod.definingClass)!! val proxy = bytecodeData.findClass(newMethod.definingClass)!!
val methods = if (walkMutable) proxy.resolve().methods else proxy.immutableClass.methods val methods = if (walkMutable) proxy.resolve().methods else proxy.immutableClass.methods