mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-24 06:10:09 +08:00
Support nested structures in desensitizer
This commit is contained in:
parent
82719d6018
commit
ec9ad7f0f1
@ -12,6 +12,10 @@ package net.mamoe.mirai.internal.network.protocol.data.jce
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.utils.io.JceStruct
|
||||
import net.mamoe.mirai.internal.utils.io.NestedStructure
|
||||
import net.mamoe.mirai.internal.utils.io.NestedStructureDesensitizer
|
||||
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
|
||||
import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
|
||||
import net.mamoe.mirai.utils.EMPTY_BYTE_ARRAY
|
||||
|
||||
@ -46,6 +50,7 @@ internal class MsgInfo(
|
||||
@TarsId(3) @JvmField val shMsgSeq: Short,
|
||||
@TarsId(4) @JvmField val strMsg: String?,
|
||||
@TarsId(5) @JvmField val uRealMsgTime: Int?,
|
||||
@param:NestedStructure(VMsgDesensitizationSerializer::class)
|
||||
@TarsId(6) @JvmField val vMsg: ByteArray,
|
||||
@TarsId(7) @JvmField val uAppShareID: Long?,
|
||||
@TarsId(8) @JvmField val vMsgCookies: ByteArray? = EMPTY_BYTE_ARRAY,
|
||||
@ -62,6 +67,15 @@ internal class MsgInfo(
|
||||
//@SerialId(19) @JvmField val stC2CTmpMsgHead: TempMsgHead?
|
||||
) : JceStruct
|
||||
|
||||
internal object VMsgDesensitizationSerializer : NestedStructureDesensitizer<MsgInfo, ProtocolStruct> {
|
||||
override fun deserialize(context: MsgInfo, byteArray: ByteArray): ProtocolStruct? {
|
||||
return when (context.shMsgType.toUShort().toInt()) {
|
||||
0x210 -> byteArray.loadAs(MsgType0x210.serializer())
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Serializable
|
||||
internal class ShareData(
|
||||
|
@ -9,6 +9,18 @@
|
||||
|
||||
package net.mamoe.mirai.internal.utils.io
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
internal interface ProtocolStruct
|
||||
internal interface ProtoBuf : ProtocolStruct
|
||||
internal interface JceStruct : ProtocolStruct
|
||||
internal interface JceStruct : ProtocolStruct
|
||||
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||
internal annotation class NestedStructure(
|
||||
val serializer: KClass<out NestedStructureDesensitizer<*, *>>
|
||||
)
|
||||
|
||||
internal interface NestedStructureDesensitizer<in C : ProtocolStruct, T : ProtocolStruct> {
|
||||
fun deserialize(context: C, byteArray: ByteArray): T?
|
||||
}
|
@ -11,11 +11,17 @@ package net.mamoe.mirai.internal.notice
|
||||
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.internal.notice.Desensitizer.Companion.generateAndDesensitize
|
||||
import net.mamoe.mirai.internal.utils.codegen.*
|
||||
import net.mamoe.mirai.internal.utils.io.NestedStructure
|
||||
import net.mamoe.mirai.internal.utils.io.NestedStructureDesensitizer
|
||||
import net.mamoe.mirai.internal.utils.io.ProtocolStruct
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlBuilder
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.createInstance
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
private val logger: MiraiLogger by lazy { MiraiLogger.Factory.create(Desensitizer::class) }
|
||||
@ -179,4 +185,20 @@ private class DesensitizationVisitor(
|
||||
desc.value = desensitizer.desensitize(desc.value as ByteArray)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any> visitClass(desc: ClassValueDesc<T>) {
|
||||
super.visitClass(desc)
|
||||
desc.properties.replaceAll() { key, value ->
|
||||
val annotation = key.findAnnotation<NestedStructure>()
|
||||
if (annotation != null && value.origin is ByteArray) {
|
||||
val instance = annotation.serializer.objectInstance ?: annotation.serializer.createInstance()
|
||||
|
||||
val result = instance.cast<NestedStructureDesensitizer<ProtocolStruct, ProtocolStruct>>()
|
||||
.deserialize(desc.origin as ProtocolStruct, value.origin as ByteArray)
|
||||
|
||||
val generate = ConstructorCallCodegenFacade.generateAndDesensitize(result)
|
||||
PlainValueDesc(desc, "$generate.toByteArray()", value.origin)
|
||||
} else value
|
||||
}
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ object ConstructorCallCodegenFacade {
|
||||
* Analyze [value] and give its correspondent [ValueDesc].
|
||||
*/
|
||||
fun analyze(value: Any?, type: KType): ValueDesc {
|
||||
if (value == null) return PlainValueDesc("null", null)
|
||||
if (value == null) return PlainValueDesc(null, "null", null)
|
||||
|
||||
val clazz = value::class
|
||||
|
||||
@ -43,14 +43,15 @@ object ConstructorCallCodegenFacade {
|
||||
prop.cast<KProperty1<Any, Any?>>()
|
||||
map[valueParameter] = analyze(prop.get(value), prop.returnType)
|
||||
}
|
||||
return ClassValueDesc(value, map)
|
||||
return ClassValueDesc(null, value, map)
|
||||
}
|
||||
|
||||
ArrayValueDesc.createOrNull(value, type)?.let { return it }
|
||||
ArrayValueDesc.createOrNull(value, type, null)?.let { return it }
|
||||
if (value is Collection<*>) {
|
||||
return CollectionValueDesc(value, arrayType = type, elementType = type.arguments.first().type!!)
|
||||
return CollectionValueDesc(null, value, arrayType = type, elementType = type.arguments.first().type!!)
|
||||
} else if (value is Map<*, *>) {
|
||||
return MapValueDesc(
|
||||
null,
|
||||
value.cast(),
|
||||
value.cast(),
|
||||
type,
|
||||
@ -61,12 +62,12 @@ object ConstructorCallCodegenFacade {
|
||||
|
||||
return when (value) {
|
||||
is CharSequence -> {
|
||||
PlainValueDesc('"' + value.toString() + '"', value)
|
||||
PlainValueDesc(null, '"' + value.toString() + '"', value)
|
||||
}
|
||||
is Char -> {
|
||||
PlainValueDesc("'$value'", value)
|
||||
PlainValueDesc(null, "'$value'", value)
|
||||
}
|
||||
else -> PlainValueDesc(value.toString(), value)
|
||||
else -> PlainValueDesc(null, value.toString(), value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,23 @@ import kotlin.reflect.typeOf
|
||||
|
||||
sealed interface ValueDesc {
|
||||
val origin: Any?
|
||||
val parent: ValueDesc?
|
||||
|
||||
fun accept(visitor: ValueDescVisitor)
|
||||
}
|
||||
|
||||
val ValueDesc.parents
|
||||
get() = sequence {
|
||||
var parent = parent
|
||||
do {
|
||||
parent ?: return@sequence
|
||||
yield(parent)
|
||||
parent = parent.parent
|
||||
} while (true);
|
||||
}
|
||||
|
||||
inline fun <reified T : ValueDesc> ValueDesc.findParent(): T? = parents.filterIsInstance<T>().firstOrNull()
|
||||
|
||||
sealed interface ArrayValueDesc : ValueDesc {
|
||||
val value: Any
|
||||
|
||||
@ -30,17 +43,27 @@ sealed interface ArrayValueDesc : ValueDesc {
|
||||
|
||||
companion object {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
fun createOrNull(array: Any, type: KType): ArrayValueDesc? {
|
||||
if (array is Array<*>) return ObjectArrayValueDesc(array, arrayType = type)
|
||||
fun createOrNull(array: Any, type: KType, parent: ValueDesc?): ArrayValueDesc? {
|
||||
if (array is Array<*>) return ObjectArrayValueDesc(parent, array, arrayType = type)
|
||||
return when (array) {
|
||||
is IntArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Int>())
|
||||
is ByteArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Byte>())
|
||||
is ShortArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Short>())
|
||||
is CharArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Char>())
|
||||
is LongArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Long>())
|
||||
is FloatArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Float>())
|
||||
is DoubleArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Double>())
|
||||
is BooleanArray -> PrimitiveArrayValueDesc(array, arrayType = type, elementType = typeOf<Boolean>())
|
||||
is IntArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Int>())
|
||||
is ByteArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Byte>())
|
||||
is ShortArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Short>())
|
||||
is CharArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Char>())
|
||||
is LongArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Long>())
|
||||
is FloatArray -> PrimitiveArrayValueDesc(parent, array, arrayType = type, elementType = typeOf<Float>())
|
||||
is DoubleArray -> PrimitiveArrayValueDesc(
|
||||
parent,
|
||||
array,
|
||||
arrayType = type,
|
||||
elementType = typeOf<Double>()
|
||||
)
|
||||
is BooleanArray -> PrimitiveArrayValueDesc(
|
||||
parent,
|
||||
array,
|
||||
arrayType = type,
|
||||
elementType = typeOf<Boolean>()
|
||||
)
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
@ -48,10 +71,11 @@ sealed interface ArrayValueDesc : ValueDesc {
|
||||
}
|
||||
|
||||
class ObjectArrayValueDesc(
|
||||
override val parent: ValueDesc?,
|
||||
override var value: Array<*>,
|
||||
override val origin: Array<*> = value,
|
||||
override val arrayType: KType,
|
||||
override val elementType: KType = arrayType.arguments.first().type ?: Any::class.createType()
|
||||
override val elementType: KType = arrayType.arguments.first().type ?: Any::class.createType(),
|
||||
) : ArrayValueDesc {
|
||||
override val elements: MutableList<ValueDesc> by lazy {
|
||||
value.mapTo(mutableListOf()) {
|
||||
@ -65,6 +89,7 @@ class ObjectArrayValueDesc(
|
||||
}
|
||||
|
||||
class CollectionValueDesc(
|
||||
override val parent: ValueDesc?,
|
||||
override var value: Collection<*>,
|
||||
override val origin: Collection<*> = value,
|
||||
override val arrayType: KType,
|
||||
@ -82,6 +107,7 @@ class CollectionValueDesc(
|
||||
}
|
||||
|
||||
class MapValueDesc(
|
||||
override val parent: ValueDesc?,
|
||||
var value: Map<Any?, Any?>,
|
||||
override val origin: Map<Any?, Any?> = value,
|
||||
val mapType: KType,
|
||||
@ -103,6 +129,7 @@ class MapValueDesc(
|
||||
}
|
||||
|
||||
class PrimitiveArrayValueDesc(
|
||||
override val parent: ValueDesc?,
|
||||
override var value: Any,
|
||||
override val origin: Any = value,
|
||||
override val arrayType: KType,
|
||||
@ -128,6 +155,7 @@ class PrimitiveArrayValueDesc(
|
||||
}
|
||||
|
||||
class PlainValueDesc(
|
||||
override val parent: ValueDesc?,
|
||||
var value: String,
|
||||
override val origin: Any?
|
||||
) : ValueDesc {
|
||||
@ -141,6 +169,7 @@ class PlainValueDesc(
|
||||
}
|
||||
|
||||
class ClassValueDesc<T : Any>(
|
||||
override val parent: ValueDesc?,
|
||||
override val origin: T,
|
||||
val properties: MutableMap<KParameter, ValueDesc>,
|
||||
) : ValueDesc {
|
||||
|
Loading…
Reference in New Issue
Block a user