diff --git a/G-Earth/src/main/java/gearth/ui/injection/InjectedPackets.java b/G-Earth/src/main/java/gearth/ui/injection/InjectedPackets.java new file mode 100644 index 0000000..df30cbc --- /dev/null +++ b/G-Earth/src/main/java/gearth/ui/injection/InjectedPackets.java @@ -0,0 +1,85 @@ +package gearth.ui.injection; + +import gearth.misc.StringifyAble; +import gearth.protocol.HMessage; +import gearth.protocol.HPacket; +import gearth.services.packet_info.PacketInfo; +import gearth.services.packet_info.PacketInfoManager; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; + +public class InjectedPackets implements StringifyAble { + + private String packetsAsString; + private String description; + + public InjectedPackets(String packetsAsString, int amountPackets, PacketInfoManager packetInfoManager, HMessage.Direction direction) { + String description; + if (amountPackets > 1) { + description = String.format("(packets: %d, length: %d)", amountPackets, packetsAsString.length()); + } + else { // assume 1 packet + HPacket packet = new HPacket(packetsAsString); + String identifier = null; + if (!packet.isPacketComplete()) { + identifier = packet.getIdentifier(); + } + else { + Optional maybeInfo = packetInfoManager.getAllPacketInfoFromHeaderId(direction, packet.headerId()) + .stream().filter(packetInfo -> packetInfo.getName() != null).findFirst(); + if (maybeInfo.isPresent()) { + PacketInfo packetInfo = maybeInfo.get(); + identifier = packetInfo.getName(); + } + } + + if (identifier != null) { + description = String.format("%s", identifier); + } + else { + description = String.format("(id: %d, length: %d)", packet.headerId(), packet.length()); + } + } + + this.description = description; + this.packetsAsString = packetsAsString; + } + + public InjectedPackets(String fromString) { + constructFromString(fromString); + } + + public String getPacketsAsString() { + return packetsAsString; + } + + public String getDescription() { + return description; + } + + @Override + public String stringify() { + Map info = new HashMap<>(); + info.put("packetsAsString", packetsAsString); + info.put("description", description); + + return new JSONObject(info).toString(); + } + + @Override + public void constructFromString(String str) { + JSONObject jsonObject = new JSONObject(str); + this.packetsAsString = jsonObject.getString("packetsAsString"); + this.description = jsonObject.getString("description"); + } + + @Override + public String toString() { + return description; + } +} 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 3cd74bc..91168fe 100644 --- a/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java +++ b/G-Earth/src/main/java/gearth/ui/injection/InjectionController.java @@ -1,29 +1,42 @@ package gearth.ui.injection; +import gearth.misc.Cacher; import gearth.services.packet_info.PacketInfoManager; import gearth.protocol.HMessage; import gearth.protocol.connection.HState; import javafx.application.Platform; import javafx.event.ActionEvent; -import javafx.scene.control.Button; -import javafx.scene.control.TextArea; +import javafx.event.EventHandler; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.text.Text; import gearth.protocol.HPacket; import gearth.ui.SubForm; +import sun.misc.Cache; +import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; import java.util.stream.Collectors; public class InjectionController extends SubForm { + + private static final String HISTORY_CACHE_KEY = "INJECTED_HISTORY"; + private static final int historylimit = 69; + public TextArea inputPacket; public Text lbl_corrruption; public Text lbl_pcktInfo; public Button btn_sendToServer; public Button btn_sendToClient; + public ListView history; + public Label lblHistory; protected void onParentSet() { getHConnection().getStateObservable().addListener((oldState, newState) -> Platform.runLater(this::updateUI)); @@ -31,6 +44,29 @@ public class InjectionController extends SubForm { inputPacket.textProperty().addListener(event -> Platform.runLater(this::updateUI)); } + public void initialize() { + history.setOnMouseClicked(event -> { + if(event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) { + InjectedPackets injectedPackets = history.getSelectionModel().getSelectedItem(); + if (injectedPackets != null) { + Platform.runLater(() -> { + inputPacket.setText(injectedPackets.getPacketsAsString()); + updateUI(); + }); + } + } + }); + + lblHistory.setTooltip(new Tooltip("Double click a packet to restore it")); + + List rawHistory = Cacher.getList(HISTORY_CACHE_KEY); + if (rawHistory != null) { + List history = rawHistory.stream() + .map(o -> (String)o).limit(historylimit - 1).map(InjectedPackets::new).collect(Collectors.toList()); + updateHistoryView(history); + } + } + private static boolean isPacketIncomplete(String line) { boolean unmatchedBrace = false; @@ -157,6 +193,8 @@ public class InjectionController extends SubForm { getHConnection().sendToServerAsync(packet); writeToLog(Color.BLUE, "SS -> packet with id: " + packet.headerId()); } + + addToHistory(packets, inputPacket.getText(), HMessage.Direction.TOSERVER); } public void sendToClient_clicked(ActionEvent actionEvent) { @@ -165,6 +203,40 @@ public class InjectionController extends SubForm { getHConnection().sendToClientAsync(packet); writeToLog(Color.RED, "CS -> packet with id: " + packet.headerId()); } + + addToHistory(packets, inputPacket.getText(), HMessage.Direction.TOCLIENT); + } + + private void addToHistory(HPacket[] packets, String packetsAsString, HMessage.Direction direction) { + InjectedPackets injectedPackets = new InjectedPackets(packetsAsString, packets.length, getHConnection().getPacketInfoManager(), direction); + + List newHistory = new ArrayList<>(); + newHistory.add(injectedPackets); + + List rawOldHistory = Cacher.getList(HISTORY_CACHE_KEY); + if (rawOldHistory != null) { + List history = rawOldHistory.stream() + .map(o -> (String)o).limit(historylimit - 1).map(InjectedPackets::new).collect(Collectors.toList()); + + // dont add to history if its equal to the latest added packet + if (history.size() != 0 && history.get(0).getPacketsAsString().equals(injectedPackets.getPacketsAsString())) { + return; + } + + newHistory.addAll(history); + } + + List historyAsStrings = newHistory.stream().map(InjectedPackets::stringify).collect(Collectors.toList()); + Cacher.put(HISTORY_CACHE_KEY, historyAsStrings); + + updateHistoryView(newHistory); + } + + private void updateHistoryView(List allHistoryItems) { + Platform.runLater(() -> { + history.getItems().clear(); + history.getItems().addAll(allHistoryItems); + }); } diff --git a/G-Earth/src/main/resources/gearth/ui/connection/Connection.fxml b/G-Earth/src/main/resources/gearth/ui/connection/Connection.fxml index 32a7bcf..96b87e5 100644 --- a/G-Earth/src/main/resources/gearth/ui/connection/Connection.fxml +++ b/G-Earth/src/main/resources/gearth/ui/connection/Connection.fxml @@ -1,19 +1,11 @@ - - - - - - - - - - - - + + + + - + @@ -148,7 +140,7 @@ -