mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-04 08:24:30 +02:00
fix(core): restricted methods
Signed-off-by: rhunk <101876869+rhunk@users.noreply.github.com>
This commit is contained in:
parent
cbf02e1a4a
commit
bf5d57758c
@ -12,7 +12,6 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import de.robv.android.xposed.XposedHelpers
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import me.rhunk.snapenhance.common.data.ContentType
|
import me.rhunk.snapenhance.common.data.ContentType
|
||||||
import me.rhunk.snapenhance.common.data.FileType
|
import me.rhunk.snapenhance.common.data.FileType
|
||||||
@ -30,6 +29,7 @@ import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder
|
|||||||
import me.rhunk.snapenhance.core.features.impl.experiments.BetterTranscript
|
import me.rhunk.snapenhance.core.features.impl.experiments.BetterTranscript
|
||||||
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
|
import me.rhunk.snapenhance.core.features.impl.spying.StealthMode
|
||||||
import me.rhunk.snapenhance.core.util.hook.HookStage
|
import me.rhunk.snapenhance.core.util.hook.HookStage
|
||||||
|
import me.rhunk.snapenhance.core.util.hook.findRestrictedConstructor
|
||||||
import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod
|
import me.rhunk.snapenhance.core.util.hook.findRestrictedMethod
|
||||||
import me.rhunk.snapenhance.core.util.hook.hook
|
import me.rhunk.snapenhance.core.util.hook.hook
|
||||||
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
import me.rhunk.snapenhance.core.util.ktx.setObjectField
|
||||||
@ -69,13 +69,7 @@ class Notifications : Feature("Notifications") {
|
|||||||
private val sentNotifications = mutableMapOf<Int, String>() // notificationId => conversationId
|
private val sentNotifications = mutableMapOf<Int, String>() // notificationId => conversationId
|
||||||
|
|
||||||
private val notifyAsUserMethod by lazy {
|
private val notifyAsUserMethod by lazy {
|
||||||
XposedHelpers.findMethodExact(
|
NotificationManager::class.java.findRestrictedMethod { it.name == "notifyAsUser" } ?: throw NoSuchMethodException("notifyAsUser")
|
||||||
NotificationManager::class.java, "notifyAsUser",
|
|
||||||
String::class.java,
|
|
||||||
Int::class.javaPrimitiveType,
|
|
||||||
Notification::class.java,
|
|
||||||
UserHandle::class.java
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val notificationManager by lazy {
|
private val notificationManager by lazy {
|
||||||
@ -85,11 +79,9 @@ class Notifications : Feature("Notifications") {
|
|||||||
private val translations by lazy { context.translation.getCategory("better_notifications") }
|
private val translations by lazy { context.translation.getCategory("better_notifications") }
|
||||||
private val config by lazy { context.config.messaging.betterNotifications }
|
private val config by lazy { context.config.messaging.betterNotifications }
|
||||||
|
|
||||||
private fun newNotificationBuilder(notification: Notification) = XposedHelpers.newInstance(
|
private fun newNotificationBuilder(notification: Notification) = Notification.Builder::class.java.findRestrictedConstructor {
|
||||||
Notification.Builder::class.java,
|
it.parameterTypes.size == 2 && it.parameterTypes[1] == Notification::class.java
|
||||||
context.androidContext,
|
}?.newInstance(context.androidContext, notification) as? Notification.Builder ?: throw NoSuchMethodException("Notification.Builder")
|
||||||
notification
|
|
||||||
) as Notification.Builder
|
|
||||||
|
|
||||||
private fun setNotificationText(notification: Notification, text: String) {
|
private fun setNotificationText(notification: Notification, text: String) {
|
||||||
notification.extras.putString("android.text", text)
|
notification.extras.putString("android.text", text)
|
||||||
|
@ -3,7 +3,6 @@ package me.rhunk.snapenhance.core.messaging
|
|||||||
import android.util.Base64InputStream
|
import android.util.Base64InputStream
|
||||||
import android.util.Base64OutputStream
|
import android.util.Base64OutputStream
|
||||||
import com.google.gson.stream.JsonWriter
|
import com.google.gson.stream.JsonWriter
|
||||||
import de.robv.android.xposed.XposedHelpers
|
|
||||||
import me.rhunk.snapenhance.common.BuildConfig
|
import me.rhunk.snapenhance.common.BuildConfig
|
||||||
import me.rhunk.snapenhance.common.data.ContentType
|
import me.rhunk.snapenhance.common.data.ContentType
|
||||||
import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry
|
import me.rhunk.snapenhance.common.database.impl.FriendFeedEntry
|
||||||
@ -11,6 +10,7 @@ import me.rhunk.snapenhance.common.database.impl.FriendInfo
|
|||||||
import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper
|
import me.rhunk.snapenhance.common.util.snap.MediaDownloaderHelper
|
||||||
import me.rhunk.snapenhance.core.ModContext
|
import me.rhunk.snapenhance.core.ModContext
|
||||||
import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder
|
import me.rhunk.snapenhance.core.features.impl.downloader.decoder.MessageDecoder
|
||||||
|
import me.rhunk.snapenhance.core.util.hook.findRestrictedConstructor
|
||||||
import me.rhunk.snapenhance.core.wrapper.impl.Message
|
import me.rhunk.snapenhance.core.wrapper.impl.Message
|
||||||
import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID
|
import me.rhunk.snapenhance.core.wrapper.impl.SnapUUID
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
@ -47,6 +47,24 @@ class ConversationExporter(
|
|||||||
private val outputFileStream by lazy { outputFile.outputStream() }
|
private val outputFileStream by lazy { outputFile.outputStream() }
|
||||||
private val participants = mutableMapOf<String, Int>()
|
private val participants = mutableMapOf<String, Int>()
|
||||||
|
|
||||||
|
private val newBase64OutputStream by lazy {
|
||||||
|
Base64OutputStream::class.java.findRestrictedConstructor {
|
||||||
|
it.parameterTypes.size == 3 &&
|
||||||
|
it.parameterTypes[0] == OutputStream::class.java &&
|
||||||
|
it.parameterTypes[1] == Int::class.javaPrimitiveType &&
|
||||||
|
it.parameterTypes[2] == Boolean::class.javaPrimitiveType
|
||||||
|
} ?: throw Throwable("Failed to find Base64OutputStream constructor")
|
||||||
|
}
|
||||||
|
|
||||||
|
private val newBase64InputStream by lazy {
|
||||||
|
Base64InputStream::class.java.findRestrictedConstructor {
|
||||||
|
it.parameterTypes.size == 3 &&
|
||||||
|
it.parameterTypes[0] == InputStream::class.java &&
|
||||||
|
it.parameterTypes[1] == Int::class.javaPrimitiveType &&
|
||||||
|
it.parameterTypes[2] == Boolean::class.javaPrimitiveType
|
||||||
|
} ?: throw Throwable("Failed to find Base64InputStream constructor")
|
||||||
|
}
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
when (exportParams.exportFormat) {
|
when (exportParams.exportFormat) {
|
||||||
ExportFormat.TEXT -> {
|
ExportFormat.TEXT -> {
|
||||||
@ -129,8 +147,7 @@ class ConversationExporter(
|
|||||||
outputFileStream.write("<div class=\"media-$mediaKey\"><!-- ".toByteArray())
|
outputFileStream.write("<div class=\"media-$mediaKey\"><!-- ".toByteArray())
|
||||||
mediaFile.inputStream().use {
|
mediaFile.inputStream().use {
|
||||||
val deflateInputStream = DeflaterInputStream(it, Deflater(Deflater.BEST_SPEED, true))
|
val deflateInputStream = DeflaterInputStream(it, Deflater(Deflater.BEST_SPEED, true))
|
||||||
(XposedHelpers.newInstance(
|
(newBase64InputStream.newInstance(
|
||||||
Base64InputStream::class.java,
|
|
||||||
deflateInputStream,
|
deflateInputStream,
|
||||||
android.util.Base64.DEFAULT or android.util.Base64.NO_WRAP,
|
android.util.Base64.DEFAULT or android.util.Base64.NO_WRAP,
|
||||||
true
|
true
|
||||||
@ -252,8 +269,7 @@ class ConversationExporter(
|
|||||||
//write the json file
|
//write the json file
|
||||||
outputFileStream.write("<script type=\"application/json\" class=\"exported_content\">".toByteArray())
|
outputFileStream.write("<script type=\"application/json\" class=\"exported_content\">".toByteArray())
|
||||||
|
|
||||||
(XposedHelpers.newInstance(
|
(newBase64OutputStream.newInstance(
|
||||||
Base64OutputStream::class.java,
|
|
||||||
outputFileStream,
|
outputFileStream,
|
||||||
android.util.Base64.DEFAULT or android.util.Base64.NO_WRAP,
|
android.util.Base64.DEFAULT or android.util.Base64.NO_WRAP,
|
||||||
true
|
true
|
||||||
|
@ -4,6 +4,7 @@ import de.robv.android.xposed.XC_MethodHook
|
|||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import me.rhunk.snapenhance.common.logger.AbstractLogger
|
import me.rhunk.snapenhance.common.logger.AbstractLogger
|
||||||
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
import org.lsposed.hiddenapibypass.HiddenApiBypass
|
||||||
|
import java.lang.reflect.Constructor
|
||||||
import java.lang.reflect.Member
|
import java.lang.reflect.Member
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
@ -190,3 +191,9 @@ fun Class<*>.findRestrictedMethod(
|
|||||||
): Method? {
|
): Method? {
|
||||||
return declaredMethods.find(predicate) ?: HiddenApiBypass.getDeclaredMethods(this).filterIsInstance<Method>().find(predicate)
|
return declaredMethods.find(predicate) ?: HiddenApiBypass.getDeclaredMethods(this).filterIsInstance<Method>().find(predicate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Class<*>.findRestrictedConstructor(
|
||||||
|
predicate: (Constructor<*>) -> Boolean
|
||||||
|
): Constructor<*>? {
|
||||||
|
return declaredConstructors.find(predicate) ?: HiddenApiBypass.getDeclaredMethods(this).filterIsInstance<Constructor<*>>().find(predicate)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user