feat: migrate to DexPatchBundle and JarPatchBundle

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
oSumAtrIX 2022-05-25 22:45:44 +02:00
parent 70ca184cf9
commit 7573db2575
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
6 changed files with 64 additions and 6 deletions

View file

@ -16,7 +16,7 @@ class ProxyBackedClassList(internal val internalClasses: MutableList<ClassDef>)
/** /**
* Apply all resolved classes into [internalClasses] and clean the [proxies] list. * 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 // FIXME: check if this could cause issues when multiple patches use the same proxy
proxies.removeIf { proxy -> proxies.removeIf { proxy ->
// if the proxy is unused, keep it in the list // if the proxy is unused, keep it in the list

View file

@ -19,11 +19,7 @@ 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( val clazz = classLoader.loadClass(entry.realName.replace('/', '.').replace(".class", ""))
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

@ -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<String>) = 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<Patch<*>>)
}
}
}

View file

@ -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('/', '.')
})
}

View file

@ -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", "")
})
}

View file

@ -0,0 +1,10 @@
package app.revanced.patcher.util.patch.util
internal class StringIterator<T, I : Iterator<T>>(
private val iterator: I,
private val _next: (T) -> String
) : Iterator<String> {
override fun hasNext() = iterator.hasNext()
override fun next() = _next(iterator.next())
}