From f4def5ef5825ab925768bd86f1839ea23a5f72f3 Mon Sep 17 00:00:00 2001 From: Him188 <Him188@mamoe.net> Date: Thu, 23 Jan 2020 19:58:44 +0800 Subject: [PATCH] Add tests for Jce --- mirai-debug/build.gradle.kts | 8 + .../src/test/java/jce/jce/HexUtil.java | 79 ++ .../test/java/jce/jce/JceDecodeException.java | 7 + .../test/java/jce/jce/JceEncodeException.java | 7 + .../java/jce/jce/JceInputStream$HeadData.java | 11 + .../src/test/java/jce/jce/JceInputStream.java | 1008 +++++++++++++++++ .../test/java/jce/jce/JceOutputStream.java | 430 +++++++ .../src/test/java/jce/jce/JceStruct.java | 78 ++ .../src/test/java/jce/jce/JceUtil.java | 594 ++++++++++ .../jce/jce/OnIllegalArgumentException.java | 7 + .../src/test/kotlin/jceTest/jceTest.kt | 293 +++++ 11 files changed, 2522 insertions(+) create mode 100644 mirai-debug/src/test/java/jce/jce/HexUtil.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceDecodeException.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceEncodeException.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceInputStream$HeadData.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceInputStream.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceOutputStream.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceStruct.java create mode 100644 mirai-debug/src/test/java/jce/jce/JceUtil.java create mode 100644 mirai-debug/src/test/java/jce/jce/OnIllegalArgumentException.java create mode 100644 mirai-debug/src/test/kotlin/jceTest/jceTest.kt diff --git a/mirai-debug/build.gradle.kts b/mirai-debug/build.gradle.kts index bb3c47204..98ae1f8bc 100644 --- a/mirai-debug/build.gradle.kts +++ b/mirai-debug/build.gradle.kts @@ -41,8 +41,11 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version" dependencies { + runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // IDE bug runtimeOnly(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug implementation(project(":mirai-core-timpc")) + runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main")) // IDE bug + implementation(project(":mirai-core-qqandroid")) // runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE implementation("org.bouncycastle:bcprov-jdk15on:1.64") @@ -70,4 +73,9 @@ dependencies { implementation(ktor("client-core", ktorVersion)) implementation(ktor("network", ktorVersion)) + testImplementation(kotlin("test-annotations-common")) + testImplementation(kotlin("test")) + testImplementation(kotlin("test-junit")) + testImplementation(kotlin("script-runtime")) + } \ No newline at end of file diff --git a/mirai-debug/src/test/java/jce/jce/HexUtil.java b/mirai-debug/src/test/java/jce/jce/HexUtil.java new file mode 100644 index 000000000..8a3e9b783 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/HexUtil.java @@ -0,0 +1,79 @@ +package jce.jce; + +import java.io.UnsupportedEncodingException; + +public class HexUtil { + private static final char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + public static final byte[] emptybytes = new byte[0]; + + public static String byte2HexStr(byte var0) { + char var1 = digits[var0 & 15]; + var0 = (byte) (var0 >>> 4); + return new String(new char[]{digits[var0 & 15], var1}); + } + + public static String bytes2HexStr(byte[] var0) { + if (var0 != null && var0.length != 0) { + char[] var3 = new char[var0.length * 2]; + + for (int var1 = 0; var1 < var0.length; ++var1) { + byte var2 = var0[var1]; + var3[var1 * 2 + 1] = digits[var2 & 15]; + var2 = (byte) (var2 >>> 4); + var3[var1 * 2 + 0] = digits[var2 & 15]; + } + + return new String(var3); + } else { + return null; + } + } + + public static byte char2Byte(char var0) { + if (var0 >= '0' && var0 <= '9') { + return (byte) (var0 - 48); + } else if (var0 >= 'a' && var0 <= 'f') { + return (byte) (var0 - 97 + 10); + } else { + return var0 >= 'A' && var0 <= 'F' ? (byte) (var0 - 65 + 10) : 0; + } + } + + public static byte hexStr2Byte(String var0) { + byte var2 = 0; + byte var1 = var2; + if (var0 != null) { + var1 = var2; + if (var0.length() == 1) { + var1 = char2Byte(var0.charAt(0)); + } + } + + return var1; + } + + public static byte[] hexStr2Bytes(String var0) { + if (var0 != null && !var0.equals("")) { + byte[] var4 = new byte[var0.length() / 2]; + + for (int var3 = 0; var3 < var4.length; ++var3) { + char var1 = var0.charAt(var3 * 2); + char var2 = var0.charAt(var3 * 2 + 1); + var4[var3] = (byte) (char2Byte(var1) * 16 + char2Byte(var2)); + } + + return var4; + } else { + return emptybytes; + } + } + + public static void main(String[] var0) { + try { + byte[] var2 = "Hello WebSocket World?".getBytes("gbk"); + System.out.println(bytes2HexStr(var2)); + } catch (UnsupportedEncodingException var1) { + var1.printStackTrace(); + } + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceDecodeException.java b/mirai-debug/src/test/java/jce/jce/JceDecodeException.java new file mode 100644 index 000000000..49c4bd5b7 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceDecodeException.java @@ -0,0 +1,7 @@ +package jce.jce; + +public class JceDecodeException extends RuntimeException { + public JceDecodeException(String var1) { + super(var1); + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceEncodeException.java b/mirai-debug/src/test/java/jce/jce/JceEncodeException.java new file mode 100644 index 000000000..40c7a5e11 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceEncodeException.java @@ -0,0 +1,7 @@ +package jce.jce; + +public class JceEncodeException extends RuntimeException { + public JceEncodeException(String var1) { + super(var1); + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceInputStream$HeadData.java b/mirai-debug/src/test/java/jce/jce/JceInputStream$HeadData.java new file mode 100644 index 000000000..df97f8166 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceInputStream$HeadData.java @@ -0,0 +1,11 @@ +package jce.jce; + +public class JceInputStream$HeadData { + public int tag; + public byte type; + + public void clear() { + this.type = 0; + this.tag = 0; + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceInputStream.java b/mirai-debug/src/test/java/jce/jce/JceInputStream.java new file mode 100644 index 000000000..bb7495b28 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceInputStream.java @@ -0,0 +1,1008 @@ +package jce.jce; + +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Array; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public final class JceInputStream { + // $FF: renamed from: bs java.nio.ByteBuffer + private ByteBuffer buffer; + protected String sServerEncoding = "GBK"; + + public JceInputStream() { + } + + public JceInputStream(ByteBuffer var1) { + this.buffer = var1; + } + + public JceInputStream(byte[] var1) { + this.buffer = ByteBuffer.wrap(var1); + } + + public JceInputStream(byte[] var1, int var2) { + this.buffer = ByteBuffer.wrap(var1); + this.buffer.position(var2); + } + + public static void main(String[] var0) { + } + + private int peakHead(JceInputStream$HeadData var1) { + return readHead(var1, this.buffer.duplicate()); + } + + private <T> T[] readArrayImpl(T var1, int var2, boolean var3) { + Object[] var7; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + if (var5.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + Object[] var6 = (Object[]) Array.newInstance(var1.getClass(), var4); + var2 = 0; + + while (true) { + var7 = var6; + if (var2 >= var4) { + return (T[]) var7; + } + + var6[var2] = this.read(var1, 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + var7 = null; + return (T[]) var7; + } + } + + public static int readHead(JceInputStream$HeadData var0, ByteBuffer var1) { + byte var2 = var1.get(); + var0.type = (byte) (var2 & 15); + var0.tag = (var2 & 240) >> 4; + if (var0.tag == 15) { + var0.tag = var1.get() & 255; + return 2; + } else { + return 1; + } + } + + private <K, V> Map<K, V> readMap(Map<K, V> var1, Map<K, V> var2, int var3, boolean var4) { + Map<K, V> var8; + if (var2 != null && !var2.isEmpty()) { + Entry<K, V> var9 = var2.entrySet().iterator().next(); + K var6 = var9.getKey(); + V var7 = var9.getValue(); + if (this.skipToTag(var3)) { + JceInputStream$HeadData var10 = new JceInputStream$HeadData(); + this.readHead(var10); + if (var10.type == 8) { + int var5 = this.read(0, 0, true); + if (var5 < 0) { + throw new JceDecodeException("size invalid: " + var5); + } + + var3 = 0; + + while (true) { + var8 = var1; + if (var3 >= var5) { + return var8; + } + + var1.put((K) this.read(var6, 0, true), (V) this.read(var7, 1, true)); + ++var3; + } + } + throw new JceDecodeException("type mismatch."); + } else { + var8 = var1; + if (var4) { + throw new JceDecodeException("require field not exist."); + } + } + } else { + var8 = new HashMap<>(); + } + + return var8; + } + + private void skip(int var1) { + this.buffer.position(this.buffer.position() + var1); + } + + private void skipField() { + JceInputStream$HeadData var1 = new JceInputStream$HeadData(); + this.readHead(var1); + this.skipField(var1.type); + } + + private void skipField(byte var1) { + byte var3 = 0; + byte var2 = 0; + int var5; + switch (var1) { + case 0: + this.skip(1); + break; + case 1: + this.skip(2); + return; + case 2: + this.skip(4); + return; + case 3: + this.skip(8); + return; + case 4: + this.skip(4); + return; + case 5: + this.skip(8); + return; + case 6: + byte var7 = this.buffer.get(); + var5 = var7; + if (var7 < 0) { + var5 = var7 + 256; + } + + this.skip(var5); + return; + case 7: + this.skip(this.buffer.getInt()); + return; + case 8: + int var8 = this.read(0, 0, true); + + for (var5 = var2; var5 < var8 * 2; ++var5) { + this.skipField(); + } + + return; + case 9: + int var6 = this.read(0, 0, true); + + for (var5 = var3; var5 < var6; ++var5) { + this.skipField(); + } + + return; + case 10: + this.skipToStructEnd(); + return; + case 11: + case 12: + break; + case 13: + JceInputStream$HeadData var4 = new JceInputStream$HeadData(); + this.readHead(var4); + if (var4.type != 0) { + throw new JceDecodeException("skipField with invalid type, type value: " + var1 + ", " + var4.type); + } + + this.skip(this.read(0, 0, true)); + return; + default: + throw new JceDecodeException("invalid type."); + } + + } + + public JceStruct directRead(JceStruct var1, int var2, boolean var3) { + JceInputStream$HeadData var4 = null; + if (this.skipToTag(var2)) { + try { + var1 = var1.newInit(); + } catch (Exception var5) { + throw new JceDecodeException(var5.getMessage()); + } + + var4 = new JceInputStream$HeadData(); + this.readHead(var4); + if (var4.type != 10) { + throw new JceDecodeException("type mismatch."); + } + + var1.readFrom(this); + this.skipToStructEnd(); + } else { + var1 = null; + if (var3) { + throw new JceDecodeException("require field not exist."); + } + } + + return var1; + } + + public ByteBuffer getBs() { + return this.buffer; + } + + public byte read(byte var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var4 = new JceInputStream$HeadData(); + this.readHead(var4); + switch (var4.type) { + case 0: + return this.buffer.get(); + case 12: + return 0; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public double read(double var1, int var3, boolean var4) { + if (this.skipToTag(var3)) { + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + switch (var5.type) { + case 4: + return this.buffer.getFloat(); + case 5: + return this.buffer.getDouble(); + case 12: + return 0.0D; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var4) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public float read(float var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var4 = new JceInputStream$HeadData(); + this.readHead(var4); + switch (var4.type) { + case 4: + return this.buffer.getFloat(); + case 12: + return 0.0F; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public int read(int var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var4 = new JceInputStream$HeadData(); + this.readHead(var4); + switch (var4.type) { + case 0: + return this.buffer.get(); + case 1: + return this.buffer.getShort(); + case 2: + return this.buffer.getInt(); + case 12: + return 0; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public long read(long var1, int var3, boolean var4) { + if (this.skipToTag(var3)) { + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + switch (var5.type) { + case 0: + return this.buffer.get(); + case 1: + return this.buffer.getShort(); + case 2: + return this.buffer.getInt(); + case 3: + return this.buffer.getLong(); + case 12: + return 0L; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var4) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public JceStruct read(JceStruct var1, int var2, boolean var3) { + JceInputStream$HeadData var4 = null; + if (this.skipToTag(var2)) { + try { + var1 = var1.getClass().newInstance(); + } catch (Exception var5) { + throw new JceDecodeException(var5.getMessage()); + } + + var4 = new JceInputStream$HeadData(); + this.readHead(var4); + if (var4.type != 10) { + throw new JceDecodeException("type mismatch."); + } + + var1.readFrom(this); + this.skipToStructEnd(); + } else { + var1 = null; + if (var3) { + throw new JceDecodeException("require field not exist."); + } + } + + return var1; + } + + public <T> Object read(T var1, int var2, boolean var3) { + if (var1 instanceof Byte) { + return this.read((byte) 0, var2, var3); + } else if (var1 instanceof Boolean) { + return this.read(false, var2, var3); + } else if (var1 instanceof Short) { + return this.read((short) 0, var2, var3); + } else if (var1 instanceof Integer) { + return this.read(0, var2, var3); + } else if (var1 instanceof Long) { + return this.read(0L, var2, var3); + } else if (var1 instanceof Float) { + return this.read(0.0F, var2, var3); + } else if (var1 instanceof Double) { + return this.read(0.0D, var2, var3); + } else if (var1 instanceof String) { + return this.readString(var2, var3); + } else if (var1 instanceof Map) { + return this.readMap((Map) var1, var2, var3); + } else if (var1 instanceof List) { + return this.readArray((List) var1, var2, var3); + } else if (var1 instanceof JceStruct) { + return this.read((JceStruct) var1, var2, var3); + } else if (var1.getClass().isArray()) { + if (!(var1 instanceof byte[]) && !(var1 instanceof Byte[])) { + if (var1 instanceof boolean[]) { + return this.read((boolean[]) null, var2, var3); + } else if (var1 instanceof short[]) { + return this.read((short[]) null, var2, var3); + } else if (var1 instanceof int[]) { + return this.read((int[]) null, var2, var3); + } else if (var1 instanceof long[]) { + return this.read((long[]) null, var2, var3); + } else if (var1 instanceof float[]) { + return this.read((float[]) null, var2, var3); + } else { + return var1 instanceof double[] ? this.read((double[]) null, var2, var3) : this.readArray((Object[]) var1, var2, var3); + } + } else { + return this.read((byte[]) null, var2, var3); + } + } else { + throw new JceDecodeException("read object error: unsupport type."); + } + } + + public String read(String var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var8 = new JceInputStream$HeadData(); + this.readHead(var8); + String var5; + byte[] var9; + switch (var8.type) { + case 6: + byte var4 = this.buffer.get(); + var2 = var4; + if (var4 < 0) { + var2 = var4 + 256; + } + + var9 = new byte[var2]; + this.buffer.get(var9); + + try { + var5 = new String(var9, this.sServerEncoding); + return var5; + } catch (UnsupportedEncodingException var7) { + return new String(var9); + } + case 7: + var2 = this.buffer.getInt(); + if (var2 <= 104857600 && var2 >= 0 && var2 <= this.buffer.capacity()) { + var9 = new byte[var2]; + this.buffer.get(var9); + + try { + var5 = new String(var9, this.sServerEncoding); + return var5; + } catch (UnsupportedEncodingException var6) { + return new String(var9); + } + } + + throw new JceDecodeException("String too long: " + var2); + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public short read(short var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var4 = new JceInputStream$HeadData(); + this.readHead(var4); + switch (var4.type) { + case 0: + return this.buffer.get(); + case 1: + return this.buffer.getShort(); + case 12: + return 0; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public boolean read(boolean var1, int var2, boolean var3) { + var1 = this.read((byte) 0, var2, var3) != 0; + + return var1; + } + + public byte[] read(byte[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + int var4; + switch (var6.type) { + case 9: + var4 = this.read(0, 0, true); + if (var4 >= 0 && var4 <= this.buffer.capacity()) { + byte[] var7 = new byte[var4]; + var2 = 0; + + while (true) { + var1 = var7; + if (var2 >= var4) { + return var1; + } + + var7[var2] = this.read(var7[0], 0, true); + ++var2; + } + } + + throw new JceDecodeException("size invalid: " + var4); + case 13: + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + if (var5.type != 0) { + throw new JceDecodeException("type mismatch, tag: " + var2 + ", type: " + var6.type + ", " + var5.type); + } + + var4 = this.read(0, 0, true); + if (var4 < 0 || var4 > this.buffer.capacity()) { + throw new JceDecodeException("invalid size, tag: " + var2 + ", type: " + var6.type + ", " + var5.type + ", size: " + var4); + } + + var1 = new byte[var4]; + this.buffer.get(var1); + break; + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } + + return var1; + } + + public double[] read(double[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + double[] var5 = new double[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public float[] read(float[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + float[] var5 = new float[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public int[] read(int[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + int[] var5 = new int[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public long[] read(long[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + long[] var5 = new long[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public JceStruct[] read(JceStruct[] var1, int var2, boolean var3) { + return (JceStruct[]) this.readArray((Object[]) var1, var2, var3); + } + + public String[] read(String[] var1, int var2, boolean var3) { + return (String[]) this.readArray((Object[]) var1, var2, var3); + } + + public short[] read(short[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + short[] var5 = new short[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public boolean[] read(boolean[] var1, int var2, boolean var3) { + var1 = null; + if (this.skipToTag(var2)) { + JceInputStream$HeadData var6 = new JceInputStream$HeadData(); + this.readHead(var6); + if (var6.type == 9) { + int var4 = this.read(0, 0, true); + if (var4 < 0) { + throw new JceDecodeException("size invalid: " + var4); + } else { + boolean[] var5 = new boolean[var4]; + var2 = 0; + + while (true) { + var1 = var5; + if (var2 >= var4) { + return var1; + } + + var5[var2] = this.read(var5[0], 0, true); + ++var2; + } + } + } + throw new JceDecodeException("type mismatch."); + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public <T> List<T> readArray(List<T> var1, int var2, boolean var3) { + byte var4 = 0; + if (var1 != null && !var1.isEmpty()) { + Object[] var6 = this.readArrayImpl(var1.get(0), var2, var3); + if (var6 == null) { + return null; + } else { + ArrayList var5 = new ArrayList(); + + for (var2 = var4; var2 < var6.length; ++var2) { + var5.add(var6[var2]); + } + + return var5; + } + } else { + return new ArrayList<>(); + } + } + + public <T> T[] readArray(T[] var1, int var2, boolean var3) { + if (var1 != null && var1.length != 0) { + return this.readArrayImpl(var1[0], var2, var3); + } else { + throw new JceDecodeException("unable to get type of key and value."); + } + } + + public String readByteString(String var1, int var2, boolean var3) { + if (this.skipToTag(var2)) { + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + byte[] var6; + switch (var5.type) { + case 6: + byte var4 = this.buffer.get(); + var2 = var4; + if (var4 < 0) { + var2 = var4 + 256; + } + + var6 = new byte[var2]; + this.buffer.get(var6); + return HexUtil.bytes2HexStr(var6); + case 7: + var2 = this.buffer.getInt(); + if (var2 <= 104857600 && var2 >= 0 && var2 <= this.buffer.capacity()) { + var6 = new byte[var2]; + this.buffer.get(var6); + return HexUtil.bytes2HexStr(var6); + } + + throw new JceDecodeException("String too long: " + var2); + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var3) { + throw new JceDecodeException("require field not exist."); + } else { + return var1; + } + } + + public void readHead(JceInputStream$HeadData var1) { + readHead(var1, this.buffer); + } + + public List<java.io.Serializable> readList(int var1, boolean var2) { + ArrayList<java.io.Serializable> var6 = new ArrayList<java.io.Serializable>(); + if (this.skipToTag(var1)) { + JceInputStream$HeadData var7 = new JceInputStream$HeadData(); + this.readHead(var7); + if (var7.type == 9) { + int var5 = this.read(0, 0, true); + if (var5 < 0) { + throw new JceDecodeException("size invalid: " + var5); + } + + var1 = 0; + + for (; var1 < var5; ++var1) { + var7 = new JceInputStream$HeadData(); + this.readHead(var7); + switch (var7.type) { + case 0: + this.skip(1); + break; + case 1: + this.skip(2); + break; + case 2: + this.skip(4); + break; + case 3: + this.skip(8); + break; + case 4: + this.skip(4); + break; + case 5: + this.skip(8); + break; + case 6: + byte var4 = this.buffer.get(); + int var3 = var4; + if (var4 < 0) { + var3 = var4 + 256; + } + + this.skip(var3); + break; + case 7: + this.skip(this.buffer.getInt()); + case 8: + case 9: + break; + case 10: + try { + JceStruct var9 = (JceStruct) Class.forName(JceStruct.class.getName()).getConstructor().newInstance(); + var9.readFrom(this); + this.skipToStructEnd(); + var6.add(var9); + break; + } catch (Exception var8) { + var8.printStackTrace(); + throw new JceDecodeException("type mismatch." + var8); + } + case 11: + default: + throw new JceDecodeException("type mismatch."); + case 12: + var6.add(new Integer(0)); + } + } + } else { + throw new JceDecodeException("type mismatch."); + } + } else if (var2) { + throw new JceDecodeException("require field not exist."); + } + + return var6; + } + + public <K, V> HashMap<K, V> readMap(Map<K, V> var1, int var2, boolean var3) { + return (HashMap<K, V>) this.readMap(new HashMap<K, V>(), var1, var2, var3); + } + + public String readString(int var1, boolean var2) { + String var4 = null; + if (this.skipToTag(var1)) { + JceInputStream$HeadData var8 = new JceInputStream$HeadData(); + this.readHead(var8); + switch (var8.type) { + case 6: + byte var3 = this.buffer.get(); + var1 = var3; + if (var3 < 0) { + var1 = var3 + 256; + } + + byte[] var10 = new byte[var1]; + this.buffer.get(var10); + + try { + var4 = new String(var10, this.sServerEncoding); + break; + } catch (UnsupportedEncodingException var7) { + return new String(var10); + } + case 7: + var1 = this.buffer.getInt(); + if (var1 <= 104857600 && var1 >= 0 && var1 <= this.buffer.capacity()) { + byte[] var9 = new byte[var1]; + this.buffer.get(var9); + + try { + String var5 = new String(var9, this.sServerEncoding); + return var5; + } catch (UnsupportedEncodingException var6) { + return new String(var9); + } + } + + throw new JceDecodeException("String too long: " + var1); + default: + throw new JceDecodeException("type mismatch."); + } + } else if (var2) { + throw new JceDecodeException("require field not exist."); + } + + return var4; + } + + public Map<String, String> readStringMap(int var1, boolean var2) { + HashMap<String, String> var4 = new HashMap<>(); + if (this.skipToTag(var1)) { + JceInputStream$HeadData var5 = new JceInputStream$HeadData(); + this.readHead(var5); + if (var5.type == 8) { + int var3 = this.read(0, 0, true); + if (var3 < 0) { + throw new JceDecodeException("size invalid: " + var3); + } + + for (var1 = 0; var1 < var3; ++var1) { + var4.put(this.readString(0, true), this.readString(1, true)); + } + } else { + throw new JceDecodeException("type mismatch."); + } + } else if (var2) { + throw new JceDecodeException("require field not exist."); + } + + return var4; + } + + public int setServerEncoding(String var1) { + this.sServerEncoding = var1; + return 0; + } + + public void skipToStructEnd() { + JceInputStream$HeadData var1 = new JceInputStream$HeadData(); + + do { + this.readHead(var1); + this.skipField(var1.type); + } while (var1.type != 11); + + } + + public boolean skipToTag(int n2) { + try { + JceInputStream$HeadData jceInputStream$HeadData = new JceInputStream$HeadData(); + do { + int n3 = this.peakHead(jceInputStream$HeadData); + if (jceInputStream$HeadData.type == 11) { + return false; + } + if (n2 <= jceInputStream$HeadData.tag) { + return n2 == jceInputStream$HeadData.tag; + } + this.skip(n3); + this.skipField(jceInputStream$HeadData.type); + } while (true); + } catch (JceDecodeException jceDecodeException) { + return false; + } catch (BufferUnderflowException bufferUnderflowException) { + // empty catch block + } + return false; + } + + public void warp(byte[] var1) { + this.wrap(var1); + } + + public void wrap(byte[] var1) { + this.buffer = ByteBuffer.wrap(var1); + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceOutputStream.java b/mirai-debug/src/test/java/jce/jce/JceOutputStream.java new file mode 100644 index 000000000..7a2a24202 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceOutputStream.java @@ -0,0 +1,430 @@ +package jce.jce; + +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +public class JceOutputStream { + // $FF: renamed from: bs java.nio.ByteBuffer + private ByteBuffer field_80728; + private OnIllegalArgumentException exceptionHandler; + protected String sServerEncoding; + + public JceOutputStream() { + this(128); + } + + public JceOutputStream(int var1) { + this.sServerEncoding = "GBK"; + this.field_80728 = ByteBuffer.allocate(var1); + } + + public JceOutputStream(ByteBuffer var1) { + this.sServerEncoding = "GBK"; + this.field_80728 = var1; + } + + public static void main(String[] var0) { + JceOutputStream var2 = new JceOutputStream(); + var2.write(1311768467283714885L, 0); + ByteBuffer var1 = var2.getByteBuffer(); + System.out.println(HexUtil.bytes2HexStr(var1.array())); + System.out.println(Arrays.toString(var2.toByteArray())); + } + + private void writeArray(Object[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public ByteBuffer getByteBuffer() { + return this.field_80728; + } + + public OnIllegalArgumentException getExceptionHandler() { + return this.exceptionHandler; + } + + public void reserve(int var1) { + if (this.field_80728.remaining() < var1) { + int var2 = (this.field_80728.capacity() + var1) * 2; + + ByteBuffer var3; + try { + var3 = ByteBuffer.allocate(var2); + var3.put(this.field_80728.array(), 0, this.field_80728.position()); + } catch (IllegalArgumentException var4) { + if (this.exceptionHandler != null) { + this.exceptionHandler.onException(var4, this.field_80728, var1, var2); + } + + throw var4; + } + + this.field_80728 = var3; + } + + } + + public void setExceptionHandler(OnIllegalArgumentException var1) { + this.exceptionHandler = var1; + } + + public int setServerEncoding(String var1) { + this.sServerEncoding = var1; + return 0; + } + + public byte[] toByteArray() { + byte[] var1 = new byte[this.field_80728.position()]; + System.arraycopy(this.field_80728.array(), 0, var1, 0, this.field_80728.position()); + return var1; + } + + public void write(byte var1, int var2) { + this.reserve(3); + if (var1 == 0) { + this.writeHead((byte) 12, var2); + } else { + this.writeHead((byte) 0, var2); + this.field_80728.put(var1); + } + } + + public void write(double var1, int var3) { + this.reserve(10); + this.writeHead((byte) 5, var3); + this.field_80728.putDouble(var1); + } + + public void write(float var1, int var2) { + this.reserve(6); + this.writeHead((byte) 4, var2); + this.field_80728.putFloat(var1); + } + + public void write(int var1, int var2) { + this.reserve(6); + if (var1 >= -32768 && var1 <= 32767) { + this.write((short) var1, var2); + } else { + this.writeHead((byte) 2, var2); + this.field_80728.putInt(var1); + } + } + + public void write(long var1, int id) { + this.reserve(10); + if (var1 >= -2147483648L && var1 <= 2147483647L) { + this.write((int) var1, id); + } else { + this.writeHead((byte) 3, id); + this.field_80728.putLong(var1); + } + } + + public void write(JceStruct var1, int var2) { + this.reserve(2); + this.writeHead((byte) 10, var2); + var1.writeTo(this); + this.reserve(2); + this.writeHead((byte) 11, 0); + } + + public void write(Boolean var1, int var2) { + this.write((boolean) var1, var2); + } + + public void write(Byte var1, int var2) { + this.write((byte) var1, var2); + } + + public void write(Double var1, int var2) { + this.write((double) var1, var2); + } + + public void write(Float var1, int var2) { + this.write((float) var1, var2); + } + + public void write(Integer var1, int var2) { + this.write((int) var1, var2); + } + + public void write(Long var1, int var2) { + this.write((long) var1, var2); + } + + public void write(Object var1, int var2) { + if (var1 instanceof Byte) { + this.write((Byte) var1, var2); + } else if (var1 instanceof Boolean) { + this.write((Boolean) var1, var2); + } else if (var1 instanceof Short) { + this.write((Short) var1, var2); + } else if (var1 instanceof Integer) { + this.write((Integer) var1, var2); + } else if (var1 instanceof Long) { + this.write((Long) var1, var2); + } else if (var1 instanceof Float) { + this.write((Float) var1, var2); + } else if (var1 instanceof Double) { + this.write((Double) var1, var2); + } else if (var1 instanceof String) { + this.write((String) var1, var2); + } else if (var1 instanceof Map) { + this.write((Map) var1, var2); + } else if (var1 instanceof List) { + this.write((List) var1, var2); + } else if (var1 instanceof JceStruct) { + this.write((JceStruct) var1, var2); + } else if (var1 instanceof byte[]) { + this.write((byte[]) var1, var2); + } else if (var1 instanceof boolean[]) { + this.write((boolean[]) var1, var2); + } else if (var1 instanceof short[]) { + this.write((short[]) var1, var2); + } else if (var1 instanceof int[]) { + this.write((int[]) var1, var2); + } else if (var1 instanceof long[]) { + this.write((long[]) var1, var2); + } else if (var1 instanceof float[]) { + this.write((float[]) var1, var2); + } else if (var1 instanceof double[]) { + this.write((double[]) var1, var2); + } else if (var1.getClass().isArray()) { + this.writeArray((Object[]) var1, var2); + } else if (var1 instanceof Collection) { + this.write((Collection) var1, var2); + } else { + throw new JceEncodeException("write object error: unsupport type. " + var1.getClass()); + } + } + + public void write(Short var1, int var2) { + this.write((short) var1, var2); + } + + public void write(String var1, int var2) { + byte[] var5; + label16: + { + byte[] var3; + try { + var3 = var1.getBytes(this.sServerEncoding); + } catch (UnsupportedEncodingException var4) { + var5 = var1.getBytes(); + break label16; + } + + var5 = var3; + } + + this.reserve(var5.length + 10); + if (var5.length > 255) { + this.writeHead((byte) 7, var2); + this.field_80728.putInt(var5.length); + } else { + this.writeHead((byte) 6, var2); + this.field_80728.put((byte) var5.length); + } + this.field_80728.put(var5); + } + + public <T> void write(Collection<T> var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + if (var1 == null) { + var2 = 0; + } else { + var2 = var1.size(); + } + + this.write(var2, 0); + if (var1 != null) { + + for (T t : var1) { + this.write(t, 0); + } + } + + } + + public <K, V> void write(Map<K, V> var1, int var2) { + this.reserve(8); + this.writeHead((byte) 8, var2); + if (var1 == null) { + var2 = 0; + } else { + var2 = var1.size(); + } + + this.write(var2, 0); + if (var1 != null) { + + for (Entry<K, V> kvEntry : var1.entrySet()) { + this.write(((Entry) kvEntry).getKey(), 0); + this.write(((Entry) kvEntry).getValue(), 1); + } + } + + } + + public void write(short var1, int var2) { + this.reserve(4); + if (var1 >= -128 && var1 <= 127) { + this.write((byte) var1, var2); + } else { + this.writeHead((byte) 1, var2); + this.field_80728.putShort(var1); + } + } + + public void write(boolean var1, int var2) { + byte var3; + if (var1) { + var3 = 1; + } else { + var3 = 0; + } + + this.write(var3, var2); + } + + public void write(byte[] var1, int var2) { + this.reserve(var1.length + 8); + this.writeHead((byte) 13, var2); + this.writeHead((byte) 0, 0); + this.write(var1.length, 0); + this.field_80728.put(var1); + } + + public void write(double[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public void write(float[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public void write(int[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public void write(long[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public <T> void write(T[] var1, int var2) { + this.writeArray(var1, var2); + } + + public void write(short[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public void write(boolean[] var1, int var2) { + this.reserve(8); + this.writeHead((byte) 9, var2); + this.write(var1.length, 0); + int var3 = var1.length; + + for (var2 = 0; var2 < var3; ++var2) { + this.write(var1[var2], 0); + } + + } + + public void writeByteString(String var1, int var2) { + this.reserve(var1.length() + 10); + byte[] var3 = HexUtil.hexStr2Bytes(var1); + if (var3.length > 255) { + this.writeHead((byte) 7, var2); + this.field_80728.putInt(var3.length); + this.field_80728.put(var3); + } else { + this.writeHead((byte) 6, var2); + this.field_80728.put((byte) var3.length); + this.field_80728.put(var3); + } + } + + public void writeHead(byte var1, int var2) { + byte var3; + if (var2 < 15) { + var3 = (byte) (var2 << 4 | var1); + this.field_80728.put(var3); + } else if (var2 < 256) { + var3 = (byte) (var1 | 240); + this.field_80728.put(var3); + this.field_80728.put((byte) var2); + } else { + throw new JceEncodeException("tag is too large: " + var2); + } + } + + public void writeStringByte(String var1, int var2) { + byte[] var3 = HexUtil.hexStr2Bytes(var1); + this.reserve(var3.length + 10); + if (var3.length > 255) { + this.writeHead((byte) 7, var2); + this.field_80728.putInt(var3.length); + this.field_80728.put(var3); + } else { + this.writeHead((byte) 6, var2); + this.field_80728.put((byte) var3.length); + this.field_80728.put(var3); + } + } +} diff --git a/mirai-debug/src/test/java/jce/jce/JceStruct.java b/mirai-debug/src/test/java/jce/jce/JceStruct.java new file mode 100644 index 000000000..9c32025d6 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceStruct.java @@ -0,0 +1,78 @@ +package jce.jce; + +import java.io.Serializable; + +public abstract class JceStruct implements Serializable { + public static final byte BYTE = 0; + public static final byte DOUBLE = 5; + public static final byte FLOAT = 4; + public static final byte INT = 2; + public static final int JCE_MAX_STRING_LENGTH = 104857600; + public static final byte LIST = 9; + public static final byte LONG = 3; + public static final byte MAP = 8; + public static final byte SHORT = 1; + public static final byte SIMPLE_LIST = 13; + public static final byte STRING1 = 6; + public static final byte STRING4 = 7; + public static final byte STRUCT_BEGIN = 10; + public static final byte STRUCT_END = 11; + public static final byte ZERO_TAG = 12; + + public static String toDisplaySimpleString(JceStruct var0) { + if (var0 == null) { + return null; + } else { + StringBuilder var1 = new StringBuilder(); + var0.displaySimple(var1, 0); + return var1.toString(); + } + } + + public boolean containField(String var1) { + return false; + } + + public void display(StringBuilder var1, int var2) { + } + + public void displaySimple(StringBuilder var1, int var2) { + } + + public Object getFieldByName(String var1) { + return null; + } + + public JceStruct newInit() { + return null; + } + + public abstract void readFrom(JceInputStream var1); + + public void recyle() { + } + + public void setFieldByName(String var1, Object var2) { + } + + public byte[] toByteArray() { + JceOutputStream var1 = new JceOutputStream(); + this.writeTo(var1); + return var1.toByteArray(); + } + + public byte[] toByteArray(String var1) { + JceOutputStream var2 = new JceOutputStream(); + var2.setServerEncoding(var1); + this.writeTo(var2); + return var2.toByteArray(); + } + + public String toString() { + StringBuilder var1 = new StringBuilder(); + this.display(var1, 0); + return var1.toString(); + } + + public abstract void writeTo(JceOutputStream var1); +} diff --git a/mirai-debug/src/test/java/jce/jce/JceUtil.java b/mirai-debug/src/test/java/jce/jce/JceUtil.java new file mode 100644 index 000000000..a41763e75 --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/JceUtil.java @@ -0,0 +1,594 @@ +package jce.jce; + +import java.nio.ByteBuffer; +import java.util.Iterator; +import java.util.List; + +public final class JceUtil { + private static final byte[] highDigits; + private static final int iConstant = 37; + private static final int iTotal = 17; + private static final byte[] lowDigits; + + static { + byte[] var1 = new byte[]{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70}; + byte[] var2 = new byte[256]; + byte[] var3 = new byte[256]; + + for (int var0 = 0; var0 < 256; ++var0) { + var2[var0] = var1[var0 >>> 4]; + var3[var0] = var1[var0 & 15]; + } + + highDigits = var2; + lowDigits = var3; + } + + public static int compareTo(byte var0, byte var1) { + if (var0 < var1) { + return -1; + } else { + return var0 > var1 ? 1 : 0; + } + } + + public static int compareTo(char var0, char var1) { + if (var0 < var1) { + return -1; + } else { + return var0 > var1 ? 1 : 0; + } + } + + public static int compareTo(double var0, double var2) { + if (var0 < var2) { + return -1; + } else { + return var0 > var2 ? 1 : 0; + } + } + + public static int compareTo(float var0, float var1) { + if (var0 < var1) { + return -1; + } else { + return var0 > var1 ? 1 : 0; + } + } + + public static int compareTo(int var0, int var1) { + if (var0 < var1) { + return -1; + } else { + return var0 > var1 ? 1 : 0; + } + } + + public static int compareTo(long var0, long var2) { + if (var0 < var2) { + return -1; + } else { + return var0 > var2 ? 1 : 0; + } + } + + public static <T extends Comparable<T>> int compareTo(T var0, T var1) { + return var0.compareTo(var1); + } + + public static <T extends Comparable<T>> int compareTo(List<T> var0, List<T> var1) { + Iterator var3 = var0.iterator(); + Iterator var4 = var1.iterator(); + + while (var3.hasNext() && var4.hasNext()) { + int var2 = ((Comparable) var3.next()).compareTo(var4.next()); + if (var2 != 0) { + return var2; + } + } + + return compareTo(var3.hasNext(), var4.hasNext()); + } + + public static int compareTo(short var0, short var1) { + if (var0 < var1) { + return -1; + } else { + return var0 > var1 ? 1 : 0; + } + } + + public static int compareTo(boolean var0, boolean var1) { + byte var3 = 1; + byte var2; + if (var0) { + var2 = 1; + } else { + var2 = 0; + } + + if (!var1) { + var3 = 0; + } + + return var2 - var3; + } + + public static int compareTo(byte[] var0, byte[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(char[] var0, char[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(double[] var0, double[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(float[] var0, float[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(int[] var0, int[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(long[] var0, long[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static <T extends Comparable<T>> int compareTo(T[] var0, T[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = var0[var2].compareTo(var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(short[] var0, short[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static int compareTo(boolean[] var0, boolean[] var1) { + int var3 = 0; + + for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) { + int var4 = compareTo(var0[var2], var1[var3]); + if (var4 != 0) { + return var4; + } + + ++var3; + } + + return compareTo(var0.length, var1.length); + } + + public static boolean equals(byte var0, byte var1) { + return var0 == var1; + } + + public static boolean equals(char var0, char var1) { + return var0 == var1; + } + + public static boolean equals(double var0, double var2) { + return var0 == var2; + } + + public static boolean equals(float var0, float var1) { + return var0 == var1; + } + + public static boolean equals(int var0, int var1) { + return var0 == var1; + } + + public static boolean equals(long var0, long var2) { + return var0 == var2; + } + + public static boolean equals(Object var0, Object var1) { + return var0.equals(var1); + } + + public static boolean equals(short var0, short var1) { + return var0 == var1; + } + + public static boolean equals(boolean var0, boolean var1) { + return var0 == var1; + } + + public static String getHexdump(ByteBuffer var0) { + int var1 = var0.remaining(); + if (var1 == 0) { + return "empty"; + } else { + StringBuffer var4 = new StringBuffer(var0.remaining() * 3 - 1); + int var2 = var0.position(); + int var3 = var0.get() & 255; + var4.append((char) highDigits[var3]); + var4.append((char) lowDigits[var3]); + --var1; + + while (var1 > 0) { + var4.append(' '); + var3 = var0.get() & 255; + var4.append((char) highDigits[var3]); + var4.append((char) lowDigits[var3]); + --var1; + } + + var0.position(var2); + return var4.toString(); + } + } + + public static String getHexdump(byte[] var0) { + return getHexdump(ByteBuffer.wrap(var0)); + } + + public static byte[] getJceBufArray(ByteBuffer var0) { + byte[] var1 = new byte[var0.position()]; + System.arraycopy(var0.array(), 0, var1, 0, var1.length); + return var1; + } + + public static int hashCode(byte var0) { + return var0 + 629; + } + + public static int hashCode(char var0) { + return var0 + 629; + } + + public static int hashCode(double var0) { + return hashCode(Double.doubleToLongBits(var0)); + } + + public static int hashCode(float var0) { + return Float.floatToIntBits(var0) + 629; + } + + public static int hashCode(int var0) { + return var0 + 629; + } + + public static int hashCode(long var0) { + return (int) (var0 >> 32 ^ var0) + 629; + } + + public static int hashCode(Object var0) { + if (var0 == null) { + return 629; + } else if (var0.getClass().isArray()) { + if (var0 instanceof long[]) { + return hashCode((long[]) ((long[]) var0)); + } else if (var0 instanceof int[]) { + return hashCode((int[]) ((int[]) var0)); + } else if (var0 instanceof short[]) { + return hashCode((short[]) ((short[]) var0)); + } else if (var0 instanceof char[]) { + return hashCode((char[]) ((char[]) var0)); + } else if (var0 instanceof byte[]) { + return hashCode((byte[]) ((byte[]) var0)); + } else if (var0 instanceof double[]) { + return hashCode((double[]) ((double[]) var0)); + } else if (var0 instanceof float[]) { + return hashCode((float[]) ((float[]) var0)); + } else if (var0 instanceof boolean[]) { + return hashCode((boolean[]) ((boolean[]) var0)); + } else { + return var0 instanceof JceStruct[] ? hashCode((JceStruct[]) ((JceStruct[]) var0)) : hashCode((Object) ((Object[]) ((Object[]) var0))); + } + } else { + return var0 instanceof JceStruct ? var0.hashCode() : var0.hashCode() + 629; + } + } + + public static int hashCode(short var0) { + return var0 + 629; + } + + public static int hashCode(boolean var0) { + byte var1; + if (var0) { + var1 = 0; + } else { + var1 = 1; + } + + return var1 + 629; + } + + public static int hashCode(byte[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + var0[var2]; + ++var2; + } + } + + return var3; + } + + public static int hashCode(char[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + var0[var2]; + ++var2; + } + } + + return var3; + } + + public static int hashCode(double[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + (int) (Double.doubleToLongBits(var0[var2]) ^ Double.doubleToLongBits(var0[var2]) >> 32); + ++var2; + } + } + + return var3; + } + + public static int hashCode(float[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + Float.floatToIntBits(var0[var2]); + ++var2; + } + } + + return var3; + } + + public static int hashCode(int[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + var0[var2]; + ++var2; + } + } + + return var3; + } + + public static int hashCode(long[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + (int) (var0[var2] ^ var0[var2] >> 32); + ++var2; + } + } + + return var3; + } + + public static int hashCode(JceStruct[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + var0[var2].hashCode(); + ++var2; + } + } + + return var3; + } + + public static int hashCode(short[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + var1 = var1 * 37 + var0[var2]; + ++var2; + } + } + + return var3; + } + + public static int hashCode(boolean[] var0) { + int var3; + if (var0 == null) { + var3 = 629; + } else { + int var1 = 17; + int var2 = 0; + + while (true) { + var3 = var1; + if (var2 >= var0.length) { + break; + } + + byte var4; + if (var0[var2]) { + var4 = 0; + } else { + var4 = 1; + } + + var1 = var4 + var1 * 37; + ++var2; + } + } + + return var3; + } +} diff --git a/mirai-debug/src/test/java/jce/jce/OnIllegalArgumentException.java b/mirai-debug/src/test/java/jce/jce/OnIllegalArgumentException.java new file mode 100644 index 000000000..af7eb6cee --- /dev/null +++ b/mirai-debug/src/test/java/jce/jce/OnIllegalArgumentException.java @@ -0,0 +1,7 @@ +package jce.jce; + +import java.nio.ByteBuffer; + +public interface OnIllegalArgumentException { + void onException(IllegalArgumentException var1, ByteBuffer var2, int var3, int var4); +} diff --git a/mirai-debug/src/test/kotlin/jceTest/jceTest.kt b/mirai-debug/src/test/kotlin/jceTest/jceTest.kt new file mode 100644 index 000000000..30116c4b8 --- /dev/null +++ b/mirai-debug/src/test/kotlin/jceTest/jceTest.kt @@ -0,0 +1,293 @@ +package jceTest + +import io.ktor.util.InternalAPI +import jce.jce.JceInputStream +import jce.jce.JceOutputStream +import jce.jce.JceStruct +import kotlinx.io.core.ByteReadPacket +import kotlinx.io.core.readBytes +import net.mamoe.mirai.qqandroid.network.io.JceInput +import net.mamoe.mirai.qqandroid.network.io.JceOutput +import net.mamoe.mirai.qqandroid.network.io.buildJcePacket +import net.mamoe.mirai.utils.io.toUHexString +import org.junit.Test + +private infix fun ByteReadPacket.shouldEqualTo(another: ByteArray) { + this.readBytes().let { + check(it.contentEquals(another)) { + """actual: ${it.toUHexString()} + |required: ${another.toUHexString()} + """.trimMargin() + } + } +} + +@UseExperimental(InternalAPI::class) +private fun qqJce(block: JceOutputStream.() -> Unit): ByteArray { + return JceOutputStream().apply(block).toByteArray() +} + +internal class JceOutputTest { + + @Test + fun writeByte() { + buildJcePacket { + writeByte(1, 1) + writeByte(-128, 2) + } shouldEqualTo qqJce { + write(1.toByte(), 1) + write((-128).toByte(), 2) + } + } + + @Test + fun writeDouble() { + buildJcePacket { + writeDouble(1.0, 1) + writeDouble(-128.0, 2) + } shouldEqualTo qqJce { + write(1.toDouble(), 1) + write((-128).toDouble(), 2) + } + } + + @Test + fun writeFloat() { + buildJcePacket { + writeFloat(1.0f, 1) + writeFloat(-128.0f, 2) + } shouldEqualTo qqJce { + write(1.toFloat(), 1) + write((-128).toFloat(), 2) + } + } + + @Test + fun writeFully() { + buildJcePacket { + writeFully(byteArrayOf(1, 2), 1) + writeFully(byteArrayOf(1, 2), 2) + } shouldEqualTo qqJce { + write(byteArrayOf(1, 2), 1) + write(byteArrayOf(1, 2), 2) + } + } + + @Test + fun testWriteFully() { + buildJcePacket { + writeFully(intArrayOf(1, 2), 1) + writeFully(intArrayOf(1, 2), 2) + } shouldEqualTo qqJce { + write(intArrayOf(1, 2), 1) + write(intArrayOf(1, 2), 2) + } + } + + @Test + fun testWriteFully1() { + buildJcePacket { + writeFully(shortArrayOf(1, 2), 1) + writeFully(shortArrayOf(1, 2), 2) + } shouldEqualTo qqJce { + write(shortArrayOf(1, 2), 1) + write(shortArrayOf(1, 2), 2) + } + } + + @Test + fun testWriteFully2() { + buildJcePacket { + writeFully(booleanArrayOf(true, false), 1) + writeFully(booleanArrayOf(true, false), 2) + } shouldEqualTo qqJce { + write(booleanArrayOf(true, false), 1) + write(booleanArrayOf(true, false), 2) + } + } + + @Test + fun testWriteFully3() { + buildJcePacket { + writeFully(longArrayOf(1, 2), 1) + writeFully(longArrayOf(1, 2), 2) + } shouldEqualTo qqJce { + write(longArrayOf(1, 2), 1) + write(longArrayOf(1, 2), 2) + } + } + + @Test + fun testWriteFully4() { + buildJcePacket { + writeFully(floatArrayOf(1f, 2f), 1) + writeFully(floatArrayOf(1f, 2f), 2) + } shouldEqualTo qqJce { + write(floatArrayOf(1f, 2f), 1) + write(floatArrayOf(1f, 2f), 2) + } + } + + @Test + fun testWriteFully5() { + buildJcePacket { + writeFully(doubleArrayOf(1.0, 2.0), 1) + writeFully(doubleArrayOf(1.0, 2.0), 2) + } shouldEqualTo qqJce { + write(doubleArrayOf(1.0, 2.0), 1) + write(doubleArrayOf(1.0, 2.0), 2) + } + } + + @Test + fun testWriteFully6() { + buildJcePacket { + writeFully(arrayOf("123", "哈哈"), 1) + writeFully(arrayOf("123", "哈哈"), 2) + } shouldEqualTo qqJce { + write(arrayOf("123", "哈哈"), 1) + write(arrayOf("123", "哈哈"), 2) + } + } + + @Test + fun writeInt() { + buildJcePacket { + writeInt(1, 1) + writeInt(-128, 2) + } shouldEqualTo qqJce { + write(1, 1) + write(-128, 2) + } + } + + @Test + fun writeLong() { + buildJcePacket { + writeLong(1, 1) + writeLong(-128, 2) + } shouldEqualTo qqJce { + write(1L, 1) + write(-128L, 2) + } + } + + @Test + fun writeShort() { + buildJcePacket { + writeShort(1, 1) + writeShort(-128, 2) + } shouldEqualTo qqJce { + write(1.toShort(), 1) + write((-128).toShort(), 2) + } + } + + @Test + fun writeBoolean() { + buildJcePacket { + writeBoolean(true, 1) + writeBoolean(false, 2) + } shouldEqualTo qqJce { + write(true, 1) + write(false, 2) + } + } + + @Test + fun writeString() { + buildJcePacket { + writeString("1", 1) + writeString("哈啊", 2) + } shouldEqualTo qqJce { + write("1", 1) + write("哈啊", 2) + } + } + + @Test + fun writeMap() { + buildJcePacket { + writeMap(mapOf("" to ""), 1) + writeMap(mapOf("" to 123), 2) + writeMap(mapOf(123.0 to "Hello"), 3) + } shouldEqualTo qqJce { + write(mapOf("" to ""), 1) + write(mapOf("" to 123), 2) + write(mapOf(123.0 to "Hello"), 3) + } + } + + @Test + fun writeCollection() { + buildJcePacket { + writeMap(mapOf("" to ""), 1) + writeMap(mapOf("" to 123), 2) + writeMap(mapOf(123.0 to "Hello"), 3) + } shouldEqualTo qqJce { + write(mapOf("" to ""), 1) + write(mapOf("" to 123), 2) + write(mapOf(123.0 to "Hello"), 3) + } + } + + data class TestMiraiStruct( + val message: String + ) : net.mamoe.mirai.qqandroid.network.io.JceStruct() { + override fun writeTo(builder: JceOutput) { + builder.writeString(message, 0) + } + + companion object : Factory<TestMiraiStruct> { + override fun newInstanceFrom(input: JceInput): TestMiraiStruct { + return TestMiraiStruct(input.readString(0)) + } + } + } + + class TestQQStruct( + private var message: String + ) : JceStruct() { + override fun readFrom(var1: JceInputStream) { + message = var1.read("", 0, true) + } + + override fun writeTo(var1: JceOutputStream) { + var1.write(message, 0) + } + } + + @Test + fun writeJceStruct() { + buildJcePacket { + writeJceStruct(TestMiraiStruct("Hello"), 0) + writeJceStruct(TestMiraiStruct("嗨"), 1) + } shouldEqualTo qqJce { + write(TestQQStruct("Hello"), 0) + write(TestQQStruct("嗨"), 1) + } + } + + @Test + fun writeObject() { + buildJcePacket { + writeObject(0.toByte(), 1) + writeObject(0.toShort(), 2) + writeObject(0, 3) + writeObject(0L, 4) + writeObject(0f, 5) + writeObject(0.0, 6) + writeObject("hello", 7) + writeObject(TestMiraiStruct("Hello"), 8) + } shouldEqualTo qqJce { + write(0.toByte(), 1) + write(0.toShort(), 2) + write(0, 3) + write(0L, 4) + write(0f, 5) + write(0.0, 6) + write("hello", 7) + write(TestQQStruct("Hello"), 8) + } + } +} \ No newline at end of file