burp-blazor/src/main/kotlin/Pack.kt

122 lines
3.2 KiB
Kotlin

package burp
import com.ensarsarajcic.kotlinx.serialization.msgpack.MsgPack
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer
var buffer = byteArrayOf()
@OptIn(ExperimentalSerializationApi::class)
val JSON = Json {
allowStructuredMapKeys = true
prettyPrint = true
prettyPrintIndent = " "
}
enum class MessageType {
Null, Invocation, StreamItem, Completion, StreamInvocation, CancelInvocation, Ping, Close
}
interface Message {
val raw: String
}
data class InvocationMessage(
val identifier: String?,
val method: String,
val arguments: List<String>,
val result: List<String>?,
override val raw: String
) : Message
data class CompletionMessage(
val identifier: String?, val num: Int, val extra: List<Any>, override val raw: String
) : Message
data class PingMessage(
val extra: List<Any>?, override val raw: String
) : Message
data class UnknownMessage(
val type: MessageType, val extra: List<Any>?, override val raw: String
) : Message
fun listToMessage(data: ArrayList<Any>, raw: String): Message {
return when (val type = MessageType.values()[(data[0] as Byte).toInt()]) {
MessageType.Invocation -> {
InvocationMessage(
identifier = data[2] as String?,
method = data[3] as String,
arguments = data[4] as List<String>,
result = if (data.size > 5) data[5] as List<String> else (null),
raw = raw
)
}
MessageType.Completion -> {
CompletionMessage(
identifier = data[2] as String?,
num = (data[3] as Byte).toInt(),
extra = data.slice(4 until data.size),
raw = raw
)
}
MessageType.Ping -> {
PingMessage(
extra = data.slice(1 until data.size), raw = raw
)
}
else -> {
UnknownMessage(
type = type, extra = data.slice(1 until data.size), raw = raw
)
}
}
}
fun decode(data: ByteArray): List<Message> {
var idx = 0
val messages = mutableListOf<Message>()
while (idx < data.size) {
var msgSize = 0
var shift = 0
while (true) {
val size = data[idx].toUByte().toInt()
idx++
msgSize += (size and 0x7F) shl shift
shift += 7
if (size < 0x80) {
break
}
}
val message = MsgPack.decodeFromByteArray(MsgPackSerializer, data.sliceArray(idx until idx + msgSize))
messages.add(listToMessage(message as ArrayList<Any>, JSON.encodeToString(MsgPackSerializer, message)))
idx += msgSize
}
return messages
}
fun encodeSize(packed: ByteArray): ByteArray {
var encodedSize = ByteArray(0)
var sz = packed.size
while (sz > 0) {
val s = sz and 0x7f
sz = sz shr 7
encodedSize += (if (sz > 0) s or 0x80 else s).toByte()
}
return encodedSize
}
fun encodeJson(input: String): ByteArray {
val packed = MsgPack.encodeToByteArray(Json.serializersModule.serializer(), input)
val size = encodeSize(packed)
return size + packed
}