@@ -2,17 +2,21 @@ package app.revanced.patches.shared.misc.integrations
2
2
3
3
import app.revanced.patcher.data.BytecodeContext
4
4
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
5
+ import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
5
6
import app.revanced.patcher.fingerprint.MethodFingerprint
6
7
import app.revanced.patcher.patch.BytecodePatch
7
8
import app.revanced.patcher.patch.PatchException
8
9
import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch.IntegrationsFingerprint.IRegisterResolver
10
+ import app.revanced.patches.shared.misc.integrations.fingerprints.ReVancedUtilsPatchesVersionFingerprint
11
+ import app.revanced.util.resultOrThrow
9
12
import com.android.tools.smali.dexlib2.Opcode
10
13
import com.android.tools.smali.dexlib2.iface.ClassDef
11
14
import com.android.tools.smali.dexlib2.iface.Method
15
+ import java.util.jar.JarFile
12
16
13
17
abstract class BaseIntegrationsPatch (
14
18
private val hooks : Set <IntegrationsFingerprint >,
15
- ) : BytecodePatch(hooks) {
19
+ ) : BytecodePatch(hooks + setOf( ReVancedUtilsPatchesVersionFingerprint ) ) {
16
20
17
21
@Deprecated(
18
22
" Use the constructor without the integrationsDescriptor parameter" ,
@@ -34,6 +38,46 @@ abstract class BaseIntegrationsPatch(
34
38
hooks.forEach { hook ->
35
39
hook.invoke(INTEGRATIONS_CLASS_DESCRIPTOR )
36
40
}
41
+
42
+ // Modify Utils method to include the patches release version version.
43
+ ReVancedUtilsPatchesVersionFingerprint .resultOrThrow().mutableMethod.apply {
44
+ val manifestValue = getPatchesManifestEntry(" Version" )
45
+
46
+ addInstructions(
47
+ 0 ,
48
+ """
49
+ const-string v0, "$manifestValue "
50
+ return-object v0
51
+ """ ,
52
+ )
53
+ }
54
+ }
55
+
56
+ /* *
57
+ * @return The value for the manifest entry,
58
+ * or "Unknown" if the entry does not exist or is blank.
59
+ */
60
+ @Suppress(" SameParameterValue" )
61
+ private fun getPatchesManifestEntry (attributeKey : String ) = JarFile (getCurrentJarFilePath()).use { jarFile ->
62
+ jarFile.manifest.mainAttributes.entries.firstOrNull { it.key.toString() == attributeKey }?.value?.toString()
63
+ ? : " Unknown"
64
+ }
65
+
66
+ /* *
67
+ * @return The file path for the jar this classfile is contained inside.
68
+ */
69
+ private fun getCurrentJarFilePath (): String {
70
+ val className = object {}::class .java.enclosingClass.name.replace(' .' , ' /' ) + " .class"
71
+ val classUrl = object {}::class .java.classLoader.getResource(className)
72
+ if (classUrl != null ) {
73
+ val urlString = classUrl.toString()
74
+
75
+ if (urlString.startsWith(" jar:file:" )) {
76
+ val end = urlString.indexOf(' !' )
77
+ return urlString.substring(" jar:file:" .length, end)
78
+ }
79
+ }
80
+ throw IllegalStateException (" Not running from inside a JAR file." )
37
81
}
38
82
39
83
/* *
@@ -50,7 +94,7 @@ abstract class BaseIntegrationsPatch(
50
94
strings : Iterable <String >? = null ,
51
95
customFingerprint : ((methodDef: Method , classDef: ClassDef ) -> Boolean )? = null ,
52
96
private val insertIndexResolver : ((Method ) -> Int ) = object : IHookInsertIndexResolver {},
53
- private val contextRegisterResolver : (Method ) -> Int = object : IRegisterResolver {}
97
+ private val contextRegisterResolver : (Method ) -> Int = object : IRegisterResolver {},
54
98
) : MethodFingerprint(
55
99
returnType,
56
100
accessFlags,
@@ -59,17 +103,19 @@ abstract class BaseIntegrationsPatch(
59
103
strings,
60
104
customFingerprint,
61
105
) {
62
- @Deprecated(" Previous constructor that is missing the insert index." +
106
+ @Deprecated(
107
+ " Previous constructor that is missing the insert index." +
63
108
" Here only for binary compatibility, " +
64
- " and this can be removed after the next major version update." )
109
+ " and this can be removed after the next major version update." ,
110
+ )
65
111
constructor (
66
112
returnType: String? = null ,
67
113
accessFlags: Int? = null ,
68
114
parameters: Iterable <String >? = null ,
69
115
opcodes: Iterable <Opcode ?>? = null ,
70
116
strings: Iterable <String >? = null ,
71
117
customFingerprint: ((methodDef: Method , classDef: ClassDef ) -> Boolean )? = null ,
72
- contextRegisterResolver: (Method ) -> Int = object : IRegisterResolver {}
118
+ contextRegisterResolver: (Method ) -> Int = object : IRegisterResolver {},
73
119
) : this (
74
120
returnType,
75
121
accessFlags,
@@ -78,7 +124,7 @@ abstract class BaseIntegrationsPatch(
78
124
strings,
79
125
customFingerprint,
80
126
object : IHookInsertIndexResolver {},
81
- contextRegisterResolver
127
+ contextRegisterResolver,
82
128
)
83
129
84
130
fun invoke (integrationsDescriptor : String ) {
@@ -103,7 +149,7 @@ abstract class BaseIntegrationsPatch(
103
149
}
104
150
}
105
151
106
- private companion object {
107
- private const val INTEGRATIONS_CLASS_DESCRIPTOR = " Lapp/revanced/integrations/shared/Utils;"
152
+ internal companion object {
153
+ internal const val INTEGRATIONS_CLASS_DESCRIPTOR = " Lapp/revanced/integrations/shared/Utils;"
108
154
}
109
155
}
0 commit comments