From 7573db25757de89824af4f3aea167e500120eabb Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 25 May 2022 22:45:44 +0200 Subject: [PATCH] feat: migrate to `DexPatchBundle` and `JarPatchBundle` Signed-off-by: oSumAtrIX --- .../patcher/util/ProxyBackedClassList.kt | 2 +- .../revanced/patcher/util/patch/PatchLoader.kt | 6 +----- .../patcher/util/patch/base/PatchBundle.kt | 17 +++++++++++++++++ .../patch/implementation/DexPatchBundle.kt | 17 +++++++++++++++++ .../patch/implementation/JarPatchBundle.kt | 18 ++++++++++++++++++ .../patcher/util/patch/util/StringIterator.kt | 10 ++++++++++ 6 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/app/revanced/patcher/util/patch/base/PatchBundle.kt create mode 100644 src/main/kotlin/app/revanced/patcher/util/patch/implementation/DexPatchBundle.kt create mode 100644 src/main/kotlin/app/revanced/patcher/util/patch/implementation/JarPatchBundle.kt create mode 100644 src/main/kotlin/app/revanced/patcher/util/patch/util/StringIterator.kt diff --git a/src/main/kotlin/app/revanced/patcher/util/ProxyBackedClassList.kt b/src/main/kotlin/app/revanced/patcher/util/ProxyBackedClassList.kt index bbd6d41..93e6f82 100644 --- a/src/main/kotlin/app/revanced/patcher/util/ProxyBackedClassList.kt +++ b/src/main/kotlin/app/revanced/patcher/util/ProxyBackedClassList.kt @@ -16,7 +16,7 @@ class ProxyBackedClassList(internal val internalClasses: MutableList) /** * Apply all resolved classes into [internalClasses] and clean the [proxies] list. */ - fun applyProxies() { + internal fun applyProxies() { // FIXME: check if this could cause issues when multiple patches use the same proxy proxies.removeIf { proxy -> // if the proxy is unused, keep it in the list diff --git a/src/main/kotlin/app/revanced/patcher/util/patch/PatchLoader.kt b/src/main/kotlin/app/revanced/patcher/util/patch/PatchLoader.kt index ef18d32..b11e4f0 100644 --- a/src/main/kotlin/app/revanced/patcher/util/patch/PatchLoader.kt +++ b/src/main/kotlin/app/revanced/patcher/util/patch/PatchLoader.kt @@ -19,11 +19,7 @@ object PatchLoader { val entry = entries.nextElement() if (!entry.name.endsWith(".class") || entry.name.contains("$")) continue - val clazz = classLoader.loadClass( - entry.name - .replace('/', '.') - .replace(".class", "") - ) + val clazz = classLoader.loadClass(entry.realName.replace('/', '.').replace(".class", "")) if (!clazz.isAnnotationPresent(app.revanced.patcher.patch.annotations.Patch::class.java)) continue diff --git a/src/main/kotlin/app/revanced/patcher/util/patch/base/PatchBundle.kt b/src/main/kotlin/app/revanced/patcher/util/patch/base/PatchBundle.kt new file mode 100644 index 0000000..e01bb02 --- /dev/null +++ b/src/main/kotlin/app/revanced/patcher/util/patch/base/PatchBundle.kt @@ -0,0 +1,17 @@ +package app.revanced.patcher.util.patch.base + +import app.revanced.patcher.patch.base.Patch +import java.io.File + +/** + * @param patchBundlePath The path to the patch bundle. + */ +abstract class PatchBundle(patchBundlePath: String) : File(patchBundlePath) { + internal fun loadPatches(classLoader: ClassLoader, classNames: Iterator) = buildList { + classNames.forEach { className -> + val clazz = classLoader.loadClass(className) + if (!clazz.isAnnotationPresent(app.revanced.patcher.patch.annotations.Patch::class.java)) return@forEach + @Suppress("UNCHECKED_CAST") this.add(clazz as Class>) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patcher/util/patch/implementation/DexPatchBundle.kt b/src/main/kotlin/app/revanced/patcher/util/patch/implementation/DexPatchBundle.kt new file mode 100644 index 0000000..fe4848d --- /dev/null +++ b/src/main/kotlin/app/revanced/patcher/util/patch/implementation/DexPatchBundle.kt @@ -0,0 +1,17 @@ +package app.revanced.patcher.util.patch.implementation + +import app.revanced.patcher.util.patch.base.PatchBundle +import app.revanced.patcher.util.patch.util.StringIterator +import org.jf.dexlib2.DexFileFactory + +/** + * A patch bundle of the ReVanced [DexPatchBundle] format. + * @param patchBundlePath The path to a patch bundle of dex format. + * @param dexClassLoader The dex class loader. + */ +class DexPatchBundle(patchBundlePath: String, private val dexClassLoader: ClassLoader) : PatchBundle(patchBundlePath) { + fun loadPatches() = loadPatches(dexClassLoader, + StringIterator(DexFileFactory.loadDexFile(path, null).classes.iterator()) { classDef -> + classDef.type.substring(1, classDef.length - 1).replace('/', '.') + }) +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patcher/util/patch/implementation/JarPatchBundle.kt b/src/main/kotlin/app/revanced/patcher/util/patch/implementation/JarPatchBundle.kt new file mode 100644 index 0000000..3d76fb2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patcher/util/patch/implementation/JarPatchBundle.kt @@ -0,0 +1,18 @@ +package app.revanced.patcher.util.patch.implementation + +import app.revanced.patcher.util.patch.base.PatchBundle +import app.revanced.patcher.util.patch.util.StringIterator +import java.net.URLClassLoader +import java.util.jar.JarFile + +/** + * A patch bundle of the ReVanced [JarPatchBundle] format. + * @param patchBundlePath The path to the patch bundle. + */ +class JarPatchBundle(patchBundlePath: String) : PatchBundle(patchBundlePath) { + fun loadPatches() = loadPatches(URLClassLoader(arrayOf(this.toURI().toURL()), null), StringIterator( + JarFile(this).entries().iterator() + ) { + it.realName.replace('/', '.').replace(".class", "") + }) +} diff --git a/src/main/kotlin/app/revanced/patcher/util/patch/util/StringIterator.kt b/src/main/kotlin/app/revanced/patcher/util/patch/util/StringIterator.kt new file mode 100644 index 0000000..af389e1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patcher/util/patch/util/StringIterator.kt @@ -0,0 +1,10 @@ +package app.revanced.patcher.util.patch.util + +internal class StringIterator>( + private val iterator: I, + private val _next: (T) -> String +) : Iterator { + override fun hasNext() = iterator.hasNext() + + override fun next() = _next(iterator.next()) +} \ No newline at end of file