diff --git a/G-Earth/src/main/java/gearth/extensions/Extension.java b/G-Earth/src/main/java/gearth/extensions/Extension.java index 254e7a5..2f40d1c 100644 --- a/G-Earth/src/main/java/gearth/extensions/Extension.java +++ b/G-Earth/src/main/java/gearth/extensions/Extension.java @@ -36,6 +36,8 @@ public abstract class Extension implements IExtension { private static final String[] FILE_FLAG = {"--filename", "-f"}; private static final String[] COOKIE_FLAG = {"--auth-token", "-c"}; // don't add a cookie or filename when debugging + protected PacketInfoManager packetInfoManager = new PacketInfoManager(new ArrayList<>()); // empty + private OutputStream out = null; private final Map> incomingMessageListeners = new HashMap<>(); private final Map> outgoingMessageListeners = new HashMap<>(); @@ -144,7 +146,7 @@ public abstract class Extension implements IExtension { String hotelVersion = packet.readString(); String clientIdentifier = packet.readString(); HClient clientType = HClient.valueOf(packet.readString()); - PacketInfoManager packetInfoManager = PacketInfoManager.readFromPacket(packet); + packetInfoManager = PacketInfoManager.readFromPacket(packet); Constants.UNITY_PACKETS = clientType == HClient.UNITY; onConnectionObservable.fireEvent(l -> l.onConnection( @@ -256,6 +258,11 @@ public abstract class Extension implements IExtension { return send(packet, HMessage.Direction.TOSERVER); } private boolean send(HPacket packet, HMessage.Direction direction) { + if (packet.isCorrupted()) return false; + + if (!packet.isPacketComplete()) packet.completePacket(direction, packetInfoManager); + if (!packet.isPacketComplete()) return false; + HPacket packet1 = new HPacket(NetworkExtensionInfo.INCOMING_MESSAGES_IDS.SENDMESSAGE); packet1.appendByte(direction == HMessage.Direction.TOCLIENT ? (byte)0 : (byte)1); packet1.appendInt(packet.getBytesLength()); diff --git a/G-Earth/src/main/java/gearth/misc/packet_info/providers/implementations/HarblePacketInfoProvider.java b/G-Earth/src/main/java/gearth/misc/packet_info/providers/implementations/HarblePacketInfoProvider.java index b8c4b9f..f7aeb39 100644 --- a/G-Earth/src/main/java/gearth/misc/packet_info/providers/implementations/HarblePacketInfoProvider.java +++ b/G-Earth/src/main/java/gearth/misc/packet_info/providers/implementations/HarblePacketInfoProvider.java @@ -44,6 +44,7 @@ public class HarblePacketInfoProvider extends RemotePacketInfoProvider { catch (Exception e) { hash = null; } try { structure = object.getString("Structure"); } catch (Exception e) { structure = null; } + structure = (structure == null || structure.equals("")) ? null : structure; int headerId; try {headerId = object.getInt("Id"); } diff --git a/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStringUtils.java b/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStringUtils.java index 4226958..a86f1c7 100644 --- a/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStringUtils.java +++ b/G-Earth/src/main/java/gearth/misc/packetrepresentation/PacketStringUtils.java @@ -135,6 +135,14 @@ public class PacketStringUtils { packet.substring(end + 2); } + String[] identifier = {null}; + if (!fixLengthLater && packet.startsWith("{")) { + packet = replaceAll(packet, "^\\{([^:{}]*)}", m -> { + identifier[0] = m.group(1); + return "[255][255]"; + }); + } + if (identifier[0] != null) fixLengthLater = true; if (packet.contains("{") || packet.contains("}")) { throw new InvalidPacketException(); @@ -164,6 +172,9 @@ public class PacketStringUtils { if (fixLengthLater) { hPacket.fixLength(); } + if (identifier[0] != null) { + hPacket.setIdentifier(identifier[0]); + } return hPacket; } public static String toString(byte[] packet) { @@ -255,6 +266,9 @@ public class PacketStringUtils { } public static void main(String[] args) throws InvalidPacketException { + HPacket zed = fromString("{test}{s:\"¥\"}{i:0}{i:0}"); + System.out.println(zed); + HPacket p1 = fromString("{l}{h:1129}{s:\"\\\\\\\\\"}{i:0}{i:0}"); System.out.println(p1.toExpression()); HPacket p1_2 = fromString(p1.toExpression()); diff --git a/G-Earth/src/main/java/gearth/protocol/HConnection.java b/G-Earth/src/main/java/gearth/protocol/HConnection.java index a6d1887..85b0db4 100644 --- a/G-Earth/src/main/java/gearth/protocol/HConnection.java +++ b/G-Earth/src/main/java/gearth/protocol/HConnection.java @@ -138,16 +138,28 @@ public class HConnection { public boolean sendToClientAsync(HPacket message) { - if (proxy == null) { - return false; + if (proxy == null) return false; + + if (!message.isPacketComplete()) { + PacketInfoManager packetInfoManager = getPacketInfoManager(); + message.completePacket(HMessage.Direction.TOCLIENT, packetInfoManager); + + if (!message.isPacketComplete()) return false; } + proxy.getAsyncPacketSender().sendToClientAsync(message); return true; } public boolean sendToServerAsync(HPacket message) { - if (proxy == null) { - return false; + if (proxy == null) return false; + + if (!message.isPacketComplete()) { + PacketInfoManager packetInfoManager = getPacketInfoManager(); + message.completePacket(HMessage.Direction.TOSERVER, packetInfoManager); + + if (!message.isPacketComplete()) return false; } + proxy.getAsyncPacketSender().sendToServerAsync(message); return true; } diff --git a/G-Earth/src/main/java/gearth/protocol/HPacket.java b/G-Earth/src/main/java/gearth/protocol/HPacket.java index 0a69fe6..469232f 100644 --- a/G-Earth/src/main/java/gearth/protocol/HPacket.java +++ b/G-Earth/src/main/java/gearth/protocol/HPacket.java @@ -15,12 +15,13 @@ import java.util.Optional; public class HPacket implements StringifyAble { - - private boolean isEdited = false; private byte[] packetInBytes; private int readIndex = 6; + // if identifier != null, this is a placeholder name for the type of packet, headerId will be "-1" + private String identifier = null; + public HPacket(byte[] packet) { packetInBytes = packet.clone(); } @@ -30,11 +31,11 @@ public class HPacket implements StringifyAble { } public HPacket(String packet) { try { - packetInBytes = PacketStringUtils.fromString(packet).packetInBytes; + HPacket packetFromString = PacketStringUtils.fromString(packet); + packetInBytes = packetFromString.packetInBytes; + identifier = packetFromString.identifier; } catch (InvalidPacketException e) { packetInBytes = new byte[0]; - // will be corrupted - // e.printStackTrace(); } } public HPacket(int header) { @@ -42,6 +43,7 @@ public class HPacket implements StringifyAble { replaceShort(4, (short)header); isEdited = false; } + public HPacket(int header, byte[] bytes) { this(header); appendBytes(bytes); @@ -55,14 +57,19 @@ public class HPacket implements StringifyAble { */ public HPacket(int header, Object... objects) throws InvalidParameterException { this(header); - for (int i = 0; i < objects.length; i++) { - Object o = objects[i]; - appendObject(o); - } - + appendObjects(objects); isEdited = false; } + public HPacket(String identifier, Object... objects) throws InvalidParameterException { + packetInBytes = new byte[]{0,0,0,2,-1,-1}; + this.identifier = identifier; + appendObjects(objects); + isEdited = false; + } + + + public String toString() { return PacketStringUtils.toString(packetInBytes); } @@ -77,6 +84,46 @@ public class HPacket implements StringifyAble { return 2; } + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getIdentifier() { + return identifier; + } + + public void completePacket(HMessage.Direction direction, PacketInfoManager packetInfoManager) { + if (isCorrupted() || identifier == null) return; + + PacketInfo packetInfo = packetInfoManager.getPacketInfoFromName(direction, identifier); + if (packetInfo == null) { + packetInfo = packetInfoManager.getPacketInfoFromHash(direction, identifier); + if (packetInfo == null) return; + } + + boolean wasEdited = isEdited; + replaceShort(4, (short)(packetInfo.getHeaderId())); + identifier = null; + + isEdited = wasEdited; + } + + public boolean canComplete(HMessage.Direction direction, PacketInfoManager packetInfoManager) { + if (isCorrupted() || identifier == null) return false; + + PacketInfo packetInfo = packetInfoManager.getPacketInfoFromName(direction, identifier); + if (packetInfo == null) { + packetInfo = packetInfoManager.getPacketInfoFromHash(direction, identifier); + return packetInfo != null; + } + + return true; + } + + public boolean isPacketComplete() { + return identifier == null; + } + public byte[] toBytes() { return packetInBytes; } @@ -534,6 +581,14 @@ public class HPacket implements StringifyAble { return appendLongString(s, StandardCharsets.ISO_8859_1); } + public HPacket appendObjects(Object... objects) { + for (Object object : objects) { + appendObject(object); + } + + return this; + } + public HPacket appendObject(Object o) throws InvalidParameterException { isEdited = true; diff --git a/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java b/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java index 7cc3e52..e4ca766 100644 --- a/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java +++ b/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java @@ -1,5 +1,7 @@ package gearth.ui.injection; +import gearth.misc.packet_info.PacketInfoManager; +import gearth.protocol.HMessage; import gearth.protocol.connection.HState; import javafx.application.Platform; import javafx.event.ActionEvent; @@ -12,7 +14,13 @@ import gearth.protocol.HConnection; import gearth.protocol.HPacket; import gearth.ui.SubForm; +import java.util.ArrayList; +import java.util.Arrays; import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; public class InjectionController extends SubForm { public TextArea inputPacket; @@ -95,9 +103,38 @@ public class InjectionController extends SubForm { } if (!dirty) { - btn_sendToClient.setDisable(getHConnection().getState() != HState.CONNECTED); - btn_sendToServer.setDisable(getHConnection().getState() != HState.CONNECTED); + PacketInfoManager packetInfoManager = getHConnection().getPacketInfoManager(); + + List unIdentifiedPackets = Arrays.stream(packets) + .filter(hPacket -> !hPacket.isPacketComplete()) + .map(HPacket::getIdentifier).collect(Collectors.toList()); + + boolean canSendToClient = unIdentifiedPackets.stream().allMatch(s -> { + if (packetInfoManager == null) return false; + return packetInfoManager.getPacketInfoFromHash(HMessage.Direction.TOCLIENT, s) != null || + packetInfoManager.getPacketInfoFromName(HMessage.Direction.TOCLIENT, s) != null; + }); + boolean canSendToServer = unIdentifiedPackets.stream().allMatch(s -> { + if (packetInfoManager == null) return false; + return packetInfoManager.getPacketInfoFromHash(HMessage.Direction.TOSERVER, s) != null || + packetInfoManager.getPacketInfoFromName(HMessage.Direction.TOSERVER, s) != null; + }); + + btn_sendToClient.setDisable(!canSendToClient || getHConnection().getState() != HState.CONNECTED); + btn_sendToServer.setDisable(!canSendToServer || getHConnection().getState() != HState.CONNECTED); if (packets.length == 1) { + + // complete packet to show correct headerId + if (!packets[0].isPacketComplete()) { + HPacket packet = packets[0]; + if (packet.canComplete(HMessage.Direction.TOCLIENT, packetInfoManager) && !packet.canComplete(HMessage.Direction.TOSERVER, packetInfoManager)) { + packet.completePacket(HMessage.Direction.TOCLIENT, packetInfoManager); + } + else if (!packet.canComplete(HMessage.Direction.TOCLIENT, packetInfoManager) && packet.canComplete(HMessage.Direction.TOSERVER, packetInfoManager)) { + packet.completePacket(HMessage.Direction.TOSERVER, packetInfoManager); + } + } + lbl_pcktInfo.setText("header (id:" + packets[0].headerId() + ", length:" + packets[0].length() + ")"); } diff --git a/G-Earth/src/main/java/gearth/ui/scheduler/InteractableScheduleItem.java b/G-Earth/src/main/java/gearth/ui/scheduler/InteractableScheduleItem.java index 1af3246..d663145 100644 --- a/G-Earth/src/main/java/gearth/ui/scheduler/InteractableScheduleItem.java +++ b/G-Earth/src/main/java/gearth/ui/scheduler/InteractableScheduleItem.java @@ -72,8 +72,8 @@ public class InteractableScheduleItem extends ScheduleItem implements StringifyA .append("\t") .append(getDelayProperty().get().toString()) .append("\t") - .append(getPacketProperty().get().toString()) - .append("\t") +// .append(getPacketProperty().get().toString()) +// .append("\t") .append(getDestinationProperty().get().name()) .append("\t") .append(getPacketAsStringProperty().get()); @@ -87,9 +87,10 @@ public class InteractableScheduleItem extends ScheduleItem implements StringifyA int index = Integer.parseInt(parts[0]); boolean paused = parts[1].equals("true"); Interval delay = new Interval(parts[2]); - HPacket packet = new HPacket(parts[3]); - HMessage.Direction direction = parts[4].equals(HMessage.Direction.TOSERVER.name()) ? HMessage.Direction.TOSERVER : HMessage.Direction.TOCLIENT; - String packetAsString = parts[5]; +// HPacket packet = new HPacket(parts[3]); + HMessage.Direction direction = parts[3].equals(HMessage.Direction.TOSERVER.name()) ? HMessage.Direction.TOSERVER : HMessage.Direction.TOCLIENT; + String packetAsString = parts[4]; + HPacket packet = new HPacket(packetAsString); construct(index, paused, delay, packet, direction); this.packetAsStringProperty = new SimpleStringProperty(packetAsString);