Initial commit

This commit is contained in:
sirjonasxx 2018-03-29 19:28:59 +02:00
commit e1347af8b1
29 changed files with 4250 additions and 0 deletions

45
src/main/Main.java Normal file
View 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
View 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";
}
}
}

View 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); }
}

View 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();
}
}

View 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();
}
}

View 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);
}
}

View File

@ -0,0 +1,7 @@
package main.protocol;
public interface StateChangeListener {
void stateChanged(HConnection.State oldState, HConnection.State newState);
}

View File

@ -0,0 +1,7 @@
package main.protocol;
public interface TrafficListener {
void onCapture(HMessage message);
}

View 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));
// }
}

View 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");
}
}

View 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;
}
}

View 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;
// }
}

View File

@ -0,0 +1,8 @@
package main.protocol.packethandler;
public interface BufferListener {
void act();
}

View 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;
}
}

View 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++;
}
}
}

View 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++;
}
}
}
}

View 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
View 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>

View 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
View 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
View 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;
}

View 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>

View 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;
}
}
}

View 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>

View 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());
}
}

View 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>

View 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;
}
}

View 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="------&gt;" 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="&lt;------" 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 &lt;-&gt; 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>

View 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) + "");
}
}