mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2024-11-26 18:30:52 +01:00
Initial commit
This commit is contained in:
commit
e1347af8b1
45
src/main/Main.java
Normal file
45
src/main/Main.java
Normal file
@ -0,0 +1,45 @@
|
||||
package main;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
import main.ui.GEarthController;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// run as root issue Invalid MIT-MAGIC-COOKIE-1 key fix: https://stackoverflow.com/questions/48139447/invalid-mit-magic-cookie-1-key
|
||||
|
||||
public class Main extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception{
|
||||
|
||||
FXMLLoader loader = new FXMLLoader(GEarthController.class.getResource("G-Earth.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
GEarthController companion = loader.getController();
|
||||
companion.setStage(primaryStage);
|
||||
|
||||
primaryStage.setResizable(false);
|
||||
//primaryStage.initStyle(StageStyle.UNDECORATED);
|
||||
primaryStage.setTitle("G-Earth");
|
||||
primaryStage.setScene(new Scene(root, 620, 295));
|
||||
primaryStage.show();
|
||||
|
||||
primaryStage.getScene().getStylesheets().add(GEarthController.class.getResource("bootstrap3.css").toExternalForm());
|
||||
|
||||
primaryStage.setOnCloseRequest( event -> {
|
||||
companion.abort();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
launch(args);
|
||||
}
|
||||
}
|
54
src/main/OSValidator.java
Normal file
54
src/main/OSValidator.java
Normal file
@ -0,0 +1,54 @@
|
||||
package main;
|
||||
|
||||
public class OSValidator {
|
||||
|
||||
private static String OS = System.getProperty("os.name").toLowerCase();
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println(OS);
|
||||
|
||||
if (isWindows()) {
|
||||
System.out.println("This is Windows");
|
||||
} else if (isMac()) {
|
||||
System.out.println("This is Mac");
|
||||
} else if (isUnix()) {
|
||||
System.out.println("This is Unix or Linux");
|
||||
} else if (isSolaris()) {
|
||||
System.out.println("This is Solaris");
|
||||
} else {
|
||||
System.out.println("Your OS is not support!!");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
return (OS.contains("win"));
|
||||
}
|
||||
|
||||
public static boolean isMac() {
|
||||
return (OS.contains("mac"));
|
||||
}
|
||||
|
||||
public static boolean isUnix() {
|
||||
return (OS.contains("nix") || OS.contains("nux") || OS.indexOf("aix") > 0);
|
||||
}
|
||||
|
||||
public static boolean isSolaris() {
|
||||
return (OS.contains("sunos"));
|
||||
}
|
||||
|
||||
public static String getOS() {
|
||||
if (isWindows()) {
|
||||
return "win";
|
||||
} else if (isMac()) {
|
||||
return "osx";
|
||||
} else if (isUnix()) {
|
||||
return "uni";
|
||||
} else if (isSolaris()) {
|
||||
return "sol";
|
||||
} else {
|
||||
return "err";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
11
src/main/irrelevant/Timer.java
Normal file
11
src/main/irrelevant/Timer.java
Normal file
@ -0,0 +1,11 @@
|
||||
package main.irrelevant;
|
||||
|
||||
public class Timer {
|
||||
private long time0 = System.nanoTime(), time1 = time0;
|
||||
private boolean ended = false;
|
||||
public void start() { time0 = System.nanoTime(); ended = false; }
|
||||
public void end() { time1 = System.nanoTime(); ended = true; }
|
||||
public double delta() {
|
||||
if ( ! ended) { end(); }
|
||||
return 1e-6 * (time1 - time0); }
|
||||
}
|
399
src/main/protocol/HConnection.java
Normal file
399
src/main/protocol/HConnection.java
Normal file
@ -0,0 +1,399 @@
|
||||
package main.protocol;
|
||||
|
||||
import main.OSValidator;
|
||||
import main.protocol.packethandler.Handler;
|
||||
import main.protocol.packethandler.IncomingHandler;
|
||||
import main.protocol.packethandler.OutgoingHandler;
|
||||
import sun.plugin2.util.SystemUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HConnection {
|
||||
|
||||
public enum State {
|
||||
NOT_CONNECTED,
|
||||
PREPARING, // DOMAIN AND PORT BEEN PASSED
|
||||
PREPARED, // FOUND IP ADDRESS OF DOMAIN
|
||||
WAITING_FOR_CLIENT, // WAITING FOR CORRECT TCP CONNECTION TO BE SET UP
|
||||
CONNECTED // CONNECTED
|
||||
}
|
||||
|
||||
private static final String hostsFileLocation;
|
||||
static {
|
||||
if (OSValidator.isWindows()) hostsFileLocation = System.getenv("WinDir") + "\\system32\\drivers\\etc\\hosts";
|
||||
else hostsFileLocation = "/etc/hosts"; // confirmed location on linux & mac
|
||||
}
|
||||
|
||||
private volatile boolean hostFileEdited = false;
|
||||
private volatile Object[] trafficListeners = {new ArrayList<TrafficListener>(), new ArrayList<TrafficListener>(), new ArrayList<TrafficListener>()};
|
||||
private volatile List<StateChangeListener> stateChangeListeners = new ArrayList<>();
|
||||
private volatile State state = State.NOT_CONNECTED;
|
||||
private volatile String input_domain = null; // given string representation
|
||||
|
||||
private volatile String actual_domain; // actual ip representation
|
||||
private volatile int port = -1;
|
||||
|
||||
private volatile ServerSocket proxy;
|
||||
private volatile Handler inHandler = null;
|
||||
private volatile Handler outHandler = null;
|
||||
|
||||
public final static boolean DEBUG = false;
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
private String detourIP() {
|
||||
return "127.0.0.1";
|
||||
}
|
||||
|
||||
public void prepare(String domain, int port) {
|
||||
setState(State.PREPARING);
|
||||
|
||||
this.actual_domain = domain;
|
||||
this.port = port;
|
||||
|
||||
if (hostFileEdited) {
|
||||
removeFromHostsFile(detourIP() + " " + domain);
|
||||
}
|
||||
|
||||
try {
|
||||
InetAddress address = InetAddress.getByName(domain);
|
||||
actual_domain = address.getHostAddress();
|
||||
if (DEBUG) System.out.println("found dom:" + actual_domain);
|
||||
input_domain = domain;
|
||||
setState(State.PREPARED);
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
setState(State.NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
public void start() throws IOException {
|
||||
if (state == State.PREPARED) {
|
||||
if (DEBUG) System.out.println("waiting for client on port: " + port);
|
||||
|
||||
setState(State.WAITING_FOR_CLIENT);
|
||||
if (!hostFileEdited) {
|
||||
addToHostsFile(detourIP() + " " + input_domain);
|
||||
}
|
||||
|
||||
proxy = new ServerSocket(port);
|
||||
|
||||
try {
|
||||
while ((state == State.WAITING_FOR_CLIENT) && !proxy.isClosed()) {
|
||||
try {
|
||||
Socket client = proxy.accept();
|
||||
if (DEBUG) System.out.println("accepted a proxy");
|
||||
new Thread(() -> {
|
||||
try {
|
||||
startProxyThread(client);
|
||||
} catch (InterruptedException | IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
|
||||
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
//e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (DEBUG) System.out.println("done waiting for clients with: " + this.state );
|
||||
}
|
||||
}
|
||||
private void startProxyThread(Socket client) throws InterruptedException, UnknownHostException, IOException {
|
||||
final boolean[] datastream = new boolean[1];
|
||||
|
||||
Socket habbo_server = new Socket(actual_domain, port);
|
||||
|
||||
OutputStream client_out = client.getOutputStream();
|
||||
InputStream client_in = client.getInputStream();
|
||||
OutputStream habbo_server_out = habbo_server.getOutputStream();
|
||||
InputStream habbo_server_in = habbo_server.getInputStream();
|
||||
|
||||
if (DEBUG) System.out.println(habbo_server.getLocalAddress().getHostAddress() + ": " + habbo_server.getLocalPort());
|
||||
|
||||
final boolean[] aborted = new boolean[1];
|
||||
|
||||
// wachten op data van client
|
||||
new Thread(() -> {
|
||||
try {
|
||||
OutgoingHandler handler = new OutgoingHandler(habbo_server_out);
|
||||
|
||||
while (!client.isClosed() && (state == State.WAITING_FOR_CLIENT || state == State.CONNECTED)) {
|
||||
byte[] buffer;
|
||||
while (client_in.available() > 0) {
|
||||
client_in.read(buffer = new byte[client_in.available()]);
|
||||
|
||||
handler.act(buffer, trafficListeners);
|
||||
if (!datastream[0] && handler.isDataStream()) {
|
||||
datastream[0] = true;
|
||||
setState(State.CONNECTED);
|
||||
onConnect();
|
||||
|
||||
outHandler = handler;
|
||||
//client_outputStream = client_out;
|
||||
//server_outputStream = habbo_server_out;
|
||||
}
|
||||
|
||||
}
|
||||
Thread.sleep(1);
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
if (DEBUG) System.out.println("abortclient");
|
||||
try {
|
||||
if (habbo_server_out != null) habbo_server_out.close();
|
||||
if (habbo_server_in != null) habbo_server_in.close();
|
||||
if (client_in != null) client_in.close();
|
||||
if (client_out != null) client_out.close();
|
||||
if (habbo_server != null && !habbo_server.isClosed()) habbo_server.close();
|
||||
if (client != null && !client.isClosed()) client.close();
|
||||
aborted[0] = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (datastream[0]) {
|
||||
setState(State.NOT_CONNECTED);
|
||||
outHandler = null;
|
||||
inHandler = null;
|
||||
};
|
||||
}
|
||||
}).start();
|
||||
// wachten op data van server
|
||||
new Thread(() -> {
|
||||
try {
|
||||
IncomingHandler handler = new IncomingHandler(client_out);
|
||||
|
||||
while (!habbo_server.isClosed() && (state == State.CONNECTED || state == State.WAITING_FOR_CLIENT)) {
|
||||
byte[] buffer;
|
||||
while (habbo_server_in.available() > 0) {
|
||||
habbo_server_in.read(buffer = new byte[habbo_server_in.available()]);
|
||||
if (!handler.isDataStream() && datastream[0]) {
|
||||
handler.setAsDataStream();
|
||||
inHandler = handler;
|
||||
}
|
||||
handler.act(buffer, trafficListeners);
|
||||
}
|
||||
Thread.sleep(1);
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
if (habbo_server_out != null) habbo_server_out.close();
|
||||
if (habbo_server_in != null) habbo_server_in.close();
|
||||
if (client_in != null) client_in.close();
|
||||
if (client_out != null) client_out.close();
|
||||
if (!habbo_server.isClosed()) habbo_server.close();
|
||||
if (!client.isClosed()) client.close();
|
||||
aborted[0] = true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
|
||||
while(!aborted[0])
|
||||
{
|
||||
Thread.sleep(50);
|
||||
}
|
||||
|
||||
try {
|
||||
if (!habbo_server.isClosed()) habbo_server.close();
|
||||
if (!client.isClosed()) client.close();
|
||||
if (DEBUG) System.out.println("STOP");
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
private void onConnect() {
|
||||
if (hostFileEdited) {
|
||||
removeFromHostsFile(detourIP() + " " + input_domain);
|
||||
}
|
||||
|
||||
if (proxy != null && !proxy.isClosed()) {
|
||||
try {
|
||||
proxy.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void abort() {
|
||||
if (hostFileEdited) {
|
||||
removeFromHostsFile(detourIP() + " " + input_domain);
|
||||
}
|
||||
port = -1;
|
||||
setState(State.NOT_CONNECTED);
|
||||
actual_domain = null;
|
||||
if (proxy != null && !proxy.isClosed()) {
|
||||
try {
|
||||
proxy.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addToHostsFile(String text) {
|
||||
if (DEBUG) System.out.println("try add hostsfile: " + text);
|
||||
try
|
||||
{
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
File f1 = new File(hostsFileLocation);
|
||||
FileReader fr = new FileReader(f1);
|
||||
BufferedReader br = new BufferedReader(fr);
|
||||
String line = null;
|
||||
boolean containmmm = false;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
if (line.equals(text))
|
||||
containmmm = true;
|
||||
lines.add(line);
|
||||
|
||||
}
|
||||
fr.close();
|
||||
br.close();
|
||||
|
||||
FileWriter fw = new FileWriter(f1);
|
||||
BufferedWriter out = new BufferedWriter(fw);
|
||||
|
||||
if (!containmmm) {
|
||||
out.write(text);
|
||||
}
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
out.write("\n"+ lines.get(i));
|
||||
}
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
hostFileEdited = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
private void removeFromHostsFile(String text) {
|
||||
try
|
||||
{
|
||||
if (DEBUG) System.out.println("try remove hostsfile: " + text);
|
||||
ArrayList<String> lines = new ArrayList<String>();
|
||||
File f1 = new File(hostsFileLocation);
|
||||
FileReader fr = new FileReader(f1);
|
||||
BufferedReader br = new BufferedReader(fr);
|
||||
String line = null;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
if (!line.contains(text))
|
||||
lines.add(line);
|
||||
|
||||
}
|
||||
fr.close();
|
||||
br.close();
|
||||
|
||||
FileWriter fw = new FileWriter(f1);
|
||||
BufferedWriter out = new BufferedWriter(fw);
|
||||
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
out.write(lines.get(i));
|
||||
if (i != lines.size() - 1) out.write("\n");
|
||||
}
|
||||
out.flush();
|
||||
out.close();
|
||||
hostFileEdited = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setState(State state) {
|
||||
if (state != this.state) {
|
||||
State buffer = this.state;
|
||||
this.state = state;
|
||||
for (StateChangeListener listener : stateChangeListeners) {
|
||||
listener.stateChanged(buffer, state);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3 orders:
|
||||
* 0 = before modification ¹
|
||||
* 1 = modification
|
||||
* 2 = after modification ¹
|
||||
*
|
||||
* ¹don't modificate (block, replace)
|
||||
*/
|
||||
public void addTrafficListener(int order, TrafficListener listener) {
|
||||
((List<TrafficListener>)trafficListeners[order]).add(listener);
|
||||
}
|
||||
public void removeTrafficListener(TrafficListener listener) {
|
||||
((List<TrafficListener>)trafficListeners[0]).remove(listener);
|
||||
((List<TrafficListener>)trafficListeners[1]).remove(listener);
|
||||
((List<TrafficListener>)trafficListeners[2]).remove(listener);
|
||||
}
|
||||
|
||||
public void addStateChangeListener(StateChangeListener listener) {
|
||||
stateChangeListeners.add(listener);
|
||||
}
|
||||
public void removeStateChangeListener(StateChangeListener listener) {
|
||||
stateChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
public String getHost() {
|
||||
return actual_domain;
|
||||
}
|
||||
public String getDomain() { return input_domain; }
|
||||
|
||||
|
||||
public boolean sendToClient(HPacket message) {
|
||||
if (inHandler == null) return false;
|
||||
new Thread(() -> inHandler.sendToStream(message.toBytes())).start();
|
||||
return true;
|
||||
}
|
||||
public boolean sendToServer(HPacket message) {
|
||||
if (outHandler == null) return false;
|
||||
outHandler.sendToStream(message.toBytes());
|
||||
return false;
|
||||
}
|
||||
|
||||
public void sendToClientAsync(HPacket message) {
|
||||
new Thread(() -> {
|
||||
sendToClient(message);
|
||||
}).start();
|
||||
}
|
||||
public void sendToServerAsync(HPacket message) {
|
||||
new Thread(() -> {
|
||||
sendToServer(message);
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
41
src/main/protocol/HMessage.java
Normal file
41
src/main/protocol/HMessage.java
Normal file
@ -0,0 +1,41 @@
|
||||
package main.protocol;
|
||||
|
||||
public class HMessage {
|
||||
|
||||
public enum Side {
|
||||
TOSERVER,
|
||||
TOCLIENT
|
||||
}
|
||||
|
||||
private HPacket hPacket;
|
||||
private Side side;
|
||||
private int index;
|
||||
|
||||
private boolean isBlocked;
|
||||
|
||||
|
||||
public HMessage(HPacket packet, Side side, int index) {
|
||||
this.side = side;
|
||||
this.hPacket = packet;
|
||||
this.index = index;
|
||||
isBlocked = false;
|
||||
}
|
||||
|
||||
public void setBlocked(boolean block) {
|
||||
isBlocked = block;
|
||||
}
|
||||
public boolean isBlocked() {
|
||||
return isBlocked;
|
||||
}
|
||||
|
||||
public HPacket getPacket() {
|
||||
return hPacket;
|
||||
}
|
||||
public Side getDestination() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public boolean isCorrupted() {
|
||||
return hPacket.isCorrupted();
|
||||
}
|
||||
}
|
498
src/main/protocol/HPacket.java
Normal file
498
src/main/protocol/HPacket.java
Normal file
@ -0,0 +1,498 @@
|
||||
package main.protocol;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class HPacket {
|
||||
// te komen: toExpressions (+impl. expressies)
|
||||
private boolean isEdited = false;
|
||||
private byte[] packetInBytes;
|
||||
private int readIndex = 6;
|
||||
|
||||
public HPacket(byte[] packet) {
|
||||
packetInBytes = packet.clone();
|
||||
}
|
||||
public HPacket(String packet) {
|
||||
packetInBytes = fromStringToBytes(fromExpressionToString(packet));
|
||||
}
|
||||
public HPacket(int header) {
|
||||
packetInBytes = new byte[]{0,0,0,4,0,0};
|
||||
replaceUShort(4, header);
|
||||
}
|
||||
public HPacket(int header, byte[] bytes) {
|
||||
packetInBytes = new byte[4];
|
||||
appendBytes(bytes);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String teststring = "";
|
||||
for (byte x : packetInBytes) {
|
||||
if ((x < 32 && x >= 0) || x < -96 || x == 93 || x == 91 || x == 125 || x == 123 || x == 127 )
|
||||
teststring+="["+((((int)x) + 256 ) % 256)+"]";
|
||||
else
|
||||
try {
|
||||
teststring+=new String(new byte[]{x}, "ISO-8859-1"); //"ISO-8859-1"
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return teststring;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns "" if invalid expression, replaces all {} occurences except {l}
|
||||
* @return
|
||||
*/
|
||||
private static String fromExpressionToString(String input) {
|
||||
try {
|
||||
int i = 0;
|
||||
char[] asChararray = input.toCharArray();
|
||||
StringBuilder newString = new StringBuilder();
|
||||
if (input.startsWith("{l}")) {
|
||||
newString.append("{l}");
|
||||
i = 3;
|
||||
}
|
||||
|
||||
while (i < input.length()) {
|
||||
if (asChararray[i] != '{') {
|
||||
newString.append(asChararray[i]);
|
||||
i++;
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
StringBuilder typeBuilder = new StringBuilder();
|
||||
while (i < input.length() && asChararray[i] != ':') {
|
||||
typeBuilder.append(asChararray[i]);
|
||||
i++;
|
||||
}
|
||||
if (i == input.length()) throw new Exception();
|
||||
String type = typeBuilder.toString();
|
||||
i++;
|
||||
|
||||
StringBuilder inhoudBuilder = new StringBuilder();
|
||||
while (i < input.length() && asChararray[i] != '}') {
|
||||
inhoudBuilder.append(asChararray[i]);
|
||||
i++;
|
||||
}
|
||||
if (i == input.length()) throw new Exception();
|
||||
String inhoud = inhoudBuilder.toString();
|
||||
i++;
|
||||
|
||||
if (type.equals("u")) {
|
||||
int probs = Integer.parseInt(inhoud);
|
||||
if (probs < 0 || probs >= 256 * 256) throw new Exception();
|
||||
newString.append("[").append(probs / 256).append("][").append(probs % 256).append("]");
|
||||
}
|
||||
else if (type.equals("i")) {
|
||||
ByteBuffer b = ByteBuffer.allocate(4).putInt(Integer.parseInt(inhoud));
|
||||
newString.append(new HPacket(b.array()).toString());
|
||||
}
|
||||
else if (type.equals("b")) { // could be a byte or a boolean, no one cares
|
||||
if (inhoud.toLowerCase().equals("true") || inhoud.toLowerCase().equals("false")) {
|
||||
newString.append(inhoud.toLowerCase().equals("true") ? "[1]" : "[0]");
|
||||
}
|
||||
else {
|
||||
int probs = Integer.parseInt(inhoud);
|
||||
if (probs < 0 || probs >= 256) throw new Exception();
|
||||
newString.append("[").append(probs).append("]");
|
||||
}
|
||||
}
|
||||
else if (type.equals("s")) {
|
||||
int probs = inhoud.length();
|
||||
if (probs < 0 || probs >= 256 * 256) throw new Exception();
|
||||
newString.append("[").append(probs / 256).append("][").append(probs % 256).append("]");
|
||||
|
||||
byte[] bts = inhoud.getBytes(StandardCharsets.ISO_8859_1);
|
||||
for (int j = 0; j < inhoud.length(); j++) {
|
||||
newString.append("[").append((((int)(bts[j])) + 256) % 256).append("]");
|
||||
}
|
||||
}
|
||||
else throw new Exception();
|
||||
|
||||
}
|
||||
}
|
||||
return newString.toString();
|
||||
}
|
||||
catch( Exception e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
private static byte[] fromStringToBytes(String curstring) {
|
||||
try {
|
||||
ArrayList<Byte> bytes = new ArrayList<>();
|
||||
int index = 0;
|
||||
char[] asChararray = curstring.toCharArray();
|
||||
byte[] asliteralbytes = curstring.getBytes("ISO-8859-1");
|
||||
|
||||
boolean startWithLength = false;
|
||||
if (curstring.startsWith("{l}")) {
|
||||
startWithLength = true;
|
||||
index = 3;
|
||||
}
|
||||
|
||||
while (index < curstring.length()) {
|
||||
if (asChararray[index] == '[') {
|
||||
int l = 2;
|
||||
while (index + l < curstring.length() && asChararray[index + l] != ']') l++;
|
||||
if (index + l == curstring.length()) throw new Exception();
|
||||
|
||||
int result = Integer.parseInt(curstring.substring(index + 1, index + l));
|
||||
if (result > 255 || result < 0) throw new Exception();
|
||||
|
||||
byte rl = result > 127 ? (byte)(result - 256) : (byte)result ;
|
||||
|
||||
bytes.add(rl);
|
||||
index = index + 1 + l;
|
||||
}
|
||||
else {
|
||||
bytes.add(asliteralbytes[index]);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
byte[] result;
|
||||
if (startWithLength) {
|
||||
result = new byte[bytes.size() + 4];
|
||||
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.putInt(bytes.size());
|
||||
for (int i = 0; i < 4; i++) {
|
||||
result[i] = b.array()[i];
|
||||
}
|
||||
for (int i = 0; i < bytes.size(); i++) {
|
||||
result[i + 4] = bytes.get(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = new byte[bytes.size()];
|
||||
for (int i = 0; i < bytes.size(); i++) {
|
||||
result[i] = bytes.get(i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception e){}
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
return packetInBytes;
|
||||
}
|
||||
|
||||
public int getReadIndex() {
|
||||
return readIndex;
|
||||
}
|
||||
public void setReadIndex(int number) {
|
||||
readIndex = number;
|
||||
}
|
||||
|
||||
public boolean isCorrupted() {
|
||||
|
||||
if (packetInBytes.length >= 6) {
|
||||
if (length() == getBytesLength() - 4) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte readByte() {
|
||||
readIndex++;
|
||||
return packetInBytes[readIndex - 1];
|
||||
}
|
||||
public byte readByte(int index) {
|
||||
return packetInBytes[index];
|
||||
}
|
||||
|
||||
public short readShort() {
|
||||
byte[] btarray = new byte[]{packetInBytes[readIndex], packetInBytes[readIndex + 1]};
|
||||
readIndex +=2;
|
||||
return java.nio.ByteBuffer.wrap(btarray).getShort();
|
||||
}
|
||||
public short readShort(int index) {
|
||||
byte[] btarray = new byte[]{packetInBytes[index], packetInBytes[index + 1]};
|
||||
return java.nio.ByteBuffer.wrap(btarray).getShort();
|
||||
}
|
||||
public int readUshort() {
|
||||
byte[] btarray = new byte[]{0, 0, packetInBytes[readIndex], packetInBytes[readIndex + 1]};
|
||||
readIndex +=2;
|
||||
return java.nio.ByteBuffer.wrap(btarray).getInt();
|
||||
}
|
||||
public int readUshort(int index) {
|
||||
byte[] btarray = new byte[]{0, 0, packetInBytes[index], packetInBytes[index + 1]};
|
||||
return java.nio.ByteBuffer.wrap(btarray).getInt();
|
||||
}
|
||||
|
||||
public int headerId() {
|
||||
return readUshort(4);
|
||||
}
|
||||
|
||||
public int readInteger(){
|
||||
byte[] btarray = new byte[]{packetInBytes[readIndex], packetInBytes[readIndex + 1], packetInBytes[readIndex + 2], packetInBytes[readIndex + 3]};
|
||||
readIndex +=4;
|
||||
return java.nio.ByteBuffer.wrap(btarray).getInt();
|
||||
}
|
||||
public int readInteger(int index) {
|
||||
byte[] btarray = new byte[]{packetInBytes[index], packetInBytes[index + 1], packetInBytes[index + 2], packetInBytes[index + 3]};
|
||||
return java.nio.ByteBuffer.wrap(btarray).getInt();
|
||||
}
|
||||
|
||||
public int length() {
|
||||
return readInteger(0);
|
||||
}
|
||||
public int getBytesLength() {
|
||||
return packetInBytes.length;
|
||||
}
|
||||
|
||||
public byte[] readBytes(int length) {
|
||||
byte[] newbytes = new byte[length];
|
||||
for (int i = 0; i < (length); i++) {
|
||||
newbytes[i] = packetInBytes[i+ readIndex];
|
||||
}
|
||||
readIndex +=length;
|
||||
return newbytes;
|
||||
}
|
||||
public byte[] readBytes(int length, int index) {
|
||||
byte[] newbytes = new byte[length];
|
||||
for (int i = 0; i < (length); i++) {
|
||||
newbytes[i] = packetInBytes[i+index];
|
||||
}
|
||||
return newbytes;
|
||||
}
|
||||
|
||||
public long readLong() {
|
||||
byte[] btarray = readBytes(8);
|
||||
return java.nio.ByteBuffer.wrap(btarray).getLong();
|
||||
}
|
||||
public long readLong(int index) {
|
||||
byte[] btarray = readBytes(8, index);
|
||||
return java.nio.ByteBuffer.wrap(btarray).getLong();
|
||||
}
|
||||
|
||||
public String readString() {
|
||||
int length = readUshort();
|
||||
byte[] x = new byte[length];
|
||||
for (int i = 0; i < x.length; i++) x[i] = readByte();
|
||||
|
||||
try {
|
||||
return new String(x, "ISO-8859-1");
|
||||
} catch (UnsupportedEncodingException e) { }
|
||||
|
||||
return null;
|
||||
}
|
||||
public String readString(int index) {
|
||||
int length = readUshort(index);
|
||||
index+=2;
|
||||
byte[] x = new byte[length];
|
||||
for (int i = 0; i < x.length; i++) { x[i] = readByte(index); index++; }
|
||||
|
||||
try {
|
||||
return new String(x, "ISO-8859-1");
|
||||
} catch (UnsupportedEncodingException e) { }
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean readBoolean() {
|
||||
return (readByte() != 0);
|
||||
}
|
||||
public boolean readBoolean(int index) {
|
||||
return (readByte(index) != 0);
|
||||
}
|
||||
|
||||
|
||||
public HPacket replaceBoolean(int index, boolean b) {
|
||||
isEdited = true;
|
||||
packetInBytes[index] = b ? (byte)1 : (byte)0;
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceInt(int index, int i) {
|
||||
isEdited = true;
|
||||
ByteBuffer b = ByteBuffer.allocate(4).putInt(i);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
packetInBytes[index + j] = b.array()[j];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceByte(int index, byte b) {
|
||||
isEdited = true;
|
||||
packetInBytes[index] = b;
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceBytes(int index, byte[] bytes) {
|
||||
isEdited = true;
|
||||
int i = 0;
|
||||
while (index + i < packetInBytes.length && i < bytes.length) {
|
||||
replaceByte(index + i, bytes[i]);
|
||||
i++;
|
||||
}
|
||||
//
|
||||
// if (i < bytes.length) {
|
||||
// appendBytes(Arrays.copyOfRange(bytes, i, bytes.length));
|
||||
// fixLength();
|
||||
// }
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceUShort(int index, int ushort) {
|
||||
isEdited = true;
|
||||
ByteBuffer b = ByteBuffer.allocate(4).putInt(ushort);
|
||||
packetInBytes[index] = b.array()[2];
|
||||
packetInBytes[index + 1] = b.array()[3];
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceShort(int index, short s) {
|
||||
isEdited = true;
|
||||
ByteBuffer b = ByteBuffer.allocate(2).putShort(s);
|
||||
packetInBytes[index] = b.array()[0];
|
||||
packetInBytes[index + 1] = b.array()[1];
|
||||
return this;
|
||||
}
|
||||
public HPacket replaceString(int index, String s) {
|
||||
isEdited = true;
|
||||
byte[] sbytes = s.getBytes(StandardCharsets.ISO_8859_1);
|
||||
int mover = s.length() - readUshort(index);
|
||||
|
||||
if (mover != 0) {
|
||||
byte[] newPacket = Arrays.copyOf(packetInBytes, packetInBytes.length + mover);
|
||||
|
||||
if (mover > 0) {
|
||||
int i = newPacket.length - 1;
|
||||
while (i > index + mover + 2) {
|
||||
newPacket[i] = packetInBytes[i - mover];
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i = index + 2 + s.length();
|
||||
while (i < newPacket.length) {
|
||||
newPacket[i] = packetInBytes[i - mover];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
packetInBytes = newPacket;
|
||||
fixLength();
|
||||
}
|
||||
|
||||
replaceUShort(index, s.length());
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
packetInBytes[index + 2 + i] = sbytes[i];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//returns if done r not
|
||||
public boolean replaceFirstString(String oldS, String newS) {
|
||||
int i = 6;
|
||||
while (i < packetInBytes.length - 1 - oldS.length()) {
|
||||
if (readUshort(i) == oldS.length() && readString(i).equals(oldS)) {
|
||||
replaceString(i, newS);
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public HPacket replaceAllString(String oldS, String newS) {
|
||||
while (replaceFirstString(oldS, newS)) {}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public HPacket appendInt(int i) {
|
||||
isEdited = true;
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 4);
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(4).putInt(i);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
packetInBytes[packetInBytes.length - 4 + j] = byteBuffer.array()[j];
|
||||
}
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
public HPacket appendByte(byte b) {
|
||||
isEdited = true;
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 1);
|
||||
packetInBytes[packetInBytes.length - 1] = b;
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
public HPacket appendBytes(byte[] bytes) {
|
||||
isEdited = true;
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + bytes.length);
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
packetInBytes[packetInBytes.length - bytes.length + i] = bytes[i];
|
||||
}
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
public HPacket appendBoolean(boolean b) {
|
||||
isEdited = true;
|
||||
appendByte((byte)(b ? 1 : 0));
|
||||
return this;
|
||||
}
|
||||
public HPacket appendUShort(int ushort) {
|
||||
isEdited = true;
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 2);
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(4).putInt(ushort);
|
||||
for (int j = 2; j < 4; j++) {
|
||||
packetInBytes[packetInBytes.length - 4 + j] = byteBuffer.array()[j];
|
||||
}
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
public HPacket appendShort(short s) {
|
||||
isEdited = true;
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 2);
|
||||
ByteBuffer byteBuffer = ByteBuffer.allocate(2).putShort(s);
|
||||
for (int j = 0; j < 2; j++) {
|
||||
packetInBytes[packetInBytes.length - 2 + j] = byteBuffer.array()[j];
|
||||
}
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
public HPacket appendString(String s) {
|
||||
isEdited = true;
|
||||
appendUShort(s.length());
|
||||
appendBytes(s.getBytes(StandardCharsets.ISO_8859_1));
|
||||
return this;
|
||||
}
|
||||
|
||||
public HPacket removeFrom(int index) {
|
||||
return removeRange(index, packetInBytes.length - index);
|
||||
}
|
||||
public HPacket removeRange(int index, int length) {
|
||||
isEdited = true;
|
||||
for (int i = index; i < packetInBytes.length - length; i++) {
|
||||
packetInBytes[i] = packetInBytes[i + length];
|
||||
}
|
||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length - length);
|
||||
fixLength();
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isReplaced() {
|
||||
return isEdited;
|
||||
}
|
||||
|
||||
private void fixLength() {
|
||||
boolean remember = isEdited;
|
||||
replaceInt(0, packetInBytes.length - 4);
|
||||
isEdited = remember;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
HPacket packet = new HPacket("[0][0][0]4[15] [0]!PRODUCTION-201802201205-141713395[0][5]FLASH[0][0][0][1][0][0][0][0]");
|
||||
packet.replaceFirstString("FLASH", "HTML");
|
||||
System.out.println(packet);
|
||||
|
||||
}
|
||||
|
||||
}
|
7
src/main/protocol/StateChangeListener.java
Normal file
7
src/main/protocol/StateChangeListener.java
Normal file
@ -0,0 +1,7 @@
|
||||
package main.protocol;
|
||||
|
||||
public interface StateChangeListener {
|
||||
|
||||
void stateChanged(HConnection.State oldState, HConnection.State newState);
|
||||
|
||||
}
|
7
src/main/protocol/TrafficListener.java
Normal file
7
src/main/protocol/TrafficListener.java
Normal file
@ -0,0 +1,7 @@
|
||||
package main.protocol;
|
||||
|
||||
public interface TrafficListener {
|
||||
|
||||
void onCapture(HMessage message);
|
||||
|
||||
}
|
215
src/main/protocol/crypto/RC4.java
Normal file
215
src/main/protocol/crypto/RC4.java
Normal file
@ -0,0 +1,215 @@
|
||||
package main.protocol.crypto;
|
||||
/*
|
||||
* Copyright (C) 2003 Clarence Ho (clarence@clarenceho.net)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use of this software for non-profit, educational,
|
||||
* or persoanl purposes, in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the author nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* In case of using this software for other purposes not stated above,
|
||||
* please conact Clarence Ho (clarence@clarenceho.net) for permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY CLARENCE HO "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import main.protocol.HPacket;
|
||||
|
||||
/**
|
||||
* This is a simple implementation of the RC4 (tm) encryption algorithm. The
|
||||
* author implemented this class for some simple applications
|
||||
* that don't need/want/require the Sun's JCE framework.
|
||||
* <p>
|
||||
* But if you are looking for encryption algorithms for a
|
||||
* full-blown application,
|
||||
* it would be better to stick with Sun's JCE framework. You can find
|
||||
* a *free* JCE implementation with RC4 (tm) at
|
||||
* Cryptix (http://www.cryptix.org/).
|
||||
* <p>
|
||||
* Note that RC4 (tm) is a trademark of RSA Data Security, Inc.
|
||||
* Also, if you are within USA, you may need to acquire licenses from
|
||||
* RSA to use RC4.
|
||||
* Please check your local law. The author is not
|
||||
* responsible for any illegal use of this code.
|
||||
* <p>
|
||||
* @author Clarence Ho
|
||||
*/
|
||||
public class RC4 {
|
||||
|
||||
private byte state[] = new byte[256];
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
/**
|
||||
* Initializes the class with a string key. The length
|
||||
* of a normal key should be between 1 and 2048 bits. But
|
||||
* this method doens't check the length at all.
|
||||
*
|
||||
* @param key the encryption/decryption key
|
||||
*/
|
||||
public RC4(String key) throws NullPointerException {
|
||||
this(key.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the class with a byte array key. The length
|
||||
* of a normal key should be between 1 and 2048 bits. But
|
||||
* this method doens't check the length at all.
|
||||
*
|
||||
* @param key the encryption/decryption key
|
||||
*/
|
||||
public RC4(byte[] key) throws NullPointerException {
|
||||
|
||||
for (int i=0; i < 256; i++) {
|
||||
state[i] = (byte)i;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
int index1 = 0;
|
||||
int index2 = 0;
|
||||
|
||||
byte tmp;
|
||||
|
||||
if (key == null || key.length == 0) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
for (int i=0; i < 256; i++) {
|
||||
|
||||
index2 = ((key[index1] & 0xff) + (state[i] & 0xff) + index2) & 0xff;
|
||||
|
||||
tmp = state[i];
|
||||
state[i] = state[index2];
|
||||
state[index2] = tmp;
|
||||
|
||||
index1 = (index1 + 1) % key.length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* RC4 encryption/decryption.
|
||||
*
|
||||
* @param data the data to be encrypted/decrypted
|
||||
* @return the result of the encryption/decryption
|
||||
*/
|
||||
public byte[] rc4(String data) {
|
||||
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] tmp = data.getBytes();
|
||||
|
||||
this.rc4(tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* RC4 encryption/decryption.
|
||||
*
|
||||
* @param buf the data to be encrypted/decrypted
|
||||
* @return the result of the encryption/decryption
|
||||
*/
|
||||
public byte[] rc4(byte[] buf) {
|
||||
|
||||
//int lx = this.x;
|
||||
//int ly = this.y;
|
||||
|
||||
int xorIndex;
|
||||
byte tmp;
|
||||
|
||||
if (buf == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] result = new byte[buf.length];
|
||||
|
||||
for (int i=0; i < buf.length; i++) {
|
||||
|
||||
x = (x + 1) & 0xff;
|
||||
y = ((state[x] & 0xff) + y) & 0xff;
|
||||
|
||||
tmp = state[x];
|
||||
state[x] = state[y];
|
||||
state[y] = tmp;
|
||||
|
||||
xorIndex = ((state[x] &0xff) + (state[y] & 0xff)) & 0xff;
|
||||
result[i] = (byte)(buf[i] ^ state[xorIndex]);
|
||||
}
|
||||
|
||||
//this.x = lx;
|
||||
//this.y = ly;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void printKey() {
|
||||
System.out.println(new HPacket(state).toString());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
byte[] sharedKey = new byte[27];
|
||||
|
||||
RC4 p1 = new RC4(sharedKey);
|
||||
RC4 p2 = new RC4(sharedKey);
|
||||
|
||||
p1.printKey();
|
||||
p2.printKey();
|
||||
byte[] enc = p1.rc4("hallo".getBytes());
|
||||
System.out.println(new String(p2.rc4(enc)));
|
||||
|
||||
p1.printKey();
|
||||
p2.printKey();
|
||||
|
||||
enc = p1.rc4("hallo".getBytes());
|
||||
System.out.println(new String(p2.rc4(enc)));
|
||||
|
||||
p1.printKey();
|
||||
p2.printKey();
|
||||
|
||||
enc = p1.rc4("meneeeer dit zijn echt veel meer dan 27 characters dus latne we dit even proberen".getBytes());
|
||||
System.out.println(new String(p2.rc4(enc)));
|
||||
|
||||
p1.printKey();
|
||||
p2.printKey();
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// byte[] plainData = "abc123".getBytes();
|
||||
// byte[] key = "Key".getBytes();
|
||||
// RC4 rc4 = new RC4(key);
|
||||
// byte[] cipherData = rc4.rc4(plainData);
|
||||
// System.out.println("加密后: " + new String(cipherData));
|
||||
// byte[] _plainData = rc4.rc4(cipherData);
|
||||
// System.out.println("解密后: " + new String(_plainData));
|
||||
// System.out.println(Arrays.equals(plainData, _plainData));
|
||||
// }
|
||||
|
||||
}
|
410
src/main/protocol/memory/FlashClient.java
Normal file
410
src/main/protocol/memory/FlashClient.java
Normal file
@ -0,0 +1,410 @@
|
||||
package main.protocol.memory;
|
||||
|
||||
import main.irrelevant.Timer;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class FlashClient {
|
||||
|
||||
|
||||
public class MemorySnippet {
|
||||
long offset;
|
||||
byte[] data;
|
||||
|
||||
public MemorySnippet(long offset, byte[] data) {
|
||||
this.offset = offset;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public long getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
private int PID;
|
||||
private List<long[]> maps;
|
||||
|
||||
public static FlashClient create() {
|
||||
File folder = new File("/proc");
|
||||
FlashClient client = null;
|
||||
|
||||
do {
|
||||
File[] fileList = folder.listFiles();
|
||||
for (File file : fileList) {
|
||||
if (file.isDirectory() && MemoryUtils.stringIsNumeric(file.getName())) {
|
||||
String path = "/proc/" + file.getName() + "/cmdline";
|
||||
if (MemoryUtils.fileContainsString(path, "--ppapi-flash-args") ||
|
||||
MemoryUtils.fileContainsString(path, "plugin-container")) {
|
||||
client = new FlashClient();
|
||||
client.PID = Integer.parseInt(file.getName());
|
||||
client.maps = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (client == null);
|
||||
|
||||
|
||||
System.out.println("* Found flashclient process: " + client.PID);
|
||||
return client;
|
||||
}
|
||||
public void refreshMemoryMaps() {
|
||||
String filename = "/proc/"+this.PID+"/maps";
|
||||
BufferedReader reader;
|
||||
maps = new ArrayList<>();
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(filename));
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] split = line.split("[- ]");
|
||||
if (split[2].startsWith("rw")) { //if (split[2].startsWith("rw")) {
|
||||
|
||||
try {
|
||||
long start = Long.parseLong(split[0], 16);
|
||||
long end = Long.parseLong(split[1], 16);
|
||||
maps.add(new long[]{start, end});
|
||||
}
|
||||
catch (Exception e){
|
||||
//this is nothing really
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("* Found memory maps (amount: " + maps.size() + ")");
|
||||
}
|
||||
|
||||
public List<MemorySnippet> createMemorySnippetList () {
|
||||
refreshMemoryMaps();
|
||||
List<MemorySnippet> result = new ArrayList<>();
|
||||
|
||||
for (long[] map : maps) {
|
||||
long begin = map[0];
|
||||
long end = map[1];
|
||||
|
||||
MemorySnippet snippet = new MemorySnippet(begin, new byte[(int)(end - begin)] );
|
||||
result.add(snippet);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public void fetchMemory(List<MemorySnippet> snippets) {
|
||||
String memoryPath = "/proc/" + PID + "/mem";
|
||||
for (MemorySnippet snippet : snippets) {
|
||||
long begin = snippet.offset;
|
||||
try {
|
||||
RandomAccessFile raf = new RandomAccessFile(memoryPath, "r");
|
||||
raf.seek(begin);
|
||||
raf.read(snippet.getData());
|
||||
raf.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* can remove & add & edit maps of memorysnipperlist
|
||||
*/
|
||||
public void updateMapLocationsSnippetList(List<MemorySnippet> snippets) {
|
||||
refreshMemoryMaps();
|
||||
|
||||
List<MemorySnippet> list2 = new ArrayList<>();
|
||||
List<long[]> not_added = new ArrayList<>();
|
||||
|
||||
// readd all maps that stayed the same
|
||||
for (long[] map : maps) {
|
||||
//if was in snippetlist:
|
||||
boolean found = false;
|
||||
for (MemorySnippet snippet : snippets) {
|
||||
if (snippet.offset == map[0] && snippet.offset + snippet.getData().length == map[1]) {
|
||||
list2.add(snippet);
|
||||
snippets.remove(snippet);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
not_added.add(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < not_added.size(); i++) {
|
||||
long[] map = not_added.get(i);
|
||||
//find potential overlap snippet
|
||||
MemorySnippet snippet = new MemorySnippet(map[0], new byte[(int)(map[1] - map[0])]);
|
||||
byte[] data = snippet.getData();
|
||||
|
||||
for (MemorySnippet potential : snippets) {
|
||||
//if there is overlap
|
||||
if ((potential.offset >= map[0] && potential.offset < map[1]) ||
|
||||
(potential.offset + potential.getData().length >= map[0] && potential.offset + potential.getData().length< map[1]) ||
|
||||
(potential.offset < map[0] && potential.offset + potential.getData().length >= map[1]) ) {
|
||||
|
||||
int start = Math.max((int)(potential.offset - map[0]), 0);
|
||||
int offset2 = -(int)(potential.offset - map[0]);
|
||||
|
||||
for (int j = start; j < Math.min(map[1] - map[0], potential.getData().length - offset2); j++) {
|
||||
data[j] = potential.getData()[j+offset2];
|
||||
}
|
||||
}
|
||||
}
|
||||
list2.add(snippet);
|
||||
}
|
||||
|
||||
snippets.clear();
|
||||
for (MemorySnippet snippet : list2) {
|
||||
snippets.add(snippet);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* creates a new memorysnippet list of data that changed (or not) from the original list with a given left&right buffer
|
||||
*/
|
||||
public List<MemorySnippet> differentiate(List<MemorySnippet> original, boolean isChanged, int leftRightbytebuffer) {
|
||||
//fill a new memorysnippet list with live data
|
||||
List<MemorySnippet> upToDate = new ArrayList<>();
|
||||
for (MemorySnippet memorySnippet : original) {
|
||||
upToDate.add(new MemorySnippet(memorySnippet.getOffset(), new byte[memorySnippet.getData().length]));
|
||||
}
|
||||
fetchMemory(upToDate);
|
||||
|
||||
List<MemorySnippet> result = new ArrayList<>();
|
||||
|
||||
long totalBytes = 0;
|
||||
|
||||
for (int i = 0; i < original.size(); i++) {
|
||||
long offset = original.get(i).getOffset();
|
||||
byte[] old = original.get(i).getData();
|
||||
byte[] curr = upToDate.get(i).getData();
|
||||
|
||||
if (!isChanged) {
|
||||
// find all non-changed stuff and put in result
|
||||
long pre = offset;
|
||||
for (int j = 0; j < old.length; j++) {
|
||||
if (old[j] != curr[j]) {
|
||||
//calculate previous block length
|
||||
int len = j - ((int)(pre - offset));
|
||||
if (len >= leftRightbytebuffer && len > 0) {
|
||||
result.add(new MemorySnippet(pre, new byte[len]));
|
||||
totalBytes += len;
|
||||
}
|
||||
pre = offset + j + 1;
|
||||
}
|
||||
}
|
||||
int len = old.length - ((int)(pre - offset));
|
||||
if (len >= leftRightbytebuffer && len > 0) {
|
||||
result.add(new MemorySnippet(pre, new byte[len]));
|
||||
totalBytes += len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//find all changed stuff and put result
|
||||
long pre = offset;
|
||||
int downCount = -1; //if downCount reaches zero, buffer should be written out
|
||||
for (int j = 0; j < old.length; j++) {
|
||||
if (old[j] != curr[j]) {
|
||||
if (downCount <= 0) {
|
||||
pre = Math.max(offset, offset + j - leftRightbytebuffer);
|
||||
}
|
||||
downCount = leftRightbytebuffer;
|
||||
}
|
||||
else { downCount -= 1; }
|
||||
if (downCount == 0) {
|
||||
int len = j - ((int)(pre - offset));
|
||||
result.add(new MemorySnippet(pre, new byte[len]));
|
||||
totalBytes += len;
|
||||
}
|
||||
}
|
||||
int len = old.length - ((int)(pre - offset));
|
||||
if (downCount > 0 && len >= leftRightbytebuffer) {
|
||||
result.add(new MemorySnippet(pre, new byte[len]));
|
||||
totalBytes += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
fetchMemory(result);
|
||||
|
||||
System.out.println("totalbytes after diff: " + totalBytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//currently not being used functions:
|
||||
List<Long> searchOffsetForByteArray(byte[] toFind) {
|
||||
if (toFind.length == 0) return null;
|
||||
|
||||
System.out.println("*** Start searching for: " + new String(toFind));
|
||||
String memoryPath = "/proc/" + PID + "/mem";
|
||||
List<Long> results = new ArrayList<>();
|
||||
|
||||
Timer t = new Timer();
|
||||
t.start();
|
||||
|
||||
for (long[] map : maps) {
|
||||
long begin = map[0];
|
||||
long end = map[1];
|
||||
try {
|
||||
RandomAccessFile raf = new RandomAccessFile(memoryPath, "r");
|
||||
byte[] wholeBuffer = new byte[(int)(end - begin)];
|
||||
raf.seek(begin);
|
||||
raf.read(wholeBuffer);
|
||||
raf.close();
|
||||
|
||||
for (int i = 0; i < wholeBuffer.length; i++) {
|
||||
|
||||
int subIndex = 0;
|
||||
while (subIndex < toFind.length && wholeBuffer[i + subIndex] == toFind[subIndex]) subIndex++;
|
||||
|
||||
if (subIndex == toFind.length) {
|
||||
long result = (long)i + begin;
|
||||
results.add(result);
|
||||
System.out.println("* Found match for " + new String(toFind) + " at address: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("*** End searching for: " + new String(toFind) + " in " + t.delta() + "ms");
|
||||
return results;
|
||||
}
|
||||
List<Long> searchOffsetForString(String keyString) {
|
||||
return searchOffsetForByteArray(keyString.getBytes());
|
||||
}
|
||||
|
||||
public List<String> findSharedKey (List<MemorySnippet> snippets){
|
||||
|
||||
byte[] bounds = "09afAF".getBytes();
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
int size = 54;
|
||||
|
||||
for (MemorySnippet snippet : snippets) {
|
||||
int count = 0;
|
||||
byte[] data = snippet.getData();
|
||||
if (data.length >= size) {
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
byte b = data[i];
|
||||
if ((b >= bounds[0] && b <= bounds[1]) ||
|
||||
(b >= bounds[2] && b <= bounds[3]) ||
|
||||
(b >= bounds[4] && b <= bounds[5])) {
|
||||
count++;
|
||||
}
|
||||
else {
|
||||
count = 0;
|
||||
}
|
||||
if (count == size && (i + 1 == data.length || !((data[i+1] >= bounds[0] && data[i+1] <= bounds[1]) ||
|
||||
(data[i+1] >= bounds[2] && data[i+1] <= bounds[3]) ||
|
||||
(data[i+1] >= bounds[4] && data[i+1] <= bounds[5]))) ) {
|
||||
results.add(new String(Arrays.copyOfRange(data, i - size + 1, i + 1)) + " on location: " + (snippet.getOffset() + i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<String> findSharedKey2() {
|
||||
List<MemorySnippet> memorySnippets = new ArrayList<>();
|
||||
|
||||
int buff = 15000000;
|
||||
|
||||
long verystart = maps.get(0)[0];
|
||||
long veryend = maps.get(0)[1];
|
||||
|
||||
for (int i = 1; i < maps.size(); i++) {
|
||||
long[] map = maps.get(i);
|
||||
if (map[1] - veryend <= buff) {
|
||||
veryend = map[1];
|
||||
}
|
||||
else {
|
||||
memorySnippets.add(new MemorySnippet(verystart, new byte[(int)(veryend - verystart + buff)]));
|
||||
verystart = maps.get(i)[0];
|
||||
veryend = maps.get(i)[1];
|
||||
}
|
||||
}
|
||||
memorySnippets.add(new MemorySnippet(verystart, new byte[(int)(veryend - verystart + buff)]));
|
||||
|
||||
fetchMemory(memorySnippets);
|
||||
return findSharedKey(memorySnippets);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
public void pauseProcess() {
|
||||
String[] args = new String[] {"kill", "-STOP", PID+""};
|
||||
Process proc;
|
||||
try {
|
||||
proc = new ProcessBuilder(args).start();
|
||||
proc.waitFor();
|
||||
proc.destroy();
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
public void resumeProcess() {
|
||||
String[] args = new String[] {"kill", "-CONT", PID+""};
|
||||
Process proc;
|
||||
try {
|
||||
proc = new ProcessBuilder(args).start();
|
||||
proc.waitFor();
|
||||
proc.destroy();
|
||||
} catch (IOException | InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
FlashClient client = FlashClient.create();
|
||||
client.refreshMemoryMaps();
|
||||
|
||||
// List<Long> gameHostOccurences = client.searchOffsetForString("game-nl.habbo.com");
|
||||
// List<Long> rsaOccurences = client.searchOffsetForString("xIBlMDUyODA4YzFhYmVmNjlhMWE2MmMzOTYzOTZiODU5NTVlMmZmNTIy");
|
||||
// List<Long> occ = client.searchOffsetForString("sirjonasxx");
|
||||
|
||||
// List<MemorySnippet> l = client.createMemorySnippetList();
|
||||
// client.fetchMemory(l);
|
||||
// Thread.sleep(1000);
|
||||
// //what didnt change in the last 1000ms?
|
||||
// List<MemorySnippet> l2 = client.differentiate(l, false, 0);
|
||||
// Thread.sleep(1000);
|
||||
// //what changed in the last 1000ms?
|
||||
// List<MemorySnippet> l3 = client.differentiate(l2, true, 0);
|
||||
// Thread.sleep(1000);
|
||||
// //what didnt change in the last 1000ms?
|
||||
// List<MemorySnippet> l4 = client.differentiate(l3, false, 0);
|
||||
// Thread.sleep(1000);
|
||||
// //what changed in the last 1000ms?
|
||||
// List<MemorySnippet> l5 = client.differentiate(l4, true, 0);
|
||||
|
||||
// client.updateMapLocationsSnippetList(l);
|
||||
|
||||
List<String> res = client.findSharedKey2();
|
||||
System.out.println(res);
|
||||
|
||||
System.out.println("test");
|
||||
}
|
||||
|
||||
}
|
34
src/main/protocol/memory/MemoryUtils.java
Normal file
34
src/main/protocol/memory/MemoryUtils.java
Normal file
@ -0,0 +1,34 @@
|
||||
package main.protocol.memory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
class MemoryUtils {
|
||||
|
||||
static boolean stringIsNumeric(String str) {
|
||||
for (char c : str.toCharArray()) {
|
||||
if (c < '0' || c > '9') return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean fileContainsString(String path, String contains) {
|
||||
|
||||
try {
|
||||
List<String> lines = Files.readAllLines(new File(path).toPath());
|
||||
for (String line : lines) {
|
||||
if (line.contains(contains)) return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// process of specified path not running anymore
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
195
src/main/protocol/memory/Rc4Obtainer.java
Normal file
195
src/main/protocol/memory/Rc4Obtainer.java
Normal file
@ -0,0 +1,195 @@
|
||||
package main.protocol.memory;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import main.protocol.HPacket;
|
||||
import main.protocol.packethandler.BufferListener;
|
||||
import main.protocol.packethandler.IncomingHandler;
|
||||
import main.protocol.packethandler.OutgoingHandler;
|
||||
import main.protocol.memory.FlashClient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Rc4Obtainer {
|
||||
|
||||
public static Rc4Obtainer rc4Obtainer = null;
|
||||
public static void initialize() {
|
||||
rc4Obtainer = new Rc4Obtainer();
|
||||
rc4Obtainer.client = FlashClient.create();
|
||||
}
|
||||
|
||||
FlashClient client = null;
|
||||
OutgoingHandler outgoingHandler = null;
|
||||
IncomingHandler incomingHandler = null;
|
||||
|
||||
private Rc4Obtainer() {
|
||||
|
||||
}
|
||||
|
||||
public void setOutgoingHandler(OutgoingHandler handler) {
|
||||
outgoingHandler = handler;
|
||||
handler.addBufferListener(() -> {
|
||||
if (handler.getCurrentIndex() >= 3) hasChangedFromLastCheck = true;
|
||||
if (!hashappened1 && handler.getCurrentIndex() == 3) {
|
||||
hashappened1 = true;
|
||||
onSendFirstEncryptedMessage();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setIncomingHandler(IncomingHandler handler) {
|
||||
incomingHandler = handler;
|
||||
handler.addBufferListener(() -> {
|
||||
if (!hashappened2 && handler.getCurrentIndex() == 1) {
|
||||
hashappened2 = true;
|
||||
onReceivePubKey();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<FlashClient.MemorySnippet> fullmemorybeforekey = null;
|
||||
private boolean hasChangedFromLastCheck = false;
|
||||
|
||||
private boolean hashappened2 = false;
|
||||
private void onReceivePubKey() {
|
||||
incomingHandler.block();
|
||||
new Thread(() -> {
|
||||
|
||||
System.out.println("[+] receive pubkey");
|
||||
client.pauseProcess();
|
||||
|
||||
fullmemorybeforekey = client.createMemorySnippetList();
|
||||
client.fetchMemory(fullmemorybeforekey);
|
||||
|
||||
System.out.println("[-] receive pubkey");
|
||||
|
||||
client.resumeProcess();
|
||||
incomingHandler.unblock();
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
private boolean hashappened1 = false;
|
||||
private void onSendFirstEncryptedMessage() {
|
||||
incomingHandler.block();
|
||||
outgoingHandler.block();
|
||||
new Thread(() -> {
|
||||
|
||||
System.out.println("[+] send encrypted");
|
||||
client.pauseProcess();
|
||||
client.updateMapLocationsSnippetList(fullmemorybeforekey);
|
||||
client.resumeProcess();
|
||||
|
||||
List<FlashClient.MemorySnippet> diff = searchForPossibleRC4Tables(fullmemorybeforekey);
|
||||
System.out.println("size: " + getTotalBytesLengthOfDiff(diff));
|
||||
for (int i = 0; i < 20; i++) {
|
||||
// if (i % 2 == 1) {
|
||||
// incomingHandler.sendToStream(new HPacket(3631).toBytes());
|
||||
// }
|
||||
sleep(200);
|
||||
boolean rem = hasChangedFromLastCheck;
|
||||
diff = searchForPossibleRC4Tables(diff);
|
||||
System.out.println("size: " + getTotalBytesLengthOfDiff(diff) + " and was changed: " + rem);
|
||||
}
|
||||
|
||||
|
||||
System.out.println("[-] send encrypted");
|
||||
outgoingHandler.unblock();
|
||||
incomingHandler.unblock();
|
||||
}).start();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private List<FlashClient.MemorySnippet> searchForPossibleRC4Tables(List<FlashClient.MemorySnippet> snippets) {
|
||||
List<FlashClient.MemorySnippet> result;
|
||||
client.pauseProcess();
|
||||
if (hasChangedFromLastCheck) {
|
||||
result = client.differentiate(snippets, true, 255);
|
||||
hasChangedFromLastCheck = false;
|
||||
}
|
||||
else {
|
||||
result = client.differentiate(snippets, false, 4);
|
||||
}
|
||||
client.resumeProcess();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private long getTotalBytesLengthOfDiff(List<FlashClient.MemorySnippet> snippets) {
|
||||
long tot = 0;
|
||||
for (FlashClient.MemorySnippet snippet : snippets) {
|
||||
tot += (snippet.getData().length);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
private void sleep(int ms) {
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// System.out.println("[+] receive pubkey");
|
||||
// incomingHandler.block();
|
||||
// client.pauseProcess();
|
||||
// fullmemorybeforekey = client.createMemorySnippetList();
|
||||
// client.fetchMemory(fullmemorybeforekey);
|
||||
// System.out.println("[-] receive pubkey");
|
||||
// incomingHandler.unblock();
|
||||
// client.resumeProcess();
|
||||
|
||||
// client.pauseProcess();
|
||||
//
|
||||
// client.refreshMemoryMaps();
|
||||
// List<String> result = client.findSharedKey2();
|
||||
// System.out.println("result size: "+ result);
|
||||
//
|
||||
// client.resumeProcess();
|
||||
|
||||
// System.out.println("[+] send encrypted");
|
||||
// client.pauseProcess();
|
||||
// client.updateMapLocationsSnippetList(fullmemorybeforekey);
|
||||
//
|
||||
// List<FlashClient.MemorySnippet> diff = client.differentiate(fullmemorybeforekey, true, 54);
|
||||
//
|
||||
// List<String> results = client.findSharedKey(diff);
|
||||
// System.out.println("results: " +results.size());
|
||||
// for (String s : results) {
|
||||
// System.out.println(s);
|
||||
// }
|
||||
// System.out.println("[-] send encrypted");
|
||||
// client.resumeProcess();
|
||||
|
||||
// payloadBuffer.push(buffer);
|
||||
// buffer = new byte[]{};
|
||||
// tempBlockIncoming = true;
|
||||
// client = FlashClient.create();
|
||||
// client.pauseProcess();
|
||||
// fullmemoryb4publickey = client.createMemorySnippetList();
|
||||
// client.fetchMemory(fullmemoryb4publickey);
|
||||
// client.resumeProcess();
|
||||
|
||||
|
||||
|
||||
// if (!doneFlash) {
|
||||
// tempBlockEncrypted = true;
|
||||
// FlashClient client = IncomingHandler.client;
|
||||
// List<FlashClient.MemorySnippet> mem = IncomingHandler.fullmemoryb4publickey;
|
||||
// client.pauseProcess();
|
||||
// client.updateMapLocationsSnippetList(mem);
|
||||
// List<FlashClient.MemorySnippet> diff = client.differentiate(mem, true, 54);
|
||||
// IncomingHandler.fullmemoryb4publickey = null;
|
||||
// List<String> results = client.findSharedKey(diff);
|
||||
// System.out.println("results: " +results.size());
|
||||
// for (String s : results) {
|
||||
// System.out.println(s);
|
||||
// }
|
||||
// client.resumeProcess();
|
||||
// tempBlockEncrypted = false;
|
||||
// IncomingHandler.tempBlockIncoming = false;
|
||||
// doneFlash = true;
|
||||
// }
|
||||
}
|
8
src/main/protocol/packethandler/BufferListener.java
Normal file
8
src/main/protocol/packethandler/BufferListener.java
Normal file
@ -0,0 +1,8 @@
|
||||
package main.protocol.packethandler;
|
||||
|
||||
|
||||
public interface BufferListener {
|
||||
|
||||
void act();
|
||||
|
||||
}
|
100
src/main/protocol/packethandler/Handler.java
Normal file
100
src/main/protocol/packethandler/Handler.java
Normal file
@ -0,0 +1,100 @@
|
||||
package main.protocol.packethandler;
|
||||
|
||||
import main.protocol.HMessage;
|
||||
import main.protocol.TrafficListener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Handler {
|
||||
|
||||
volatile PayloadBuffer payloadBuffer = new PayloadBuffer();
|
||||
volatile OutputStream out;
|
||||
private volatile Object[] listeners = null; //get notified on packet send
|
||||
private volatile boolean isTempBlocked = false;
|
||||
volatile boolean isDataStream = false;
|
||||
volatile int currentIndex = 0;
|
||||
|
||||
|
||||
public Handler(OutputStream outputStream) {
|
||||
out = outputStream;
|
||||
}
|
||||
|
||||
public boolean isDataStream() {return isDataStream;}
|
||||
public void setAsDataStream() {
|
||||
isDataStream = true;
|
||||
}
|
||||
|
||||
public void act(byte[] buffer, Object[] listeners) throws IOException {
|
||||
this.listeners = listeners;
|
||||
|
||||
if (isDataStream) {
|
||||
payloadBuffer.push(buffer);
|
||||
notifyBufferListeners();
|
||||
|
||||
if (!isTempBlocked) {
|
||||
flush();
|
||||
}
|
||||
else {
|
||||
if (this instanceof OutgoingHandler) {
|
||||
System.out.println("blocked outgoing bytes with size: "+ buffer.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
out.write(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public void block() {
|
||||
isTempBlocked = true;
|
||||
}
|
||||
public void unblock() {
|
||||
try {
|
||||
flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
isTempBlocked = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* LISTENERS CAN EDIT THE MESSAGE BEFORE BEING SENT
|
||||
* @param message
|
||||
*/
|
||||
void notifyListeners(HMessage message) {
|
||||
for (TrafficListener listener : (List<TrafficListener>)listeners[0]) {
|
||||
listener.onCapture(message);
|
||||
}
|
||||
for (TrafficListener listener : (List<TrafficListener>)listeners[1]) {
|
||||
listener.onCapture(message);
|
||||
}
|
||||
for (TrafficListener listener : (List<TrafficListener>)listeners[2]) {
|
||||
listener.onCapture(message);
|
||||
}
|
||||
}
|
||||
public abstract void sendToStream(byte[] buffer);
|
||||
|
||||
public abstract void flush() throws IOException;
|
||||
|
||||
|
||||
|
||||
private List<BufferListener> bufferListeners = new ArrayList<>();
|
||||
public void addBufferListener(BufferListener listener) {
|
||||
bufferListeners.add(listener);
|
||||
}
|
||||
public void removeBufferListener(BufferListener listener) {
|
||||
bufferListeners.remove(listener);
|
||||
}
|
||||
private void notifyBufferListeners() {
|
||||
for (int i = bufferListeners.size() - 1; i >= 0; i -= 1) {
|
||||
bufferListeners.get(i).act();
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentIndex() {
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
46
src/main/protocol/packethandler/IncomingHandler.java
Normal file
46
src/main/protocol/packethandler/IncomingHandler.java
Normal file
@ -0,0 +1,46 @@
|
||||
package main.protocol.packethandler;
|
||||
|
||||
import main.protocol.HMessage;
|
||||
import main.protocol.HPacket;
|
||||
import main.protocol.memory.Rc4Obtainer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class IncomingHandler extends Handler {
|
||||
|
||||
public IncomingHandler(OutputStream outputStream) {
|
||||
super(outputStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsDataStream() {
|
||||
super.setAsDataStream();
|
||||
Rc4Obtainer.rc4Obtainer.setIncomingHandler(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToStream(byte[] buffer) {
|
||||
try {
|
||||
out.write(buffer);
|
||||
out.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
HPacket[] hpackets = payloadBuffer.receive();
|
||||
|
||||
for (HPacket hpacket : hpackets){
|
||||
HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOCLIENT, currentIndex);
|
||||
notifyListeners(hMessage);
|
||||
|
||||
if (!hMessage.isBlocked()) {
|
||||
out.write(hMessage.getPacket().toBytes());
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
}
|
67
src/main/protocol/packethandler/OutgoingHandler.java
Normal file
67
src/main/protocol/packethandler/OutgoingHandler.java
Normal file
@ -0,0 +1,67 @@
|
||||
package main.protocol.packethandler;
|
||||
|
||||
import main.protocol.HMessage;
|
||||
import main.protocol.HPacket;
|
||||
import main.protocol.memory.Rc4Obtainer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class OutgoingHandler extends Handler {
|
||||
|
||||
private final static int encryptOffset = 3; //all packets with index < 3 aren't encrypted
|
||||
|
||||
public OutgoingHandler(OutputStream outputStream) {
|
||||
super(outputStream);
|
||||
}
|
||||
|
||||
private void dataStreamCheck(byte[] buffer) {
|
||||
if (!isDataStream) {
|
||||
HPacket hpacket = new HPacket(buffer);
|
||||
isDataStream = (hpacket.getBytesLength() > 6 && hpacket.headerId() == 4000 && hpacket.headerId() == 4000);
|
||||
if (isDataStream) {
|
||||
Rc4Obtainer.initialize();
|
||||
Rc4Obtainer.rc4Obtainer.setOutgoingHandler(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void act(byte[] buffer, Object[] listeners) throws IOException {
|
||||
dataStreamCheck(buffer);
|
||||
super.act(buffer, listeners);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToStream(byte[] buffer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
|
||||
if (currentIndex < encryptOffset) {
|
||||
HPacket[] hpackets = payloadBuffer.receive();
|
||||
for (HPacket hpacket : hpackets){
|
||||
HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOSERVER, currentIndex);
|
||||
notifyListeners(hMessage);
|
||||
if (!hMessage.isBlocked()) {
|
||||
out.write(hMessage.getPacket().toBytes());
|
||||
}
|
||||
currentIndex ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentIndex >= encryptOffset) {
|
||||
if (payloadBuffer.peak().length > 0) {
|
||||
HPacket packet = new HPacket(payloadBuffer.forceClear());
|
||||
HMessage hMessage = new HMessage(packet, HMessage.Side.TOSERVER, currentIndex);
|
||||
|
||||
notifyListeners(hMessage);
|
||||
out.write(packet.toBytes());
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
59
src/main/protocol/packethandler/PayloadBuffer.java
Normal file
59
src/main/protocol/packethandler/PayloadBuffer.java
Normal file
@ -0,0 +1,59 @@
|
||||
package main.protocol.packethandler;
|
||||
|
||||
import main.protocol.HPacket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PayloadBuffer {
|
||||
|
||||
private byte[] buffer = new byte[0];
|
||||
|
||||
public HPacket[] pushAndReceive(byte[] tcpData){
|
||||
push(tcpData);
|
||||
return receive();
|
||||
}
|
||||
public void push(byte[] tcpData) {
|
||||
buffer = buffer.length == 0 ? tcpData : combineByteArrays(buffer, tcpData);
|
||||
}
|
||||
public HPacket[] receive() {
|
||||
if (buffer.length < 6) return new HPacket[0];
|
||||
|
||||
HPacket total = new HPacket(buffer);
|
||||
if (total.getBytesLength() - 4 == total.length()) {
|
||||
buffer = new byte[0];
|
||||
return new HPacket[]{total};
|
||||
}
|
||||
else if (total.getBytesLength() - 4 > total.length()) {
|
||||
ArrayList<HPacket> all = new ArrayList<>();
|
||||
while (total.getBytesLength() >= 4 && total.getBytesLength() - 4 >= total.length()){
|
||||
all.add(new HPacket(Arrays.copyOfRange(buffer, 0, total.length() + 4)));
|
||||
buffer = Arrays.copyOfRange(buffer, total.length() + 4, buffer.length);
|
||||
total = new HPacket(buffer);
|
||||
}
|
||||
return all.toArray(new HPacket[all.size()]);
|
||||
}
|
||||
else {
|
||||
return new HPacket[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private byte[] combineByteArrays(byte[] arr1, byte[] arr2) {
|
||||
byte[] combined = new byte[arr1.length + arr2.length];
|
||||
System.arraycopy(arr1,0,combined,0 ,arr1.length);
|
||||
System.arraycopy(arr2,0,combined,arr1.length,arr2.length);
|
||||
return combined;
|
||||
}
|
||||
|
||||
|
||||
public byte[] peak() {
|
||||
return buffer;
|
||||
}
|
||||
public byte[] forceClear() {
|
||||
byte[] buff = buffer;
|
||||
buffer = new byte[0];
|
||||
return buff;
|
||||
}
|
||||
|
||||
}
|
39
src/main/ui/G-Earth.fxml
Normal file
39
src/main/ui/G-Earth.fxml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Tab?>
|
||||
<?import javafx.scene.control.TabPane?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<!--maxHeight="19.0" minHeight="19.0"-->
|
||||
|
||||
<VBox xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ui.GEarthController">
|
||||
<Pane fx:id="mover" maxHeight="0.0" minHeight="0.0" prefWidth="200.0" />
|
||||
<TabPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="295.0" prefWidth="565.0" tabClosingPolicy="UNAVAILABLE">
|
||||
<tabs>
|
||||
<Tab text="Connection">
|
||||
<content>
|
||||
<fx:include fx:id="connection" source="connection/Connection.fxml" />
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab text="Logger">
|
||||
<content>
|
||||
<fx:include fx:id="logger" source="logger/Logger.fxml" />
|
||||
</content></Tab>
|
||||
<Tab text="Injection">
|
||||
<content>
|
||||
<fx:include fx:id="injection" source="injection/Injection.fxml" />
|
||||
</content></Tab>
|
||||
<Tab text="Tools">
|
||||
<content>
|
||||
<fx:include fx:id="tools" source="tools/Tools.fxml" />
|
||||
</content>
|
||||
</Tab>
|
||||
<Tab disable="true" text="Scheduler" />
|
||||
<Tab disable="true" text="Settings" />
|
||||
<Tab disable="true" text="Extensions" />
|
||||
<Tab disable="true" text="Info" />
|
||||
</tabs>
|
||||
</TabPane>
|
||||
|
||||
</VBox>
|
87
src/main/ui/GEarthController.java
Normal file
87
src/main/ui/GEarthController.java
Normal file
@ -0,0 +1,87 @@
|
||||
package main.ui;
|
||||
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.stage.Stage;
|
||||
import main.protocol.HConnection;
|
||||
import main.ui.connection.ConnectionForm;
|
||||
import main.ui.injection.InjectionForm;
|
||||
import main.ui.logger.LoggerForm;
|
||||
import main.ui.tools.ToolsForm;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class GEarthController {
|
||||
|
||||
private Stage stage = null;
|
||||
private volatile HConnection hConnection;
|
||||
|
||||
public ConnectionForm connectionController;
|
||||
public InjectionForm injectionController;
|
||||
public LoggerForm loggerController;
|
||||
public ToolsForm toolsController;
|
||||
public Pane mover;
|
||||
|
||||
public GEarthController() {
|
||||
hConnection = new HConnection();
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
connectionController.setParentController(this);
|
||||
injectionController.setParentController(this);
|
||||
loggerController.setParentController(this);
|
||||
toolsController.setParentController(this);
|
||||
//custom header bar
|
||||
// final Point[] startpos = {null};
|
||||
// final Double[] xx = {0.0};
|
||||
// final Double[] yy = {0.0};
|
||||
// final Boolean[] isMoving = {false};
|
||||
//
|
||||
// mover.addEventHandler(MouseEvent.MOUSE_PRESSED,
|
||||
// event -> {
|
||||
// startpos[0] = MouseInfo.getPointerInfo().getLocation();
|
||||
// xx[0] = stage.getX();
|
||||
// yy[0] = stage.getY();
|
||||
// isMoving[0] = true;
|
||||
// });
|
||||
//
|
||||
// mover.addEventHandler(MouseEvent.MOUSE_RELEASED,
|
||||
// event -> {
|
||||
// isMoving[0] = false;
|
||||
// });
|
||||
//
|
||||
//
|
||||
// mover.setOnMouseDragged(event -> {
|
||||
// if (isMoving[0]) {
|
||||
// Point now = MouseInfo.getPointerInfo().getLocation();
|
||||
// double diffX = now.getX() - startpos[0].getX();
|
||||
// double diffY = now.getY() - startpos[0].getY();
|
||||
// stage.setX(xx[0] + diffX);
|
||||
// stage.setY(yy[0] + diffY);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
public void setStage(Stage stage) {
|
||||
this.stage = stage;
|
||||
}
|
||||
public Stage getStage() {
|
||||
return stage;
|
||||
}
|
||||
|
||||
HConnection getHConnection() {
|
||||
return hConnection;
|
||||
}
|
||||
void writeToLog(javafx.scene.paint.Color color, String text) {
|
||||
loggerController.miniLogText(color, text);
|
||||
}
|
||||
|
||||
|
||||
public void abort() {
|
||||
hConnection.abort();
|
||||
}
|
||||
|
||||
}
|
32
src/main/ui/SubForm.java
Normal file
32
src/main/ui/SubForm.java
Normal file
@ -0,0 +1,32 @@
|
||||
package main.ui;
|
||||
|
||||
|
||||
import main.protocol.HConnection;
|
||||
import main.protocol.HMessage;
|
||||
import main.protocol.HPacket;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class SubForm {
|
||||
|
||||
GEarthController parentController;
|
||||
|
||||
public void setParentController(GEarthController controller) {
|
||||
parentController = controller;
|
||||
onParentSet();
|
||||
}
|
||||
|
||||
|
||||
//abstract
|
||||
protected void onParentSet() {
|
||||
|
||||
}
|
||||
|
||||
protected HConnection getHConnection() {
|
||||
return parentController.getHConnection();
|
||||
}
|
||||
protected void writeToLog(javafx.scene.paint.Color color, String text) {
|
||||
parentController.writeToLog(color, text);
|
||||
}
|
||||
|
||||
}
|
893
src/main/ui/bootstrap3.css
vendored
Normal file
893
src/main/ui/bootstrap3.css
vendored
Normal file
@ -0,0 +1,893 @@
|
||||
.root {
|
||||
-fx-body-color : #F5F5F5;
|
||||
-fx-outer-border : #cecece;
|
||||
}
|
||||
.button,.menu-button,.toggle-button,.split-menu-button {
|
||||
-fx-font-size: 14;
|
||||
-fx-background-radius: 4;
|
||||
-fx-border-radius: 4;
|
||||
-fx-pref-height: 30;
|
||||
-fx-min-width: 30;
|
||||
}
|
||||
.button,.menu-button,.split-menu-button,.toggle-button,.number-button {
|
||||
-fx-background-insets: 0, 0, -1, 0;
|
||||
}
|
||||
|
||||
.split-menu-button > .label {
|
||||
-fx-border-radius: 4 0 0 4;
|
||||
-fx-background-radius: 3 0 0 3;
|
||||
}
|
||||
|
||||
.split-menu-button > .arrow-button {
|
||||
-fx-border-radius: 0 4 4 0;
|
||||
-fx-background-radius: 0 3 3 0;
|
||||
}
|
||||
|
||||
.lg {
|
||||
-fx-min-height: 46;
|
||||
-fx-max-height: 46;
|
||||
-fx-font-size: 18;
|
||||
}
|
||||
|
||||
.sm {
|
||||
-fx-min-height: 30;
|
||||
-fx-max-height: 30;
|
||||
}
|
||||
|
||||
.xs {
|
||||
-fx-min-height: 22;
|
||||
-fx-max-height: 22;
|
||||
-fx-font-size: 10;
|
||||
}
|
||||
|
||||
.primary .arrow,
|
||||
.success .arrow,
|
||||
.info .arrow,
|
||||
.warning .arrow,
|
||||
.danger .arrow {
|
||||
-fx-background-color: transparent, white;
|
||||
}
|
||||
|
||||
.primary > .label,
|
||||
.success > .label,
|
||||
.info > .label,
|
||||
.warning > .label,
|
||||
.danger > .label {
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
-fx-min-width: 80;
|
||||
}
|
||||
|
||||
/*positions*/
|
||||
/*first*/
|
||||
.button.first, .menu-button.first, .toggle-button.first, .text-field.first, .text-area.first {
|
||||
-fx-border-radius: 4 0 0 4;
|
||||
-fx-background-radius: 4 0 0 4;
|
||||
}
|
||||
|
||||
.split-menu-button.first > .arrow-button, .split-menu-button.middle > .arrow-button {
|
||||
-fx-border-radius: 0;
|
||||
-fx-background-radius: 0;
|
||||
}
|
||||
|
||||
VBox > .button.first,
|
||||
VBox > .menu-button.first,
|
||||
VBox > .toggle-button.first,
|
||||
VBox > .split-menu-button.first,
|
||||
VBox > .text-field.first,
|
||||
VBox > .text-area.first {
|
||||
-fx-border-radius: 4 4 0 0;
|
||||
-fx-background-radius: 4 4 0 0;
|
||||
}
|
||||
|
||||
VBox > .split-menu-button.first > .label {
|
||||
-fx-border-radius: 4 0 0 0;
|
||||
-fx-background-radius: 3 0 0 0;
|
||||
}
|
||||
VBox > .split-menu-button.first > .arrow-button {
|
||||
-fx-border-radius: 0 4 0 0;
|
||||
-fx-background-radius: 0 3 0 0;
|
||||
}
|
||||
/*middle*/
|
||||
.middle {
|
||||
-fx-border-radius: 0;
|
||||
-fx-background-radius: 0;
|
||||
}
|
||||
|
||||
/*last*/
|
||||
.split-menu-button.middle > .label, .split-menu-button.last > .label {
|
||||
-fx-border-radius: 0;
|
||||
-fx-background-radius: 0;
|
||||
}
|
||||
|
||||
.split-menu-button.last {
|
||||
-fx-border-radius: 0 4 4 0;
|
||||
-fx-background-radius: 0 4 4 0;
|
||||
}
|
||||
|
||||
.button.middle, .text-field.middle, .text-area.middle, .split-menu-button.middle, .toggle-button.middle {
|
||||
-fx-border-radius: 0;
|
||||
-fx-background-radius: 0;
|
||||
}
|
||||
|
||||
.button.last, .text-field.last, .text-area.last, .split-menu-button.last, .toggle-button.last, .menu-button.last {
|
||||
-fx-border-radius: 0 4 4 0;
|
||||
-fx-background-radius: 0 4 4 0;
|
||||
}
|
||||
VBox > .button.last,
|
||||
VBox > .menu-button.last,
|
||||
VBox > .toggle-button.last,
|
||||
VBox > .split-menu-button.last,
|
||||
VBox > .text-field.last,
|
||||
VBox > .text-area.last {
|
||||
-fx-border-radius: 0 0 4 4;
|
||||
-fx-background-radius: 0 0 4 4;
|
||||
}
|
||||
|
||||
VBox > .split-menu-button.last > .label {
|
||||
-fx-border-radius: 0 0 0 4;
|
||||
-fx-background-radius: 0 0 0 3;
|
||||
}
|
||||
VBox > .split-menu-button.last > .arrow-button {
|
||||
-fx-border-radius: 0 0 4 0;
|
||||
-fx-background-radius: 0 0 3 0;
|
||||
}
|
||||
|
||||
/*button styles*/
|
||||
|
||||
/*default button settings*/
|
||||
|
||||
/*bgcolor setting*/
|
||||
.color-picker,.date-picker > .arrow-button,
|
||||
.number-button,.left-arrow-button,.right-arrow-button,
|
||||
.button,.split-menu-button,.toggle-button,.menu-button,
|
||||
.font-menu-button, .split-menu-button > .label, .split-menu-button > .arrow-button {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
.color-picker,.date-picker > .arrow-button,
|
||||
.button,.menu-button,.toggle-button,.number-button,.left-arrow-button,.right-arrow-button,
|
||||
.font-menu-button,
|
||||
.split-menu-button > .label,.split-menu-button > .arrow-button {
|
||||
-fx-border-color: #cccccc;
|
||||
-fx-text-fill: #333333;
|
||||
}
|
||||
/*just for the special split menu button*/
|
||||
.split-menu-button > .label {
|
||||
-fx-border-width: 1 0 1 1;
|
||||
}
|
||||
/*for date picker arrow button*/
|
||||
.date-picker > .arrow-button {
|
||||
-fx-border-radius: 0 4 4 0;
|
||||
}
|
||||
.combo-box > .arrow-button, .choice-box > .arrow-button {
|
||||
-fx-border-width: 0;
|
||||
}
|
||||
/*hover state*/
|
||||
.color-picker:hover,
|
||||
.date-picker:hover > .arrow-button,
|
||||
.combo-box:hover,.choice-box:hover,
|
||||
.number-button:hover,.left-arrow-button:hover,.right-arrow-button:hover,
|
||||
.button:hover,.menu-button:hover,.toggle-button:hover,
|
||||
.font-menu-button:hover,
|
||||
.split-menu-button > .label:hover, .split-menu-button > .arrow-button:hover {
|
||||
-fx-background-color: #e6e6e6;
|
||||
-fx-border-color: #acacac;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.color-picker:pressed,.color-picker:selected,
|
||||
.number-button:pressed,.number-button:selected,
|
||||
.date-picker:pressed > .arrow-button,
|
||||
.combo-box:pressed > .arrow-button,.combo-box:selected > .arrow-button,
|
||||
.choice-box:pressed > .arrow-button,.choice-box:selected > .arrow-button,
|
||||
.font-menu-button:pressed,.font-menu-button:selected,
|
||||
.left-arrow-button:pressed,.left-arrow-button:selected,
|
||||
.right-arrow-button:pressed,.right-arrow-button:selected,
|
||||
.button:pressed, .button:selected,.menu-button:pressed,.menu-button:selected
|
||||
,.toggle-button:pressed,.toggle-button:selected,
|
||||
.split-menu-button:pressed > .label, .split-menu-button > .arrow-button:pressed {
|
||||
-fx-background-color: #e6e6e6;
|
||||
-fx-border-color: #acacac;
|
||||
-fx-effect: innershadow(gaussian, #adadad, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/*primary*/
|
||||
|
||||
.button.primary,.split-menu-button.primary,.toggle-button.primary,.menu-button.primary,
|
||||
.split-menu-button.primary > .label, .split-menu-button.primary > .arrow-button {
|
||||
-fx-background-color: #337ab7;
|
||||
}
|
||||
|
||||
.button.primary,.menu-button.primary,.toggle-button.primary,
|
||||
.split-menu-button.primary > .label,.split-menu-button.primary > .arrow-button {
|
||||
-fx-border-color: #2e6da4;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
/*hover state*/
|
||||
.button.primary:hover,.menu-button.primary:hover,.toggle-button.primary:hover,
|
||||
.split-menu-button.primary > .label:hover, .split-menu-button.primary > .arrow-button:hover {
|
||||
-fx-border-color: #204d74;
|
||||
-fx-background-color: #286090;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.button.primary:pressed, .button.primary:selected,
|
||||
.menu-button.primary:pressed,.menu-button.primary:selected
|
||||
,.toggle-button.primary:pressed,.toggle-button.primary:selected,
|
||||
.split-menu-button.primary:pressed > .label, .split-menu-button.primary > .arrow-button:pressed {
|
||||
-fx-background-color: #286090;
|
||||
-fx-border-color: #204d74;
|
||||
-fx-effect: innershadow(gaussian, #204d74, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/*success*/
|
||||
|
||||
.button.success,.split-menu-button.success,.toggle-button.success,.menu-button.success,
|
||||
.split-menu-button.success > .label, .split-menu-button.success > .arrow-button {
|
||||
-fx-background-color: #5cb85c;
|
||||
}
|
||||
|
||||
.button.success,.menu-button.success,.toggle-button.success,
|
||||
.split-menu-button.success > .label,.split-menu-button.success > .arrow-button {
|
||||
-fx-border-color: #4cae4c;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
/*hover state*/
|
||||
.button.success:hover,.menu-button.success:hover,.toggle-button.success:hover,
|
||||
.split-menu-button.success > .label:hover, .split-menu-button.success > .arrow-button:hover {
|
||||
-fx-border-color: #398439;
|
||||
-fx-background-color: #449d44;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.button.success:pressed, .button.success:selected,
|
||||
.menu-button.success:pressed,.menu-button.success:selected
|
||||
,.toggle-button.success:pressed,.toggle-button.success:selected,
|
||||
.split-menu-button.success:pressed > .label, .split-menu-button.success > .arrow-button:pressed {
|
||||
-fx-background-color: #449d44;
|
||||
-fx-border-color: #398439;
|
||||
-fx-effect: innershadow(gaussian, #398439, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/*info*/
|
||||
|
||||
.button.info,.split-menu-button.info,.toggle-button.info,.menu-button.info,
|
||||
.split-menu-button.info > .label, .split-menu-button.info > .arrow-button {
|
||||
-fx-background-color: #5bc0de;
|
||||
}
|
||||
|
||||
.button.info,.menu-button.info,.toggle-button.info,
|
||||
.split-menu-button.info > .label,.split-menu-button.info > .arrow-button {
|
||||
-fx-border-color: #46b8da;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
/*hover state*/
|
||||
.button.info:hover,.menu-button.info:hover,.toggle-button.info:hover,
|
||||
.split-menu-button.info > .label:hover, .split-menu-button.info > .arrow-button:hover {
|
||||
-fx-border-color: #269abc;
|
||||
-fx-background-color: #31b0d5;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.button.info:pressed, .button.info:selected,
|
||||
.menu-button.info:pressed,.menu-button.info:selected
|
||||
,.toggle-button.info:pressed,.toggle-button.info:selected,
|
||||
.split-menu-button.info:pressed > .label, .split-menu-button.info > .arrow-button:pressed {
|
||||
-fx-background-color: #31b0d5;
|
||||
-fx-border-color: #269abc;
|
||||
-fx-effect: innershadow(gaussian, #269abc, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/*warning*/
|
||||
|
||||
.button.warning,.split-menu-button.warning,.toggle-button.warning,.menu-button.warning,
|
||||
.split-menu-button.warning > .label, .split-menu-button.warning > .arrow-button {
|
||||
-fx-background-color: #f0ad4e;
|
||||
}
|
||||
|
||||
.button.warning,.menu-button.warning,.toggle-button.warning,
|
||||
.split-menu-button.warning > .label,.split-menu-button.warning > .arrow-button {
|
||||
-fx-border-color: #eea236;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
/*hover state*/
|
||||
.button.warning:hover,.menu-button.warning:hover,.toggle-button.warning:hover,
|
||||
.split-menu-button.warning > .label:hover, .split-menu-button.warning > .arrow-button:hover {
|
||||
-fx-border-color: #d58512;
|
||||
-fx-background-color: #ec971f;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.button.warning:pressed, .button.warning:selected,
|
||||
.menu-button.warning:pressed,.menu-button.warning:selected
|
||||
,.toggle-button.warning:pressed,.toggle-button.warning:selected,
|
||||
.split-menu-button.warning:pressed > .label, .split-menu-button.warning > .arrow-button:pressed {
|
||||
-fx-background-color: #ec971f;
|
||||
-fx-border-color: #d58512;
|
||||
-fx-effect: innershadow(gaussian, #d58512, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/*danger*/
|
||||
|
||||
.button.danger,.split-menu-button.danger,.toggle-button.danger,.menu-button.danger,
|
||||
.split-menu-button.danger > .label, .split-menu-button.danger > .arrow-button {
|
||||
-fx-background-color: #d9534f;
|
||||
}
|
||||
|
||||
.button.danger,.menu-button.danger,.toggle-button.danger,
|
||||
.split-menu-button.danger > .label,.split-menu-button.danger > .arrow-button {
|
||||
-fx-border-color: #d43f3a;
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
/*hover state*/
|
||||
.button.danger:hover,.menu-button.danger:hover,.toggle-button.danger:hover,
|
||||
.split-menu-button.danger > .label:hover, .split-menu-button.danger > .arrow-button:hover {
|
||||
-fx-border-color: #ac2925;
|
||||
-fx-background-color: #c9302c;
|
||||
}
|
||||
/*pressed selected*/
|
||||
.button.danger:pressed, .button.danger:selected,
|
||||
.menu-button.danger:pressed,.menu-button.danger:selected
|
||||
,.toggle-button.danger:pressed,.toggle-button.danger:selected,
|
||||
.split-menu-button.danger:pressed > .label, .split-menu-button.danger > .arrow-button:pressed {
|
||||
-fx-border-color: #ac2925;
|
||||
-fx-background-color: #c9302c;
|
||||
-fx-effect: innershadow(gaussian, #ac2925, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
-fx-min-width: 200;
|
||||
}
|
||||
|
||||
.menu-item:focused {
|
||||
-fx-background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.menu-item:focused > * {
|
||||
-fx-text-fill: #262626;
|
||||
}
|
||||
.menu-item:focused .arrow {
|
||||
-fx-background-color: #333333;
|
||||
}
|
||||
|
||||
.check-menu-item:checked:hover > .left-container > .check,
|
||||
.check-menu-item:checked:focused > .left-container > .check,
|
||||
.radio-menu-item:checked:hover > .left-container > .radio,
|
||||
.radio-menu-item:checked:focused > .left-container > .radio {
|
||||
-fx-background-color: #333333;
|
||||
}
|
||||
|
||||
.context-menu {
|
||||
-fx-border-radius: 4;
|
||||
-fx-background-radius: 4;
|
||||
-fx-border-color: #bebec0;
|
||||
}
|
||||
|
||||
.context-menu > * {
|
||||
-fx-padding: 5 0 5 0;
|
||||
}
|
||||
|
||||
.separator {
|
||||
-fx-padding: 5 0 5 0;
|
||||
}
|
||||
|
||||
.text-field {
|
||||
-fx-pref-height: 30;
|
||||
}
|
||||
|
||||
.combo-box, .choice-box {
|
||||
-fx-background-insets: 0;
|
||||
-fx-border-color: #cecece;
|
||||
-fx-padding: -1;
|
||||
-fx-border-width: 1;
|
||||
}
|
||||
.combo-box, .choice-box, .color-picker, .date-picker {
|
||||
-fx-border-radius: 4;
|
||||
-fx-background-radius: 4;
|
||||
-fx-pref-height: 30;
|
||||
}
|
||||
|
||||
.combo-box:editable > .arrow-button {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
.combo-box:editable > .arrow-button:hover {
|
||||
-fx-background-color: #e6e6e6;
|
||||
}
|
||||
|
||||
.combo-box:editable > .arrow-button:pressed {
|
||||
-fx-effect: innershadow(gaussian, #adadad, 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
.combo-box > .text-input, .date-picker > .text-input {
|
||||
-fx-background-radius: 4 0 0 4;
|
||||
-fx-border-width: 0;
|
||||
}
|
||||
|
||||
.text-field, .text-area {
|
||||
-fx-border-color: #cccccc;
|
||||
-fx-background-color: white;
|
||||
-fx-border-radius: 4;
|
||||
-fx-background-radius: 4;
|
||||
-fx-effect: innershadow(gaussian, transparent, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.text-field:focused, .text-area:focused {
|
||||
-fx-border-color: #66afe9;
|
||||
-fx-effect: dropshadow(gaussian, #66afe9, 10, 0, 0, 0);
|
||||
}
|
||||
|
||||
.text-area .scroll-pane, .text-area .scroll-pane .content {
|
||||
-fx-background-color: white;
|
||||
-fx-background-radius: 4;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-background {
|
||||
-fx-background-color: #f4f4f4;
|
||||
}
|
||||
.tab-pane.plain .tab-header-background {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-area .tab {
|
||||
-fx-border-radius: 4 4 0 0;
|
||||
-fx-background-radius: 5 5 0 0;
|
||||
-fx-background-color: transparent;
|
||||
-fx-border-color: transparent;
|
||||
-fx-padding: 3 10 5 10;
|
||||
-fx-background-insets: 0;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-area .tab .tab-label {
|
||||
-fx-text-fill: #337ab7;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-area .tab:hover {
|
||||
-fx-background-color: #eeeeee;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-area .tab:selected {
|
||||
-fx-focus-color: transparent;
|
||||
-fx-border-color: #dddddd #dddddd white #dddddd;
|
||||
-fx-background-color: white;
|
||||
}
|
||||
.tab-pane .tab-header-area .tab:selected .tab-label {
|
||||
-fx-text-fill: #333333;
|
||||
}
|
||||
.tab-pane > .tab-content-area {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
.tab-pane .tab-header-area .tab .tab-label {
|
||||
-fx-focus-color: transparent;
|
||||
}
|
||||
|
||||
.tab-pane:focused > .tab-header-area > .headers-region > .tab:selected .focus-indicator {
|
||||
-fx-border-color: transparent;
|
||||
}
|
||||
|
||||
.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button {
|
||||
-fx-background-color: #337ab7;
|
||||
}
|
||||
.tab-pane > .tab-header-area > .headers-region > .tab:selected > .tab-container > .tab-close-button {
|
||||
-fx-background-color: #333333;
|
||||
}
|
||||
.tab-pane > .tab-header-area > .headers-region > .tab > .tab-container > .tab-close-button:hover {
|
||||
-fx-background-color: red;
|
||||
-fx-cursor: hand;
|
||||
}
|
||||
|
||||
.scroll-bar {
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 0;
|
||||
-fx-block-increment: 50;
|
||||
}
|
||||
|
||||
.corner {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.scroll-bar .decrement-button, .scroll-bar .decrement-arrow {
|
||||
visibility: hidden;
|
||||
-fx-pref-height: 1;
|
||||
-fx-pref-width: 1;
|
||||
}
|
||||
|
||||
.scroll-bar .increment-button, .scroll-bar .increment-arrow {
|
||||
visibility: hidden;
|
||||
-fx-pref-height: 1;
|
||||
-fx-pref-width: 1;
|
||||
}
|
||||
|
||||
.scroll-bar:vertical {
|
||||
-fx-pref-width: 10;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal {
|
||||
-fx-pref-height: 10;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal .track,
|
||||
.scroll-bar:vertical .track {
|
||||
-fx-background-color: transparent;
|
||||
-fx-border-color: transparent;
|
||||
-fx-background-radius: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:vertical .track-background,
|
||||
.scroll-bar:horizontal .track-background {
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-radius: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal .thumb {
|
||||
-fx-background-color: #c9c9c9;
|
||||
-fx-background-insets: 2 0 2 0;
|
||||
-fx-background-radius: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:vertical .thumb {
|
||||
-fx-background-color: #c9c9c9;
|
||||
-fx-background-insets: 0 2 0 2;
|
||||
-fx-background-radius: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal .thumb:hover,
|
||||
.scroll-bar:vertical .thumb:hover {
|
||||
-fx-background-color: #b5b5b5;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal .thumb:pressed,
|
||||
.scroll-bar:vertical .thumb:pressed {
|
||||
-fx-background-color: #a0a0a0;
|
||||
}
|
||||
|
||||
.scroll-bar:vertical .increment-button, .scroll-bar:vertical .decrement-button {
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 5;
|
||||
-fx-padding: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:horizontal .increment-button, .scroll-bar:horizontal .decrement-button {
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 5;
|
||||
-fx-padding: 5;
|
||||
}
|
||||
|
||||
.scroll-bar:vertical:focused,
|
||||
.scroll-bar:horizontal:focused {
|
||||
-fx-background-color: transparent, rgb(96, 96, 96), rgb(96, 96, 96);
|
||||
}
|
||||
|
||||
.menu-bar {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
.menu-bar > .container > .menu-button {
|
||||
-fx-background-radius: 0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-border-width: 0;
|
||||
-fx-border-radius: 0;
|
||||
}
|
||||
.menu-bar > .container > .menu-button:hover,
|
||||
.menu-bar > .container > .menu-button:showing {
|
||||
-fx-background-color: #56c0e0;
|
||||
}
|
||||
|
||||
.color-palette {
|
||||
-fx-background-color: white;
|
||||
}
|
||||
|
||||
.pagination > .pagination-control > .control-box {
|
||||
-fx-spacing: -1;
|
||||
}
|
||||
.pagination > .pagination-control > .control-box > .left-arrow-button {
|
||||
-fx-border-radius: 3 0 0 3;
|
||||
-fx-border-insets: 0 0 0 7;
|
||||
-fx-background-insets: 0 0 0 7, 0 0 0 5, 1 1 1 6, 2 2 2 7;
|
||||
}
|
||||
.pagination > .pagination-control > .control-box > .right-arrow-button {
|
||||
-fx-border-radius: 0 3 3 0;
|
||||
-fx-border-insets: 0 7 0 0;
|
||||
-fx-background-insets: 0 7 -1 0, 0 5 0 0, 1 6 1 1, 2 7 2 2;
|
||||
}
|
||||
.pagination > .pagination-control > .control-box > .number-button {
|
||||
-fx-background-radius: 0;
|
||||
-fx-border-radius: 0;
|
||||
}
|
||||
|
||||
.progress-bar > .track {
|
||||
-fx-pref-height: 10;
|
||||
-fx-background-radius: 3;
|
||||
-fx-effect: innershadow(gaussian, #e4e4e4, 4, 0, 0, 1);
|
||||
-fx-background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.progress-bar > .bar {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: #337ab7;
|
||||
}
|
||||
|
||||
.progress-bar.success > .bar {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: #5cb85c;
|
||||
}
|
||||
|
||||
.progress-bar.info > .bar {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: #5bc0de;
|
||||
}
|
||||
|
||||
.progress-bar.warning > .bar {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: #f0ad4e
|
||||
}
|
||||
|
||||
.progress-bar.danger > .bar {
|
||||
-fx-background-insets: 0;
|
||||
-fx-background-color: #d9534f;
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
-fx-background: white;
|
||||
-fx-text-fill: #333333;
|
||||
-fx-background-color: white;
|
||||
-fx-background-radius: 4px;
|
||||
-fx-border-radius: 4px;
|
||||
-fx-border-color: #C0C0C0;
|
||||
-fx-background-insets: 0;
|
||||
-fx-padding: 0.667em 0.75em 0.667em 0.75em; /* 10px */
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.5), 10, 0.0, 0, 3);
|
||||
-fx-font-size: 0.85em;
|
||||
}
|
||||
|
||||
.tooltip.success {
|
||||
-fx-background: #dff0d8;
|
||||
-fx-background-color: #dff0d8;
|
||||
-fx-text-fill: #99bb96;
|
||||
-fx-border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.tooltip.info {
|
||||
-fx-background: #d8ecf6;
|
||||
-fx-background-color: #d8ecf6;
|
||||
-fx-text-fill: #31708f;
|
||||
-fx-border-color: #bce8f1;
|
||||
}
|
||||
|
||||
.tooltip.warning {
|
||||
-fx-background: #fcf8e3;
|
||||
-fx-background-color: #fcf8e3;
|
||||
-fx-text-fill: #8a6e3c;
|
||||
-fx-border-color: #faebcc;
|
||||
}
|
||||
|
||||
.tooltip.danger {
|
||||
-fx-background: #f2dede;
|
||||
-fx-background-color: #f2dede;
|
||||
-fx-text-fill: #a94442;
|
||||
-fx-border-color: #ebccd1;
|
||||
}
|
||||
|
||||
.titled-pane > .title {
|
||||
-fx-background-color: #f5f5f5;
|
||||
-fx-border-color: #dddddd;
|
||||
/*-fx-background-insets: 5, 1, 5;*/
|
||||
-fx-background-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
|
||||
-fx-border-radius: 3 3 0 0, 2 2 0 0, 1 1 0 0;
|
||||
-fx-padding: 11
|
||||
}
|
||||
|
||||
.titled-pane > .content {
|
||||
-fx-background-color: white;
|
||||
-fx-background-radius: 0 0 4 4;
|
||||
-fx-border-radius: 0 0 4 4;
|
||||
-fx-border-color: #dddddd;
|
||||
/*-fx-padding: -11;*/
|
||||
}
|
||||
|
||||
.titled-pane.primary {
|
||||
-fx-text-fill: white;
|
||||
}
|
||||
|
||||
.titled-pane.primary > .title {
|
||||
-fx-background-color: #337ab7;
|
||||
-fx-border-color: #337ab7;
|
||||
}
|
||||
|
||||
.titled-pane.primary > .content {
|
||||
-fx-border-color: #337ab7;
|
||||
}
|
||||
|
||||
.titled-pane.success .arrow,
|
||||
.titled-pane.info .arrow,
|
||||
.titled-pane.warning .arrow,
|
||||
.titled-pane.danger .arrow {
|
||||
-fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
|
||||
}
|
||||
|
||||
.titled-pane.success {
|
||||
-fx-text-fill: #3c763d;
|
||||
}
|
||||
|
||||
.titled-pane.success > .title {
|
||||
-fx-background-color: #dff0d8;
|
||||
-fx-border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.titled-pane.success > .content {
|
||||
-fx-border-color: #d6e9c6;
|
||||
}
|
||||
|
||||
.titled-pane.info {
|
||||
-fx-text-fill: #31708f;
|
||||
}
|
||||
|
||||
.titled-pane.info > .title {
|
||||
-fx-background-color: #d9edf7;
|
||||
-fx-border-color: #bce8f1;
|
||||
}
|
||||
|
||||
.titled-pane.info > .content {
|
||||
-fx-border-color: #bce8f1;
|
||||
}
|
||||
|
||||
.titled-pane.warning {
|
||||
-fx-text-fill: #8a6d3b;
|
||||
}
|
||||
|
||||
.titled-pane.warning > .title {
|
||||
-fx-background-color: #fcf8e3;
|
||||
-fx-border-color: #faebcc;
|
||||
}
|
||||
|
||||
.titled-pane.warning > .content {
|
||||
-fx-border-color: #faebcc;
|
||||
}
|
||||
|
||||
.titled-pane.danger {
|
||||
-fx-text-fill: #a94442;
|
||||
}
|
||||
|
||||
.titled-pane.danger > .title {
|
||||
-fx-background-color: #f2dede;
|
||||
-fx-border-color: #eacbd0;
|
||||
}
|
||||
|
||||
.titled-pane.danger > .content {
|
||||
-fx-border-color: #eacbd0;
|
||||
}
|
||||
|
||||
.accordion > .titled-pane > .title,
|
||||
.accordion > .titled-pane > .content {
|
||||
-fx-background-radius: 0;
|
||||
-fx-border-radius: 0;
|
||||
}
|
||||
|
||||
.tool-bar:vertical { /* left */
|
||||
-fx-border-color: transparent #dddddd transparent transparent;
|
||||
}
|
||||
|
||||
.tool-bar { /* top */
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: transparent transparent #dddddd transparent;
|
||||
}
|
||||
|
||||
.tool-bar:vertical {
|
||||
-fx-background-insets: 0, 0 1 0 0;
|
||||
}
|
||||
|
||||
/*table view columns*/
|
||||
.filler,.column-header,.show-hide-columns-button {
|
||||
-fx-background-color: #dddddd, white, white;
|
||||
}
|
||||
.show-hide-columns-button {
|
||||
-fx-border-width: 0;
|
||||
-fx-background-insets: 0 0 1 1;
|
||||
}
|
||||
.column-header:hover,.show-hide-columns-button:hover {
|
||||
-fx-background-color: #dddddd, white, #f8f8f8;
|
||||
}
|
||||
.column-header-background > .filler {
|
||||
-fx-border-color: transparent #dddddd transparent transparent;
|
||||
-fx-border-insets: 0 1 0 0;
|
||||
}
|
||||
.column-drag-header {
|
||||
-fx-background-color: #2fb254;
|
||||
}
|
||||
|
||||
/*split pane*/
|
||||
.split-pane > .split-pane-divider {
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: #eeeeee;
|
||||
-fx-pref-width: 8;
|
||||
}
|
||||
.split-pane:horizontal > .split-pane-divider {
|
||||
-fx-background-insets: 0, 0 1 0 1;
|
||||
-fx-border-width: 0 1 0 1;
|
||||
}
|
||||
/* vertical the two nodes are placed on top of each other. */
|
||||
.split-pane:vertical > .split-pane-divider {
|
||||
-fx-background-insets: 0, 1 0 1 0;
|
||||
-fx-border-width: 1 0 1 0;
|
||||
}
|
||||
.split-pane > .split-pane-divider:hover {
|
||||
-fx-background-color: #E0E0E0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* CheckBox *
|
||||
* *
|
||||
******************************************************************************/
|
||||
.check-box > .box {
|
||||
-fx-background-radius: 3;
|
||||
/*-fx-padding: 0.166667em 0.166667em 0.25em 0.25em; !* 2 2 3 3 *!*/
|
||||
-fx-padding:0;
|
||||
-fx-border-color: #56c0e0;
|
||||
-fx-border-radius: 3;
|
||||
-fx-background-color: white;
|
||||
}
|
||||
.check-box > .box > .mark {
|
||||
-fx-background-color: null;
|
||||
-fx-padding: 0.416667em 0.416667em 0.5em 0.5em; /* 5 5 6 6 */
|
||||
-fx-shape: "M927.936 272.992l-68.288-68.288c-12.608-12.576-32.96-12.576-45.536 0l-409.44 409.44-194.752-196.16c-12.576-12.576-32.928-12.576-45.536 0l-68.288 68.288c-12.576 12.608-12.576 32.96 0 45.536l285.568 287.488c12.576 12.576 32.96 12.576 45.536 0l500.736-500.768c12.576-12.544 12.576-32.96 0-45.536z";
|
||||
-fx-background-insets: -3 -3 1 0;
|
||||
}
|
||||
.check-box {
|
||||
-fx-label-padding: 0.2em 0.0em 0.3em 0.416667em; /* 0 0 0 5 */
|
||||
-fx-text-fill: -fx-text-background-color;
|
||||
-fx-padding: 0 0 2 0;
|
||||
}
|
||||
.check-box:indeterminate > .box {
|
||||
-fx-padding: 0;
|
||||
}
|
||||
.check-box:selected > .box > .mark {
|
||||
-fx-background-color: linear-gradient(to bottom, #56c0e0, #40b8dc);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* RadioButton *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
.radio-button {
|
||||
-fx-label-padding: 0.0em 0.0em 0.1em 0.416667em; /* 0 0 0 5 */
|
||||
-fx-text-fill: -fx-text-background-color;
|
||||
-fx-padding: 0 0 .5 0;
|
||||
}
|
||||
.radio-button > .radio,
|
||||
.radio-button:focused > .radio {
|
||||
-fx-border-color: #56c0e0;
|
||||
-fx-border-radius: 1em;
|
||||
-fx-background-radius: 1.0em; /* large value to make sure this remains circular */
|
||||
-fx-padding: 1 2 3 2;
|
||||
-fx-background-color: white;
|
||||
}
|
||||
.radio-button > .radio > .dot {
|
||||
-fx-background-color: transparent;
|
||||
-fx-background-radius: 1.0em; /* large value to make sure this remains circular */
|
||||
-fx-padding: 0.333333em; /* 4 -- radius of the inner black dot when selected */
|
||||
-fx-background-insets: 3 2 1 2;
|
||||
}
|
||||
.radio-button:selected > .radio,.radio-button:hover > .radio {
|
||||
-fx-fill-color: #56c0e0;
|
||||
}
|
||||
.radio-button:pressed > .radio {
|
||||
-fx-background-color: #50c0e2;
|
||||
}
|
||||
.radio-button:selected > .radio > .dot {
|
||||
-fx-background-color: #56c0e0;
|
||||
}
|
||||
|
||||
/*common things*/
|
||||
.check-box:hover > .box,
|
||||
.check-box:selected > .box,
|
||||
.radio-button:hover > .radio,
|
||||
.radio-button:selected > .radio {
|
||||
-fx-background-color: linear-gradient(to bottom, white, #efefef);
|
||||
}
|
||||
|
||||
.check-box:pressed > .box,
|
||||
.radio-button:pressed > .radio {
|
||||
-fx-background-color: #50c0e2;
|
||||
}
|
209
src/main/ui/connection/Connection.fxml
Normal file
209
src/main/ui/connection/Connection.fxml
Normal file
@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<GridPane alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ui.connection.ConnectionForm">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane alignment="CENTER" GridPane.hgrow="SOMETIMES" GridPane.vgrow="SOMETIMES">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="364.0" minWidth="10.0" prefWidth="325.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="279.0" minWidth="10.0" prefWidth="252.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane GridPane.columnIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="32.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="32.0" minHeight="10.0" prefHeight="29.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="45.0" minHeight="10.0" prefHeight="43.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="120.0" minWidth="10.0" prefWidth="68.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="188.0" minWidth="10.0" prefWidth="184.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Port:" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||
<ComboBox fx:id="inpPort" editable="true" GridPane.columnIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets right="15.0" />
|
||||
</GridPane.margin>
|
||||
</ComboBox>
|
||||
</children>
|
||||
</GridPane>
|
||||
<GridPane layoutX="10.0" layoutY="10.0" GridPane.rowIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="120.0" minWidth="10.0" prefWidth="68.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="188.0" minWidth="10.0" prefWidth="184.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Host:" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
|
||||
<ComboBox fx:id="inpHost" editable="true" GridPane.columnIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets right="15.0" />
|
||||
</GridPane.margin>
|
||||
</ComboBox>
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button fx:id="btnConnect" alignment="CENTER" maxWidth="1.7976931348623157E308" onAction="#btnConnect_clicked" text="Connect" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets left="15.0" right="15.0" />
|
||||
</GridPane.margin></Button>
|
||||
</children>
|
||||
<opaqueInsets>
|
||||
<Insets />
|
||||
</opaqueInsets>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="6.0" top="22.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
<GridPane style="-fx-border-color: #888888; -fx-border-radius: 5px;">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="140.0" minWidth="10.0" prefWidth="103.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="191.0" minWidth="10.0" prefWidth="190.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="12.0" left="20.0" right="10.0" top="18.0" />
|
||||
</GridPane.margin>
|
||||
<children>
|
||||
<Label text="Public key:" textFill="#000000cc">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<Label text="Private key:" textFill="#000000cc" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<TextField editable="false" GridPane.columnIndex="1">
|
||||
<opaqueInsets>
|
||||
<Insets />
|
||||
</opaqueInsets>
|
||||
<GridPane.margin>
|
||||
<Insets left="5.0" right="10.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
<TextField editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets left="5.0" right="10.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="7.0" top="7.0" />
|
||||
</padding>
|
||||
</GridPane>
|
||||
</children>
|
||||
</GridPane>
|
||||
<GridPane alignment="CENTER" GridPane.rowIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="283.0" minWidth="10.0" prefWidth="197.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="380.0" minWidth="10.0" prefWidth="380.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="62.0" minHeight="10.0" prefHeight="53.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="107.0" minHeight="10.0" prefHeight="85.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Connection state:" textFill="#000000ba" GridPane.valignment="BOTTOM">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0" left="2.0" />
|
||||
</GridPane.margin>
|
||||
<font>
|
||||
<Font size="12.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="lblState" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-border-color: #888888; -fx-border-radius: 5px;" text="Not connected" textAlignment="CENTER" textFill="#000000d1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="14.0" left="20.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
<GridPane style="-fx-border-color: #888888; -fx-border-radius: 5px; " GridPane.columnIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="140.0" minWidth="10.0" prefWidth="103.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="191.0" minWidth="10.0" prefWidth="190.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="12.0" left="20.0" right="10.0" top="18.0" />
|
||||
</GridPane.margin>
|
||||
<children>
|
||||
<Label text="Game host:" textFill="#000000cc">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<Label text="Port:" textFill="#000000cc" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin>
|
||||
</Label>
|
||||
<TextField fx:id="outHost" editable="false" GridPane.columnIndex="1">
|
||||
<opaqueInsets>
|
||||
<Insets />
|
||||
</opaqueInsets>
|
||||
<GridPane.margin>
|
||||
<Insets left="5.0" right="10.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
<TextField fx:id="outPort" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets left="5.0" right="10.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="7.0" top="7.0" />
|
||||
</padding>
|
||||
</GridPane>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
</children>
|
||||
</GridPane>
|
97
src/main/ui/connection/ConnectionForm.java
Normal file
97
src/main/ui/connection/ConnectionForm.java
Normal file
@ -0,0 +1,97 @@
|
||||
package main.ui.connection;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.Observable;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.event.EventType;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import main.protocol.HConnection;
|
||||
import main.ui.SubForm;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConnectionForm extends SubForm {
|
||||
|
||||
public ComboBox<String> inpPort;
|
||||
public ComboBox<String> inpHost;
|
||||
public Button btnConnect;
|
||||
public Label lblState;
|
||||
public TextField outHost;
|
||||
public TextField outPort;
|
||||
|
||||
private boolean isBusy = false;
|
||||
|
||||
public void initialize() {
|
||||
inpPort.getEditor().textProperty().addListener(observable -> {
|
||||
try {
|
||||
int i = Integer.parseInt(inpPort.getEditor().getText());
|
||||
btnConnect.setDisable(i < 0 || i >= 256 * 256);
|
||||
}
|
||||
catch (Exception e) {
|
||||
btnConnect.setDisable(true);
|
||||
}
|
||||
});
|
||||
|
||||
inpPort.getItems().addAll("30000", "38101");
|
||||
inpHost.getItems().addAll("game-nl.habbo.com", "game-us.habbo.com");
|
||||
|
||||
inpPort.getSelectionModel().selectFirst();
|
||||
inpHost.getSelectionModel().selectFirst();
|
||||
}
|
||||
|
||||
public void onParentSet(){
|
||||
getHConnection().addStateChangeListener((oldState, newState) -> Platform.runLater(() -> {
|
||||
if (newState == HConnection.State.NOT_CONNECTED) {
|
||||
inpHost.setDisable(false);
|
||||
inpPort.setDisable(false);
|
||||
lblState.setText("Not connected");
|
||||
btnConnect.setText("Connect");
|
||||
outHost.setText("");
|
||||
outPort.setText("");
|
||||
}
|
||||
else if (oldState == HConnection.State.NOT_CONNECTED) {
|
||||
inpHost.setDisable(true);
|
||||
inpPort.setDisable(true);
|
||||
btnConnect.setText("Abort");
|
||||
}
|
||||
|
||||
if (newState == HConnection.State.CONNECTED) {
|
||||
lblState.setText("Connected");
|
||||
outHost.setText(getHConnection().getHost());
|
||||
outPort.setText(getHConnection().getPort()+"");
|
||||
}
|
||||
if (newState == HConnection.State.WAITING_FOR_CLIENT) {
|
||||
lblState.setText("Waiting for connection");
|
||||
}
|
||||
|
||||
}));
|
||||
}
|
||||
|
||||
public void btnConnect_clicked(ActionEvent actionEvent) {
|
||||
if (!isBusy) {
|
||||
isBusy = true;
|
||||
getHConnection().prepare(inpHost.getEditor().getText(), Integer.parseInt(inpPort.getEditor().getText()));
|
||||
|
||||
if (HConnection.DEBUG) System.out.println("connecting");
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
getHConnection().start();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
else {
|
||||
getHConnection().abort();
|
||||
isBusy = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
76
src/main/ui/injection/Injection.fxml
Normal file
76
src/main/ui/injection/Injection.fxml
Normal file
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
<?import javafx.scene.text.Text?>
|
||||
|
||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ui.injection.InjectionForm">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="232.0" minHeight="10.0" prefHeight="36.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="232.0" minHeight="10.0" prefHeight="194.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="121.0" minHeight="10.0" prefHeight="32.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane GridPane.rowIndex="0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Text fx:id="lbl_corrruption" fill="#ee0404b2" strokeType="OUTSIDE" strokeWidth="0.0" text="isCorrupted: True">
|
||||
<font>
|
||||
<Font name="System Italic" size="11.0" />
|
||||
</font>
|
||||
</Text>
|
||||
<Text fx:id="lbl_pcktInfo" fill="#000000b2" nodeOrientation="LEFT_TO_RIGHT" strokeType="OUTSIDE" strokeWidth="0.0" text="header (id:NULL, length:0)" GridPane.columnIndex="1" GridPane.halignment="RIGHT">
|
||||
<font>
|
||||
<Font name="System Italic" size="11.0" />
|
||||
</font>
|
||||
</Text>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets left="13.0" right="13.0" top="4.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
<TextArea fx:id="inputPacket" prefHeight="185.0" prefWidth="545.0" wrapText="true" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0" left="10.0" right="10.0" />
|
||||
</GridPane.margin>
|
||||
</TextArea>
|
||||
<GridPane GridPane.rowIndex="2">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Button fx:id="btn_sendToServer" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#sendToServer_clicked" text="Send to server" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
<Button fx:id="btn_sendToClient" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#sendToClient_clicked" text="Send to client" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="7.0" />
|
||||
</padding>
|
||||
</GridPane>
|
62
src/main/ui/injection/InjectionForm.java
Normal file
62
src/main/ui/injection/InjectionForm.java
Normal file
@ -0,0 +1,62 @@
|
||||
package main.ui.injection;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.text.Text;
|
||||
import main.protocol.HConnection;
|
||||
import main.protocol.HPacket;
|
||||
import main.ui.SubForm;
|
||||
|
||||
public class InjectionForm extends SubForm {
|
||||
public TextArea inputPacket;
|
||||
public Text lbl_corrruption;
|
||||
public Text lbl_pcktInfo;
|
||||
public Button btn_sendToServer;
|
||||
public Button btn_sendToClient;
|
||||
|
||||
protected void onParentSet() {
|
||||
getHConnection().addStateChangeListener((oldState, newState) -> Platform.runLater(() ->
|
||||
updateUI()));
|
||||
|
||||
inputPacket.textProperty().addListener(event -> { Platform.runLater(() ->
|
||||
updateUI());
|
||||
});
|
||||
}
|
||||
|
||||
private void updateUI() {
|
||||
HPacket packet = new HPacket(inputPacket.getText());
|
||||
if (!packet.isCorrupted()) {
|
||||
lbl_corrruption.setText("isCorrupted: False");
|
||||
lbl_corrruption.setFill(Paint.valueOf("Green"));
|
||||
lbl_pcktInfo.setText("header (id:"+packet.headerId()+", length:"+packet.length()+")");
|
||||
|
||||
btn_sendToClient.setDisable(getHConnection().getState() != HConnection.State.CONNECTED);
|
||||
btn_sendToServer.setDisable(getHConnection().getState() != HConnection.State.CONNECTED);
|
||||
}
|
||||
else {
|
||||
lbl_corrruption.setText("isCorrupted: True");
|
||||
lbl_corrruption.setFill(Paint.valueOf("#ee0404b2"));
|
||||
lbl_pcktInfo.setText("header (id:NULL, length:"+packet.getBytesLength()+")");
|
||||
|
||||
btn_sendToClient.setDisable(true);
|
||||
btn_sendToServer.setDisable(true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void sendToServer_clicked(ActionEvent actionEvent) {
|
||||
HPacket packet = new HPacket(inputPacket.getText());
|
||||
getHConnection().sendToServerAsync(packet);
|
||||
writeToLog(Color.BLUE, "SS -> packet with id: " + packet.headerId());
|
||||
}
|
||||
|
||||
public void sendToClient_clicked(ActionEvent actionEvent) {
|
||||
HPacket packet = new HPacket(inputPacket.getText());
|
||||
getHConnection().sendToClientAsync(packet);
|
||||
writeToLog(Color.RED, "CS -> packet with id: " + packet.headerId());
|
||||
}
|
||||
}
|
120
src/main/ui/logger/Logger.fxml
Normal file
120
src/main/ui/logger/Logger.fxml
Normal file
@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ScrollPane?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.TextFlow?>
|
||||
|
||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ui.logger.LoggerForm">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="293.0" minWidth="10.0" prefWidth="242.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="10.0" prefWidth="323.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="5.0E9" prefWidth="5.0E9">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="138.0" minHeight="10.0" prefHeight="126.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="111.0" minHeight="10.0" prefHeight="109.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0">
|
||||
<children>
|
||||
<GridPane prefHeight="52.0" prefWidth="214.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="160.0" minWidth="10.0" prefWidth="132.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="110.0" minWidth="10.0" prefWidth="84.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<Label text="Packet size limit:" />
|
||||
<TextField fx:id="txtPacketLimit" text="8000" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets right="8.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
</children>
|
||||
</GridPane>
|
||||
<Button fx:id="btnUpdate" alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#updatePacketLimit" prefHeight="44.0" prefWidth="62.0" text="Update" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="-1.0" left="6.0" right="6.0" />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
</children>
|
||||
</GridPane>
|
||||
<CheckBox fx:id="cbx_blockIn" mnemonicParsing="false" text="Block Incoming" />
|
||||
<CheckBox fx:id="cbx_blockOut" mnemonicParsing="false" text="Block Outgoing" />
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox alignment="BOTTOM_LEFT" prefHeight="99.0" prefWidth="198.0" spacing="8.0" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<CheckBox fx:id="cbx_showAdditional" mnemonicParsing="false" selected="true" text="Show additional data" />
|
||||
<CheckBox disable="true" mnemonicParsing="false" selected="true" text="Show packet structure" />
|
||||
<CheckBox fx:id="cbx_splitPackets" mnemonicParsing="false" selected="true" text="Split packets" />
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
</VBox>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="12.0" left="17.0" top="15.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
<GridPane style="-fx-border-color: #888; -fx-border-radius: 5px;" GridPane.columnIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="125.0" minHeight="10.0" prefHeight="33.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="233.0" minHeight="10.0" prefHeight="191.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<CheckBox fx:id="cbx_useLog" mnemonicParsing="false" selected="true" text="Use history log">
|
||||
<GridPane.margin>
|
||||
<Insets left="5.0" />
|
||||
</GridPane.margin>
|
||||
</CheckBox>
|
||||
<ScrollPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" style="-fx-border-color: #888888; -fx-border-radius: 1px; -fx-background: #FFFFFF;" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.vgrow="ALWAYS">
|
||||
<TextFlow fx:id="txt_logField" style=" -fx-background-color: #FFFFFF;">
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
</TextFlow>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||
</padding>
|
||||
</ScrollPane>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
|
||||
</GridPane.margin>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="7.0" right="7.0" top="6.0" />
|
||||
</padding>
|
||||
</GridPane>
|
||||
</children>
|
||||
</GridPane>
|
157
src/main/ui/logger/LoggerForm.java
Normal file
157
src/main/ui/logger/LoggerForm.java
Normal file
@ -0,0 +1,157 @@
|
||||
package main.ui.logger;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.Text;
|
||||
import javafx.scene.text.TextFlow;
|
||||
import main.protocol.HConnection;
|
||||
import main.protocol.HMessage;
|
||||
import main.ui.SubForm;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LoggerForm extends SubForm {
|
||||
|
||||
|
||||
public TextField txtPacketLimit;
|
||||
public CheckBox cbx_blockIn;
|
||||
public CheckBox cbx_blockOut;
|
||||
public CheckBox cbx_showAdditional;
|
||||
public CheckBox cbx_splitPackets;
|
||||
public CheckBox cbx_useLog;
|
||||
public TextFlow txt_logField;
|
||||
public Button btnUpdate;
|
||||
|
||||
private int packetLimit = 8000;
|
||||
|
||||
public final static Map<String, String> colorizePackets;
|
||||
|
||||
static {
|
||||
//FOR GNOME ONLY, shows up colorized packets
|
||||
colorizePackets = new HashMap<>();
|
||||
colorizePackets.put("BLOCKED", (char)27 + "[35m"); // some kind of grey
|
||||
colorizePackets.put("INCOMING", (char)27 + "[31m"); // red
|
||||
colorizePackets.put("OUTGOING", (char)27 + "[34m"); // blue
|
||||
colorizePackets.put("REPLACED", (char)27 + "[33m"); // yellow
|
||||
|
||||
// others:
|
||||
colorizePackets.put("INJECTED", "");
|
||||
colorizePackets.put("SKIPPED", (char)27 + "[36m");
|
||||
colorizePackets.put("DEFAULT", (char)27 + "[0m");
|
||||
|
||||
if (System.getenv("XDG_CURRENT_DESKTOP") == null || !System.getenv("XDG_CURRENT_DESKTOP").toLowerCase().contains("gnome")) {
|
||||
for (String key : colorizePackets.keySet()) {
|
||||
colorizePackets.put(key, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void onParentSet(){
|
||||
|
||||
getHConnection().addStateChangeListener((oldState, newState) -> Platform.runLater(() -> {
|
||||
if (newState == HConnection.State.PREPARING) {
|
||||
miniLogText(Color.ORANGE, "Connecting to "+getHConnection().getDomain() + ":" + getHConnection().getPort());
|
||||
}
|
||||
if (newState == HConnection.State.CONNECTED) {
|
||||
miniLogText(Color.GREEN, "Connecting to "+getHConnection().getDomain() + ":" + getHConnection().getPort());
|
||||
}
|
||||
if (newState == HConnection.State.NOT_CONNECTED) {
|
||||
miniLogText(Color.RED, "End of connection");
|
||||
}
|
||||
}));
|
||||
|
||||
getHConnection().addTrafficListener(2, message -> { Platform.runLater(() -> {
|
||||
if (message.getDestination() == HMessage.Side.TOCLIENT && cbx_blockIn.isSelected() ||
|
||||
message.getDestination() == HMessage.Side.TOSERVER && cbx_blockOut.isSelected()) return;
|
||||
|
||||
String splitter = cbx_splitPackets.isSelected() ? "-----------------------------------\n" : "";
|
||||
|
||||
String type = message.getDestination() == HMessage.Side.TOCLIENT ?"" +
|
||||
colorizePackets.get("INCOMING") + "INCOMING" :
|
||||
colorizePackets.get("OUTGOING") + "OUTGOING";
|
||||
|
||||
String additionalData = " ";
|
||||
if (!message.isCorrupted() && cbx_showAdditional.isSelected()) {
|
||||
additionalData = " (h:"+ message.getPacket().headerId() +", l:"+message.getPacket().length()+") ";
|
||||
}
|
||||
|
||||
String arrow = "--> ";
|
||||
|
||||
String packet = message.isCorrupted() ?
|
||||
message.getPacket().getBytesLength() + " (encrypted)": // message.getPacket().toString() : // TEMP CODE TO VIEW ENCRYPTED BODY
|
||||
message.getPacket().length() < packetLimit ?
|
||||
message.getPacket().toString() :
|
||||
colorizePackets.get("SKIPPED") + "<packet skipped (length >= " + (packetLimit) + ")>";
|
||||
|
||||
|
||||
String skipStyle = colorizePackets.get("DEFAULT");
|
||||
|
||||
String isBlocked = message.isBlocked() ? colorizePackets.get("BLOCKED") + "[BLOCKED] " : "";
|
||||
String isEdited = !message.getPacket().isReplaced() || message.isBlocked() ? "" : colorizePackets.get("REPLACED") + "[REPLACED] ";
|
||||
System.out.println(splitter + isBlocked + isEdited + type + additionalData + arrow + packet + skipStyle);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void updatePacketLimit(ActionEvent actionEvent) {
|
||||
packetLimit = Integer.parseInt(txtPacketLimit.getText());
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
public void initialize() {
|
||||
txtPacketLimit.textProperty().addListener(observable -> {
|
||||
boolean isInt = true;
|
||||
|
||||
try {
|
||||
Integer.parseInt(txtPacketLimit.getText());
|
||||
} catch (NumberFormatException e) {
|
||||
isInt = false;
|
||||
}
|
||||
|
||||
btnUpdate.setDisable(!isInt);
|
||||
});
|
||||
|
||||
txtPacketLimit.setOnKeyPressed(event -> {
|
||||
if(event.getCode().equals(KeyCode.ENTER) && !btnUpdate.isDisable()) {
|
||||
updatePacketLimit(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void miniLogText(Color color, String text) {
|
||||
if (cbx_useLog.isSelected()) {
|
||||
String color2 = "#" + color.toString().substring(2, 8);
|
||||
|
||||
Calendar rightNow = Calendar.getInstance();
|
||||
String hour = addToNumber(""+rightNow.get(Calendar.HOUR_OF_DAY));
|
||||
String minutes = addToNumber(""+rightNow.get(Calendar.MINUTE));
|
||||
String seconds = addToNumber(""+rightNow.get(Calendar.SECOND));
|
||||
String timestamp = "["+hour+":"+minutes+":"+seconds+"] ";
|
||||
|
||||
timestamp = timestamp.replace(" ", "\u00A0"); // disable automatic linebreaks
|
||||
Text time = new Text(timestamp);
|
||||
time.setStyle("-fx-opacity: "+0.5+";");
|
||||
|
||||
text = text.replace(" ", "\u00A0");
|
||||
Text otherText = new Text(text + "\n");
|
||||
otherText.setStyle("-fx-fill: "+color2+";");
|
||||
|
||||
txt_logField.getChildren().addAll(time, otherText);
|
||||
}
|
||||
}
|
||||
|
||||
private String addToNumber(String text) {
|
||||
if (text.length() == 1) text = "0" + text;
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
165
src/main/ui/tools/Tools.fxml
Normal file
165
src/main/ui/tools/Tools.fxml
Normal file
@ -0,0 +1,165 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ui.tools.ToolsForm">
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="158.0" minHeight="10.0" prefHeight="134.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="141.0" minHeight="10.0" prefHeight="128.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="683.0" minWidth="10.0" prefWidth="276.0" />
|
||||
</columnConstraints>
|
||||
<children>
|
||||
<GridPane>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="53.0" minHeight="10.0" prefHeight="29.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="108.0" minHeight="10.0" prefHeight="100.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane style="-fx-border-color: #888888; -fx-border-radius: 5px;" GridPane.rowIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="103.0" minWidth="10.0" prefWidth="73.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="159.0" minWidth="10.0" prefWidth="146.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="129.0" minWidth="10.0" prefWidth="89.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="148.0" minWidth="10.0" prefWidth="89.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="167.0" minWidth="10.0" prefWidth="146.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
<children>
|
||||
<Label alignment="CENTER" text="Integer:">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin></Label>
|
||||
<TextField fx:id="txt_intDecoded" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></TextField>
|
||||
<Button fx:id="btnEncodeInt" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnEncodeInt_clicked" text="Encode" GridPane.columnIndex="2" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></Button>
|
||||
<Button fx:id="btnDecodeInt" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnDecodeInt_clicked" text="Decode" GridPane.columnIndex="3" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></Button>
|
||||
<TextField fx:id="txt_intEncoded" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="4">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
|
||||
<Label alignment="CENTER" text="Ushort:" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" />
|
||||
</GridPane.margin></Label>
|
||||
<TextField fx:id="txt_ushortDecoded" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></TextField>
|
||||
<Button fx:id="btnEncodeUShort" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnEncodeUShort_clicked" text="Encode" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></Button>
|
||||
<Button fx:id="btnDecodeUshort" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#btnDecodeUshort_clicked" text="Decode" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin></Button>
|
||||
<TextField fx:id="txt_ushortEncoded" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" GridPane.columnIndex="4" GridPane.rowIndex="1">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</TextField>
|
||||
|
||||
</children>
|
||||
</GridPane>
|
||||
<Label text="Encoding/decoding" textFill="#000000cc">
|
||||
<GridPane.margin>
|
||||
<Insets left="6.0" top="5.0" />
|
||||
</GridPane.margin>
|
||||
<font>
|
||||
<Font name="System Italic" size="12.0" />
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets left="10.0" right="10.0" top="5.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
<GridPane layoutX="20.0" layoutY="15.0" GridPane.rowIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints maxHeight="53.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints maxHeight="104.0" minHeight="10.0" prefHeight="99.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<GridPane style="-fx-border-color: #888888; -fx-border-radius: 5px;" GridPane.rowIndex="1">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="190.0" minWidth="10.0" prefWidth="180.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="10.0" prefWidth="90.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="118.0" minWidth="10.0" prefWidth="90.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="219.0" minWidth="10.0" prefWidth="180.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
<children>
|
||||
<Button disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="------>" GridPane.columnIndex="1" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
<TextArea disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="7.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</TextArea>
|
||||
<Button disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="<------" GridPane.columnIndex="2" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="5.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</Button>
|
||||
<TextArea disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="3" GridPane.halignment="CENTER">
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="5.0" right="7.0" top="7.0" />
|
||||
</GridPane.margin>
|
||||
</TextArea>
|
||||
</children>
|
||||
</GridPane>
|
||||
<Label text="Packet <-> expression" textFill="#000000cc">
|
||||
<GridPane.margin>
|
||||
<Insets left="6.0" top="2.0" />
|
||||
</GridPane.margin>
|
||||
<font>
|
||||
<Font name="System Italic" size="12.0" />
|
||||
</font>
|
||||
</Label>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets bottom="7.0" left="10.0" right="10.0" top="5.0" />
|
||||
</GridPane.margin>
|
||||
</GridPane>
|
||||
</children>
|
||||
</GridPane>
|
117
src/main/ui/tools/ToolsForm.java
Normal file
117
src/main/ui/tools/ToolsForm.java
Normal file
@ -0,0 +1,117 @@
|
||||
package main.ui.tools;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import main.protocol.HPacket;
|
||||
import main.ui.SubForm;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
public class ToolsForm extends SubForm {
|
||||
public TextField txt_intDecoded;
|
||||
public TextField txt_intEncoded;
|
||||
public TextField txt_ushortDecoded;
|
||||
public TextField txt_ushortEncoded;
|
||||
public Button btnEncodeInt;
|
||||
public Button btnDecodeInt;
|
||||
public Button btnEncodeUShort;
|
||||
public Button btnDecodeUshort;
|
||||
|
||||
|
||||
public void initialize() {
|
||||
txt_intDecoded.textProperty().addListener(observable -> {
|
||||
boolean isInt = true;
|
||||
|
||||
try {
|
||||
Integer.parseInt(txt_intDecoded.getText());
|
||||
} catch (NumberFormatException e) {
|
||||
isInt = false;
|
||||
}
|
||||
|
||||
btnEncodeInt.setDisable(!isInt);
|
||||
});
|
||||
|
||||
txt_intDecoded.setOnKeyPressed(event -> {
|
||||
if(event.getCode().equals(KeyCode.ENTER) && !btnEncodeInt.isDisable()) {
|
||||
btnEncodeInt_clicked(null);
|
||||
}
|
||||
});
|
||||
|
||||
//---------------
|
||||
|
||||
txt_ushortDecoded.textProperty().addListener(observable -> {
|
||||
boolean isDouble = true;
|
||||
|
||||
try {
|
||||
int res = Integer.parseInt(txt_ushortDecoded.getText());
|
||||
if (res < 0 || res >= (256*256)) isDouble = false;
|
||||
} catch (NumberFormatException e) {
|
||||
isDouble = false;
|
||||
}
|
||||
btnEncodeUShort.setDisable(!isDouble);
|
||||
});
|
||||
|
||||
txt_ushortDecoded.setOnKeyPressed(event -> {
|
||||
if(event.getCode().equals(KeyCode.ENTER) && !btnEncodeUShort.isDisable()) {
|
||||
btnEncodeUShort_clicked(null);
|
||||
}
|
||||
});
|
||||
|
||||
//----------------
|
||||
|
||||
txt_intEncoded.textProperty().addListener(observable -> {
|
||||
HPacket packet = new HPacket(txt_intEncoded.getText());
|
||||
btnDecodeInt.setDisable(packet.getBytesLength() != 4);
|
||||
});
|
||||
|
||||
txt_intEncoded.setOnKeyPressed(event -> {
|
||||
if(event.getCode().equals(KeyCode.ENTER) && !btnDecodeInt.isDisable()) {
|
||||
btnDecodeInt_clicked(null);
|
||||
}
|
||||
});
|
||||
|
||||
//----------------
|
||||
|
||||
txt_ushortEncoded.textProperty().addListener(observable -> {
|
||||
HPacket packet = new HPacket(txt_ushortEncoded.getText());
|
||||
btnDecodeUshort.setDisable(packet.getBytesLength() != 2);
|
||||
});
|
||||
|
||||
txt_ushortEncoded.setOnKeyPressed(event -> {
|
||||
if(event.getCode().equals(KeyCode.ENTER) && !btnDecodeUshort.isDisable()) {
|
||||
btnDecodeUshort_clicked(null);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public void btnEncodeInt_clicked(ActionEvent actionEvent) {
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.putInt(Integer.parseInt(txt_intDecoded.getText()));
|
||||
|
||||
HPacket packet = new HPacket(b.array());
|
||||
txt_intEncoded.setText(packet.toString());
|
||||
}
|
||||
|
||||
public void btnDecodeInt_clicked(ActionEvent actionEvent) {
|
||||
txt_intDecoded.setText(new HPacket(txt_intEncoded.getText()).readInteger(0) + "");
|
||||
}
|
||||
|
||||
public void btnEncodeUShort_clicked(ActionEvent actionEvent) {
|
||||
ByteBuffer b = ByteBuffer.allocate(4);
|
||||
b.putInt(Integer.parseInt(txt_ushortDecoded.getText()));
|
||||
|
||||
HPacket packet = new HPacket(new byte[]{b.array()[2], b.array()[3]});
|
||||
txt_ushortEncoded.setText(packet.toString());
|
||||
}
|
||||
|
||||
public void btnDecodeUshort_clicked(ActionEvent actionEvent) {
|
||||
txt_ushortDecoded.setText(new HPacket(txt_ushortEncoded.getText()).readUshort(0) + "");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user