Merge remote-tracking branch 'origin/master' into windowsSupport

This commit is contained in:
sirjonasxx 2018-09-29 20:11:35 +02:00
commit 0823ab922b
52 changed files with 1131 additions and 327 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
.idea/
out/
G-Earth2.iml
Extensions/

3
src/META-INF/MANIFEST.MF Normal file
View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: main.extensions.examples.adminonconnect.AdminOnConnect

BIN
src/json-simple-1.1.1.jar Normal file

Binary file not shown.

View File

@ -1,6 +1,7 @@
package main;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
@ -17,7 +18,6 @@ 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();
@ -29,11 +29,11 @@ public class Main extends Application {
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();
Platform.exit();
});
}

View File

@ -4,10 +4,7 @@ import main.protocol.HMessage;
import main.protocol.HPacket;
import main.ui.extensions.Extensions;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
@ -26,14 +23,29 @@ public abstract class Extension {
void act(String[] args);
}
protected static final boolean CANLEAVE = true; // can you disconnect the ext
protected static final boolean CANDELETE = true; // can you delete the ext (will be false for some built-in extensions)
private String[] args;
private boolean isCorrupted = false;
private static final String[] PORT_FLAG = {"--port", "-p"};
private static final String[] FILE_FLAG = {"--filename", "-f"};
private OutputStream out = null;
private Map<Integer, List<MessageListener>> incomingMessageListeners = new HashMap<>();
private Map<Integer, List<MessageListener>> outgoingMessageListeners = new HashMap<>();
private final Map<Integer, List<MessageListener>> incomingMessageListeners = new HashMap<>();
private final Map<Integer, List<MessageListener>> outgoingMessageListeners = new HashMap<>();
private FlagsCheckListener flagRequestCallback = null;
private String getArgument(String[] args, String... arg) {
for (int i = 0; i < args.length - 1; i++) {
for (String str : arg) {
if (args[i].toLowerCase().equals(str.toLowerCase())) {
return args[i+1];
}
}
}
return null;
}
/**
* Makes the connection with G-Earth, pass the arguments given in the Main method "super(args)"
@ -41,29 +53,53 @@ public abstract class Extension {
*/
public Extension(String[] args) {
//obtain port
int port = 0;
this.args = args;
outerloop:
for (int i = 0; i < args.length - 1; i++) {
for (String str : PORT_FLAG) {
if (args[i].equals(str)) {
port = Integer.parseInt(args[i+1]);
break outerloop;
}
}
if (getInfoAnnotations() == null) {
System.err.println("Extension info not found\n\n" +
"Usage:\n" +
"@ExtensionInfo ( \n" +
" Title = \"...\",\n" +
" Description = \"...\",\n" +
" Version = \"...\",\n" +
" Author = \"...\"" +
"\n)");
isCorrupted = true;
}
if (getArgument(args, PORT_FLAG) == null) {
System.err.println("Don't forget to include G-Earth's port in your program parameters (-p {port})");
isCorrupted = true;
}
}
public void run() {
if (isCorrupted) {
return;
}
int port = Integer.parseInt(getArgument(args, PORT_FLAG));
String file = getArgument(args, FILE_FLAG);
Socket gEarthExtensionServer = null;
try {
gEarthExtensionServer = new Socket("localhost", port);
gEarthExtensionServer = new Socket("127.0.0.1", port);
InputStream in = gEarthExtensionServer.getInputStream();
DataInputStream dIn = new DataInputStream(in);
out = gEarthExtensionServer.getOutputStream();
while (!gEarthExtensionServer.isClosed()) {
int length = dIn.readInt();
int length;
try {
length = dIn.readInt();
}
catch(EOFException exception) {
//g-earth closed the extension
break;
}
byte[] headerandbody = new byte[length + 4];
int amountRead = 0;
@ -77,11 +113,18 @@ public abstract class Extension {
if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.INFOREQUEST) {
ExtensionInfo info = getInfoAnnotations();
HPacket response = new HPacket(Extensions.INCOMING_MESSAGES_IDS.EXTENSIONINFO);
response.appendString(getTitle())
.appendString(getAuthor())
.appendString(getVersion())
.appendString(getDescription());
response.appendString(info.Title())
.appendString(info.Author())
.appendString(info.Version())
.appendString(info.Description())
.appendBoolean(isOnClickMethodUsed())
.appendBoolean(file != null)
.appendString(file == null ? "": file)
.appendBoolean(CANLEAVE)
.appendBoolean(CANDELETE);
writeToStream(response.toBytes());
}
else if (packet.headerId() == Extensions.OUTGOING_MESSAGES_IDS.CONNECTIONSTART) {
@ -121,19 +164,29 @@ public abstract class Extension {
incomingMessageListeners :
outgoingMessageListeners;
if (listeners.containsKey(-1)) { // registered on all packets
for (int i = listeners.get(-1).size() - 1; i >= 0; i--) {
listeners.get(-1).get(i).act(habboMessage);
habboMessage.getPacket().setReadIndex(6);
List<MessageListener> correctListeners = new ArrayList<>();
synchronized (incomingMessageListeners) {
synchronized (outgoingMessageListeners) {
if (listeners.containsKey(-1)) { // registered on all packets
for (int i = listeners.get(-1).size() - 1; i >= 0; i--) {
correctListeners.add(listeners.get(-1).get(i));
}
}
if (listeners.containsKey(habboPacket.headerId())) {
for (int i = listeners.get(habboPacket.headerId()).size() - 1; i >= 0; i--) {
correctListeners.add(listeners.get(habboPacket.headerId()).get(i));
}
}
}
}
if (listeners.containsKey(habboPacket.headerId())) {
for (int i = listeners.get(habboPacket.headerId()).size() - 1; i >= 0; i--) {
listeners.get(habboPacket.headerId()).get(i).act(habboMessage);
habboMessage.getPacket().setReadIndex(6);
}
for(MessageListener listener : correctListeners) {
habboMessage.getPacket().setReadIndex(6);
listener.act(habboMessage);
}
habboMessage.getPacket().setReadIndex(6);
HPacket response = new HPacket(Extensions.INCOMING_MESSAGES_IDS.MANIPULATEDPACKET);
response.appendLongString(habboMessage.stringify());
@ -143,9 +196,9 @@ public abstract class Extension {
}
}
} catch (IOException | ArrayIndexOutOfBoundsException e) {
e.printStackTrace();
System.err.println("Connection failed; is G-Earth active?");
// e.printStackTrace();
}
finally {
if (gEarthExtensionServer != null && !gEarthExtensionServer.isClosed()) {
@ -206,10 +259,13 @@ public abstract class Extension {
incomingMessageListeners :
outgoingMessageListeners;
if (!listeners.containsKey(headerId)) {
listeners.put(headerId, new ArrayList<>());
synchronized (listeners) {
if (!listeners.containsKey(headerId)) {
listeners.put(headerId, new ArrayList<>());
}
}
listeners.get(headerId).add(messageListener);
}
@ -249,6 +305,25 @@ public abstract class Extension {
}
private boolean isOnClickMethodUsed() {
Class<? extends Extension> c = getClass();
while (c != Extension.class) {
try {
c.getDeclaredMethod("onClick");
// if it didnt error, onClick exists
return true;
} catch (NoSuchMethodException e) {
// e.printStackTrace();
}
c = (Class<? extends Extension>) c.getSuperclass();
}
return false;
}
/**
* Gets called when a connection has been established with G-Earth.
* This does not imply a connection with Habbo is setup.
@ -270,8 +345,8 @@ public abstract class Extension {
*/
protected void onEndConnection(){}
protected abstract String getTitle();
protected abstract String getDescription();
protected abstract String getVersion();
protected abstract String getAuthor();
ExtensionInfo getInfoAnnotations() {
return getClass().getAnnotation(ExtensionInfo.class);
}
}

View File

@ -0,0 +1,114 @@
package main.extensions;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
import main.protocol.HMessage;
import main.protocol.HPacket;
/**
* Created by Jonas on 22/09/18.
*/
public abstract class ExtensionForm extends Application {
private Extension extension = null;
protected static String[] args;
private volatile Stage primaryStage = null;
@Override
public void start(Stage primaryStage) throws Exception {
Platform.setImplicitExit(false);
setStageData(primaryStage);
this.primaryStage = primaryStage;
primaryStage.setOnCloseRequest(event -> {
event.consume();
Platform.runLater(primaryStage::hide);
});
ExtensionForm thiss = this;
ExtensionInfo extInfo = getClass().getAnnotation(ExtensionInfo.class);
Thread t = new Thread(() -> {
extension = new Extension(args) {
@Override
protected void init() {
thiss.initExtension();
}
@Override
protected void onClick() {
thiss.onClick();
}
@Override
protected void onStartConnection() {
thiss.onStartConnection();
}
@Override
protected void onEndConnection() {
thiss.onEndConnection();
}
@Override
ExtensionInfo getInfoAnnotations() {
return extInfo;
}
};
extension.run();
// Platform.runLater(primaryStage::close);
//when the extension has ended, close this process
Platform.exit();
});
t.start();
}
public abstract void setStageData(Stage primaryStage) throws Exception;
//wrap extension methods
protected boolean requestFlags(Extension.FlagsCheckListener flagRequestCallback){
return extension.requestFlags(flagRequestCallback);
}
protected void writeToConsole(String s) {
extension.writeToConsole(s);
}
protected void intercept(HMessage.Side side, Extension.MessageListener messageListener) {
extension.intercept(side, messageListener);
}
protected void intercept(HMessage.Side side, int headerId, Extension.MessageListener messageListener){
extension.intercept(side, headerId, messageListener);
}
protected boolean sendToServer(HPacket packet){
return extension.sendToServer(packet);
}
protected boolean sendToClient(HPacket packet){
return extension.sendToClient(packet);
}
/**
* Gets called when a connection has been established with G-Earth.
* This does not imply a connection with Habbo is setup.
*/
protected void initExtension(){}
/**
* The application got doubleclicked from the G-Earth interface. Doing something here is optional
*/
private void onClick(){
Platform.runLater(() -> {
primaryStage.show();
});
}
/**
* A connection with Habbo has been started
*/
protected void onStartConnection(){}
/**
* A connection with Habbo has ended
*/
protected void onEndConnection(){}
}

View File

@ -0,0 +1,15 @@
package main.extensions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by Jonas on 25/09/18.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ExtensionInfo {
String Title();
String Description();
String Version();
String Author();
}

View File

@ -1,17 +1,26 @@
package main.extensions.examples;
package main.extensions.examples.adminonconnect;
import main.extensions.Extension;
import main.extensions.ExtensionInfo;
import main.protocol.HMessage;
import main.protocol.HPacket;
/**
* Created by Jonas on 26/06/18.
*/
@ExtensionInfo(
Title = "Always admin!",
Description = "Gives you admin permission on connect",
Version = "1.0",
Author = "sirjonasxx"
)
public class AdminOnConnect extends Extension {
public static void main(String[] args) {
new AdminOnConnect(args);
new AdminOnConnect(args).run();
}
public AdminOnConnect(String[] args) {
super(args);
@ -39,22 +48,4 @@ public class AdminOnConnect extends Extension {
protected void onStartConnection() {
done = false;
}
@Override
protected void onClick() {
System.out.println("clicked");
}
protected String getTitle() {
return "Always admin!";
}
protected String getDescription() {
return "Gives you admin permission on connect";
}
protected String getVersion() {
return "1.0";
}
protected String getAuthor() {
return "sirjonasxx";
}
}

View File

@ -0,0 +1,44 @@
package main.extensions.examples.blockreplacepackets;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import main.extensions.ExtensionForm;
import main.extensions.ExtensionInfo;
import main.ui.GEarthController;
import java.net.URL;
/**
* Created by Jonas on 22/09/18.
*/
@ExtensionInfo(
Title = "iManipulate",
Description = "Block &/ replace packets",
Version = "0.1",
Author = "sirjonasxx"
)
public class BlockAndReplacePackets extends ExtensionForm {
public static void main(String[] args) {
ExtensionForm.args = args;
launch(args);
}
@Override
protected void initExtension() {
}
@Override
public void setStageData(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(BlockAndReplacePackets.class.getResource("blockreplace.fxml"));
Parent root = loader.load();
primaryStage.setTitle("Packet blocker and replacer");
primaryStage.setScene(new Scene(root, 565, 262));
}
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane prefHeight="260.0" prefWidth="179.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.extensions.examples.blockreplacepackets.BlockAndReplacePackets">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="367.0" minWidth="10.0" prefWidth="163.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="121.0" minHeight="10.0" prefHeight="28.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="234.0" minHeight="10.0" prefHeight="234.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TextArea fx:id="text" editable="false" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1">
<GridPane.margin>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</GridPane.margin>
</TextArea>
<Label alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" text="Blocks packets:" textAlignment="CENTER" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
</children>
</GridPane>
</children>
</GridPane>

View File

@ -1,6 +1,7 @@
package main.extensions.examples;
package main.extensions.examples.speechcolorizer;
import main.extensions.Extension;
import main.extensions.ExtensionInfo;
import main.protocol.HMessage;
import main.protocol.HPacket;
@ -15,11 +16,16 @@ import java.util.Random;
*
*/
@ExtensionInfo(
Title = "Colorize me!",
Description = "Because we like to be weird",
Version = "1.0",
Author = "sirjonasxx"
)
public class SpeechColorizer extends Extension {
public static void main(String[] args) {
new SpeechColorizer(args);
new SpeechColorizer(args).run();
}
private SpeechColorizer(String[] args) {
super(args);

View File

@ -0,0 +1,7 @@
package main.extensions.extra;
/**
* Created by Jonas on 22/09/18.
*/
public class Inspector {
}

View File

@ -1,183 +1,71 @@
package main.misc;
import java.io.*;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Created by Jonas on 05/04/18.
* Created by Jonas on 28/09/18.
*/
public class Cacher {
private static final String CACHEFILENAME = "jsoncache.json";
private static String getCacheDir() {
return System.getProperty("user.home") + File.separator + ".G-Earth" + File.separator;
}
public static boolean exists(String key) {
File f = new File(getCacheDir(), "cache.txt");
if (f.exists()) {
private static boolean cacheFileExists() {
File f = new File(getCacheDir(), CACHEFILENAME);
return (f.exists() && !f.isDirectory());
}
private static JSONObject getCacheContents() {
if (cacheFileExists()) {
try {
List<String> lines = Files.readAllLines(f.toPath());
File f = new File(getCacheDir(), CACHEFILENAME);
String contents = String.join("\n", Files.readAllLines(f.toPath()));
for (String line : lines) {
if (line.startsWith(key+":")) {
return true;
}
}
} catch (IOException e) {
JSONParser parser = new JSONParser();
return (JSONObject) parser.parse(contents);
} catch (IOException | ParseException e) {
e.printStackTrace();
}
}
return false;
return new JSONObject();
}
private static void updateCache(JSONObject contents) {
try (FileWriter file = new FileWriter(new File(getCacheDir(), CACHEFILENAME))) {
public static String get(String key) {
File f = new File(getCacheDir(), "cache.txt");
if (f.exists()) {
try {
List<String> lines = Files.readAllLines(f.toPath());
file.write(contents.toJSONString());
file.flush();
for (String line : lines) {
if (line.startsWith(key+":")) {
return line.split(":")[1];
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
public static void remove(String key) {
File targetFile = new File(getCacheDir() + File.separator + "cache.txt");
File parent = targetFile.getParentFile();
if (!parent.exists() && !parent.mkdirs()) {
throw new IllegalStateException("Couldn't create dir: " + parent);
}
if (!targetFile.exists()) {
try {
targetFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try
{
ArrayList<String> lines = new ArrayList<String>();
File f1 = new File(getCacheDir() + File.separator + "cache.txt");
FileReader fr = new FileReader(f1);
BufferedReader br = new BufferedReader(fr);
String line = null;
while ((line = br.readLine()) != null)
{
if (!line.startsWith(key + ":"))
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();
}
catch (Exception ex)
{
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void add(String key, String value) {
File targetFile = new File(getCacheDir() + File.separator + "cache.txt");
File parent = targetFile.getParentFile();
if (!parent.exists() && !parent.mkdirs()) {
throw new IllegalStateException("Couldn't create dir: " + parent);
}
if (!targetFile.exists()) {
try {
targetFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void put(String key, Object val) {
JSONObject object = getCacheContents();
if (object.containsKey(key)) object.remove(key);
// File f = new File(getCacheDir(), "cache.txt");
// if (!f.exists()) {
// try {
// PrintWriter writer = new PrintWriter(f.getPath(), "UTF-8");
// writer.write("");
// writer.close();
// } catch (FileNotFoundException | UnsupportedEncodingException e) {
// e.printStackTrace();
// }
// }
try
{
ArrayList<String> lines = new ArrayList<String>();
File f1 = new File(getCacheDir() + File.separator + "cache.txt");
FileReader fr = new FileReader(f1);
BufferedReader br = new BufferedReader(fr);
String line = null;
boolean containmmm = false;
while ((line = br.readLine()) != null)
{
if (line.startsWith(key+":"))
containmmm = true;
lines.add(line);
}
fr.close();
br.close();
FileWriter fw = new FileWriter(f1);
BufferedWriter out = new BufferedWriter(fw);
if (!containmmm) {
out.write(key+":"+value);
}
for (int i = 0; i < lines.size(); i++) {
out.write("\n"+ lines.get(i));
}
out.flush();
out.close();
}
catch (Exception ex)
{
ex.printStackTrace();
}
object.put(key, val);
updateCache(object);
}
public static Object get(String key) {
JSONObject object = getCacheContents();
public static void update(String key, String value) {
remove(key);
add(key, value);
return object.get(key);
}
public static void main(String[] args) {
// System.out.println(exists("hallo"));
// System.out.println(get("hallo"));
//
// add("hallo","doei");
//
// System.out.println(exists("hallo"));
// System.out.println(get("hallo"));
//
// remove("hallo");
// System.out.println(get("hallo"));
System.out.println(get("PRODUCTION-201804032203-770536283-pingHeader"));
public static void clear() {
updateCache(new JSONObject());
}
}

View File

@ -0,0 +1,50 @@
package main.misc;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.CheckBox;
import javafx.scene.control.DialogPane;
/**
* Created by Jonas on 27/09/18.
*/
public class ConfirmationDialog {
public static boolean showDialog = true;
public static Alert createAlertWithOptOut(Alert.AlertType type, String title, String headerText,
String message, String optOutMessage, /*Callback<Boolean, Void> optOutAction,*/
ButtonType... buttonTypes) {
Alert alert = new Alert(type);
// Need to force the alert to layout in order to grab the graphic,
// as we are replacing the dialog pane with a custom pane
alert.getDialogPane().applyCss();
Node graphic = alert.getDialogPane().getGraphic();
// Create a new dialog pane that has a checkbox instead of the hide/show details button
// Use the supplied callback for the action of the checkbox
alert.setDialogPane(new DialogPane() {
@Override
protected Node createDetailsButton() {
CheckBox optOut = new CheckBox();
optOut.setText(optOutMessage);
optOut.setOnAction(event -> showDialog = !optOut.isSelected());
return optOut;
}
});
alert.getDialogPane().getButtonTypes().addAll(buttonTypes);
alert.getDialogPane().setContentText(message);
// Fool the dialog into thinking there is some expandable content
// a Group won't take up any space if it has no children
alert.getDialogPane().setExpandableContent(new Group());
alert.getDialogPane().setExpanded(true);
// Reset the dialog graphic using the default style
alert.getDialogPane().setGraphic(graphic);
alert.setTitle(title);
alert.setHeaderText(headerText);
return alert;
}
}

View File

@ -1,5 +1,6 @@
package main.protocol;
import main.misc.Cacher;
import main.protocol.hostreplacer.HostReplacer;
import main.protocol.hostreplacer.HostReplacerFactory;
import main.protocol.memory.Rc4Obtainer;
@ -16,6 +17,7 @@ import java.util.*;
public class HConnection {
public static final String HOTELS_CACHE_KEY = "hotelsConnectionInfo";
private final Queue<HPacket> sendToClientAsyncQueue = new LinkedList<>();
private final Queue<HPacket> sendToServerAsyncQueue = new LinkedList<>();
@ -63,16 +65,27 @@ public class HConnection {
CONNECTED // CONNECTED
}
private static List<String> autoDetectHosts;
public static List<String> autoDetectHosts;
static {
autoDetectHosts = new ArrayList<>();
autoDetectHosts.add("game-us.habbo.com:38101");
autoDetectHosts.add("game-nl.habbo.com:30000");
autoDetectHosts.add("game-br.habbo.com:30000");
autoDetectHosts.add("game-de.habbo.com:30000");
autoDetectHosts.add("game-es.habbo.com:30000");
autoDetectHosts.add("game-fi.habbo.com:30000");
autoDetectHosts.add("game-fr.habbo.com:30000");
autoDetectHosts.add("game-it.habbo.com:30000");
autoDetectHosts.add("game-nl.habbo.com:30000");
autoDetectHosts.add("game-tr.habbo.com:30000");
autoDetectHosts.add("game-us.habbo.com:38101");
List<String> additionalCachedHotels = (List<String>) Cacher.get(HOTELS_CACHE_KEY);
if (additionalCachedHotels != null) {
for (String additionalHotel : additionalCachedHotels) {
if (!autoDetectHosts.contains(additionalHotel)) {
autoDetectHosts.add(additionalHotel);
}
}
}
}
@ -110,6 +123,16 @@ public class HConnection {
// manual method
public void prepare(String domain, int port) {
List<String> additionalCachedHotels = (List<String>) Cacher.get(HOTELS_CACHE_KEY);
if (additionalCachedHotels == null) {
additionalCachedHotels = new ArrayList<>();
}
if (!additionalCachedHotels.contains(domain +":"+port)) {
additionalCachedHotels.add(domain+":"+port);
Cacher.put(HOTELS_CACHE_KEY, additionalCachedHotels);
}
List<String> potentialHost = new ArrayList<>();
potentialHost.add(domain+":"+port);
prepare(potentialHost);
@ -134,17 +157,29 @@ public class HConnection {
removeFromHosts();
}
try {
for (String host : allPotentialHosts) {
InetAddress address = InetAddress.getByName(host.split(":")[0]);
actual_domain.add(address.getHostAddress());
}
setState(State.PREPARED);
} catch (UnknownHostException e) {
e.printStackTrace();
setState(State.NOT_CONNECTED);
List<String> willremove = new ArrayList<>();
for (String host : allPotentialHosts) {
InetAddress address = null;
try {
address = InetAddress.getByName(host.split(":")[0]);
actual_domain.add(address.getHostAddress());
} catch (UnknownHostException e) {
// e.printStackTrace();
actual_domain.add(null);
willremove.add(host);
}
}
List<String> additionalCachedHotels = (List<String>) Cacher.get(HOTELS_CACHE_KEY);
if (additionalCachedHotels != null) {
for (String host: willremove) {
additionalCachedHotels.remove(host);
}
Cacher.put(HOTELS_CACHE_KEY, additionalCachedHotels);
}
setState(State.PREPARED);
}
public void start() throws IOException {
@ -157,6 +192,8 @@ public class HConnection {
for (int i = 0; i < actual_domain.size(); i++) {
if (actual_domain.get(i) == null) continue;
ServerSocket proxy = new ServerSocket(port.get(i), 10, InetAddress.getByName("127.0.0." + (i+1)));
this.proxy.add(proxy);
String dom = actual_domain.get(i);
@ -186,7 +223,7 @@ public class HConnection {
} catch (IOException e1) {
// TODO Auto-generated catch block
//e1.printStackTrace();
// e1.printStackTrace();
}
}
} catch (Exception e) {
@ -359,17 +396,31 @@ public class HConnection {
}
private void addToHosts() {
String[] lines = new String[input_domain.size()];
List<String> linesTemp = new ArrayList<>();
for (int i = 0; i < input_domain.size(); i++) {
lines[i] = ("127.0.0." + (i+1)) + " " + input_domain.get(i);
if (actual_domain.get(i) != null) {
linesTemp.add(("127.0.0." + (i+1)) + " " + input_domain.get(i));
}
}
String[] lines = new String[linesTemp.size()];
for (int i = 0; i < linesTemp.size(); i++) {
lines[i] = linesTemp.get(i);
}
hostsReplacer.addRedirect(lines);
hostRedirected = true;
}
private void removeFromHosts(){
String[] lines = new String[input_domain.size()];
List<String> linesTemp = new ArrayList<>();
for (int i = 0; i < input_domain.size(); i++) {
lines[i] = ("127.0.0." + (i+1)) + " " + input_domain.get(i);
if (actual_domain.get(i) != null) {
linesTemp.add(("127.0.0." + (i+1)) + " " + input_domain.get(i));
}
}
String[] lines = new String[linesTemp.size()];
for (int i = 0; i < linesTemp.size(); i++) {
lines[i] = linesTemp.get(i);
}
hostsReplacer.removeRedirect(lines);
hostRedirected = false;

View File

@ -72,6 +72,7 @@ public class Rc4Obtainer {
if (payloadBuffer.peak().length == 0) {
outgoingHandler.setRc4(rc4Tryout);
incomingHandler.setRc4(rc4Tryout);
break outerloop;
}

View File

@ -2,6 +2,7 @@ package main.protocol.packethandler;
import main.protocol.HMessage;
import main.protocol.TrafficListener;
import main.protocol.crypto.RC4;
import java.io.IOException;
import java.io.OutputStream;
@ -10,6 +11,8 @@ import java.util.List;
public abstract class Handler {
protected static final boolean DEBUG = false;
volatile PayloadBuffer payloadBuffer = new PayloadBuffer();
volatile OutputStream out;
volatile Object[] listeners = null; //get notified on packet send
@ -17,6 +20,9 @@ public abstract class Handler {
volatile boolean isDataStream = false;
volatile int currentIndex = 0;
protected RC4 clientcipher = null;
protected RC4 servercipher = null;
public Handler(OutputStream outputStream, Object[] listeners) {
this.listeners = listeners;
@ -28,18 +34,11 @@ public abstract class Handler {
isDataStream = true;
}
public void act(byte[] buffer) throws IOException {
if (isDataStream) {
payloadBuffer.push(buffer);
notifyBufferListeners(buffer.length);
public abstract void act(byte[] buffer) throws IOException;
if (!isTempBlocked) {
flush();
}
}
else {
out.write(buffer);
}
public void setRc4(RC4 rc4) {
this.clientcipher = rc4.deepCopy();
this.servercipher = rc4.deepCopy();
}
public void block() {
@ -73,7 +72,7 @@ public abstract class Handler {
public abstract void flush() throws IOException;
protected abstract void printForDebugging(byte[] bytes);
private List<BufferListener> bufferListeners = new ArrayList<>();
public void addBufferListener(BufferListener listener) {

View File

@ -13,13 +13,48 @@ public class IncomingHandler extends Handler {
super(outputStream, listeners);
}
private final Object lock = new Object();
private Boolean isEncryptedStream = null;
@Override
public void act(byte[] buffer) throws IOException {
if (isDataStream) {
if (DEBUG) {
printForDebugging(buffer);
}
if (isEncryptedStream == null || !isEncryptedStream) {
payloadBuffer.push(buffer);
}
else {
payloadBuffer.push(servercipher.rc4(buffer));
}
notifyBufferListeners(buffer.length);
if (!isTempBlocked) {
flush();
}
}
else {
out.write(buffer);
}
}
@Override
public void sendToStream(byte[] buffer) {
synchronized (lock) {
try {
out.write(buffer);
out.write(
(isEncryptedStream == null || !isEncryptedStream)
? buffer
: clientcipher.rc4(buffer)
);
} catch (IOException e) {
e.printStackTrace();
}
@ -33,14 +68,29 @@ public class IncomingHandler extends Handler {
for (HPacket hpacket : hpackets){
HMessage hMessage = new HMessage(hpacket, HMessage.Side.TOCLIENT, currentIndex);
if (isDataStream) notifyListeners(hMessage);
if (isDataStream) {
notifyListeners(hMessage);
}
if (!hMessage.isBlocked()) {
out.write(hMessage.getPacket().toBytes());
out.write(
(isEncryptedStream == null || !isEncryptedStream)
? hMessage.getPacket().toBytes()
: clientcipher.rc4(hMessage.getPacket().toBytes())
);
}
if (isDataStream && isEncryptedStream == null && hpacket.length() == 261) {
isEncryptedStream = hpacket.readBoolean(264);
}
currentIndex++;
}
}
}
@Override
protected void printForDebugging(byte[] bytes) {
System.out.println("-- DEBUG INCOMING -- " + new HPacket(bytes).toString() + " -- DEBUG --");
}
}

View File

@ -14,10 +14,7 @@ public class OutgoingHandler extends Handler {
private final Object lock = new Object();
private final static int encryptOffset = 3; //all packets with index < 3 aren't encrypted
private RC4 clientcipher = null;
private RC4 servercipher = null;
private List<Byte> tempEncryptedBuffer = new ArrayList<>();
public OutgoingHandler(OutputStream outputStream, Object[] listeners) {
@ -35,7 +32,6 @@ public class OutgoingHandler extends Handler {
public void act(byte[] buffer) throws IOException {
dataStreamCheck(buffer);
if (isDataStream) {
if (currentIndex < encryptOffset) {
payloadBuffer.push(buffer);
}
@ -45,7 +41,11 @@ public class OutgoingHandler extends Handler {
}
}
else {
payloadBuffer.push(clientcipher.rc4(buffer));
byte[] tm = clientcipher.rc4(buffer);
if (DEBUG) {
printForDebugging(tm);
}
payloadBuffer.push(tm);
}
notifyBufferListeners(buffer.length);
@ -60,20 +60,8 @@ public class OutgoingHandler extends Handler {
}
@Override
public void sendToStream(byte[] buffer) {
synchronized (lock) {
try {
out.write(servercipher.rc4(buffer));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setRc4(RC4 rc4) {
this.clientcipher = rc4;
this.servercipher = rc4.deepCopy();
super.setRc4(rc4);
byte[] encrbuffer = new byte[tempEncryptedBuffer.size()];
for (int i = 0; i < tempEncryptedBuffer.size(); i++) {
@ -87,6 +75,19 @@ public class OutgoingHandler extends Handler {
}
tempEncryptedBuffer = null;
}
@Override
public void sendToStream(byte[] buffer) {
synchronized (lock) {
try {
out.write(servercipher.rc4(buffer));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public List<Byte> getEncryptedBuffer() {
return tempEncryptedBuffer;
}
@ -109,4 +110,10 @@ public class OutgoingHandler extends Handler {
}
}
@Override
protected void printForDebugging(byte[] bytes) {
System.out.println("-- DEBUG OUTGOING -- " + new HPacket(bytes).toString() + " -- DEBUG --");
}
}

View File

@ -7,6 +7,8 @@ import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import java.io.File;
public class BoxButton extends StackPane {
private ImageView imageView;
@ -15,9 +17,9 @@ public class BoxButton extends StackPane {
private boolean isVisible;
//paths zijn relatief aan deze classpath
public BoxButton(String imagePath, String imageOnHoverPath) {
this.image = new Image(getClass().getResourceAsStream(imagePath));
this.imageOnHover = new Image(getClass().getResourceAsStream(imageOnHoverPath));
public BoxButton(String imageName, String imageOnHoverName) {
this.image = new Image(getClass().getResourceAsStream("files" + File.separator + imageName));
this.imageOnHover = new Image(getClass().getResourceAsStream("files" + File.separator + imageOnHoverName));
this.imageView = new ImageView();
setCursor(Cursor.DEFAULT);

View File

@ -1,5 +1,9 @@
package main.ui.buttons;
import org.omg.CORBA.Environment;
import java.io.File;
public class DeleteButton extends BoxButton {
public DeleteButton() {

View File

@ -0,0 +1,10 @@
package main.ui.buttons;
/**
* Created by Jonas on 26/09/18.
*/
public class ExitButton extends BoxButton {
public ExitButton() {
super("ButtonExit.png", "ButtonExitHover.png");
}
}

View File

@ -0,0 +1,10 @@
package main.ui.buttons;
/**
* Created by Jonas on 26/09/18.
*/
public class FireButton extends BoxButton {
public FireButton() {
super("ButtonFire.png", "ButtonFireHover.png");
}
}

View File

@ -8,6 +8,7 @@ import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
@ -31,10 +32,10 @@ public class PauseResumeButton extends StackPane{
public PauseResumeButton(boolean isPaused) {
this.isPaused[0] = isPaused;
this.imagePause = new Image(getClass().getResourceAsStream("ButtonPause.png"));
this.imagePauseOnHover = new Image(getClass().getResourceAsStream("ButtonPauseHover.png"));
this.imageResume = new Image(getClass().getResourceAsStream("ButtonResume.png"));
this.imageResumeOnHover = new Image(getClass().getResourceAsStream("ButtonResumeHover.png"));
this.imagePause = new Image(getClass().getResourceAsStream("files"+ File.separator+"ButtonPause.png"));
this.imagePauseOnHover = new Image(getClass().getResourceAsStream("files"+ File.separator+"ButtonPauseHover.png"));
this.imageResume = new Image(getClass().getResourceAsStream("files"+ File.separator+"ButtonResume.png"));
this.imageResumeOnHover = new Image(getClass().getResourceAsStream("files"+ File.separator+"ButtonResumeHover.png"));
this.imageView = new ImageView();
setCursor(Cursor.DEFAULT);

View File

@ -0,0 +1,9 @@
package main.ui.buttons;
/**
* Created by Jonas on 26/09/18.
*/
public class ReloadButton extends BoxButton {
public ReloadButton() {
super("ButtonReload.png", "ButtonReloadHover.png"); }
}

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 443 B

After

Width:  |  Height:  |  Size: 443 B

View File

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 460 B

View File

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 B

View File

Before

Width:  |  Height:  |  Size: 725 B

After

Width:  |  Height:  |  Size: 725 B

View File

Before

Width:  |  Height:  |  Size: 621 B

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 446 B

View File

@ -14,6 +14,10 @@ import main.protocol.TrafficListener;
import main.ui.SubForm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Connection extends SubForm {
@ -35,8 +39,24 @@ public class Connection extends SubForm {
updateInputUI();
});
inpPort.getItems().addAll("30000", "38101");
inpHost.getItems().addAll("game-nl.habbo.com", "game-us.habbo.com");
List<String> knownHosts = HConnection.autoDetectHosts;
Set<String> hosts = new HashSet<>();
Set<String> ports = new HashSet<>();
for (String h : knownHosts) {
String[] split = h.split(":");
hosts.add(split[0]);
ports.add(split[1]);
}
List<String> hostsSorted = new ArrayList<>(hosts);
hostsSorted.sort(String::compareTo);
List<String> portsSorted = new ArrayList<>(ports);
portsSorted.sort(String::compareTo);
inpPort.getItems().addAll(portsSorted);
inpHost.getItems().addAll(hostsSorted);
inpPort.getSelectionModel().selectFirst();
inpHost.getSelectionModel().selectFirst();

View File

@ -1,17 +1,25 @@
package main.ui.extensions;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import main.ui.buttons.SimpleClickButton;
import main.extensions.Extension;
import main.misc.ConfirmationDialog;
import main.ui.buttons.*;
import main.ui.extensions.executer.ExecutionInfo;
import main.ui.extensions.executer.ExtensionRunner;
import main.ui.extensions.executer.ExtensionRunnerFactory;
import main.ui.extensions.executer.NormalExtensionRunner;
import main.ui.scheduler.ScheduleItem;
import main.ui.buttons.DeleteButton;
import main.ui.buttons.EditButton;
import main.ui.buttons.PauseResumeButton;
import javax.tools.Tool;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Created by Jonas on 19/07/18.
@ -19,17 +27,27 @@ import main.ui.buttons.PauseResumeButton;
public class ExtensionItemContainer extends GridPane {
public static final int[] columnWidths = {22, 34, 18, 13, 11};
GEarthExtension item;
private GEarthExtension item;
Label titleLabel;
Label descriptionLabel;
Label authorLabel;
Label versionLabel;
private Label titleLabel;
private Label descriptionLabel;
private Label authorLabel;
private Label versionLabel;
VBox parent;
private VBox parent;
ExtensionItemContainer(GEarthExtension item, VBox parent, ScrollPane scrollPane) {
private volatile int port;
private HBox buttonsBox = null;
private HBox additionalButtonBox = null;
private ExitButton exitButton;
private SimpleClickButton clickButton;
private ReloadButton reloadButton;
ExtensionItemContainer(GEarthExtension item, VBox parent, ScrollPane scrollPane, int port) {
super();
this.port = port;
setGridLinesVisible(true);
VBox.setMargin(this, new Insets(2, -2, -2, -2));
@ -61,28 +79,72 @@ public class ExtensionItemContainer extends GridPane {
add(authorLabel, 2, 0);
add(versionLabel, 3, 0);
// getChildren().addAll(indexLabel, packetLabel, delayLabel, destinationLabel);
DeleteButton deleteButton = new DeleteButton();
deleteButton.show();
deleteButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> item.isRemoveClickTrigger());
SimpleClickButton clickButton = new SimpleClickButton();
exitButton = new ExitButton();
Tooltip delete = new Tooltip("Close connection with this extension");
Tooltip.install(exitButton,delete);
exitButton.show();
exitButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> item.isRemoveClickTrigger());
clickButton = new SimpleClickButton();
clickButton.show();
clickButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> item.isClickTrigger());
HBox buttonsBox = new HBox(clickButton, deleteButton);
buttonsBox.setSpacing(10);
buttonsBox = new HBox(clickButton, exitButton);
reloadButton = new ReloadButton();
Tooltip reload = new Tooltip("Restart this extension");
Tooltip.install(reloadButton, reload);
reloadButton.show();
reloadButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
reloadButton.setVisible(false);
ExtensionRunner runner = ExtensionRunnerFactory.get();
runner.tryRunExtension(Paths.get(NormalExtensionRunner.JARPATH, ExecutionInfo.EXTENSIONSDIRECTORY, item.getFileName()).toString(), port);
});
DeleteButton deleteButton = new DeleteButton();
Tooltip uninstall = new Tooltip("Uninstall this extension");
Tooltip.install(deleteButton, uninstall);
deleteButton.show();
GridPane this2 = this;
deleteButton.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
boolean delet_dis = true;
if (ConfirmationDialog.showDialog) {
Alert alert = ConfirmationDialog.createAlertWithOptOut(Alert.AlertType.CONFIRMATION,
"Confirmation Dialog", null,
"Are you sure want to uninstall this extension?", "Do not ask again",
ButtonType.YES, ButtonType.NO
);
if (!(alert.showAndWait().filter(t -> t == ButtonType.YES).isPresent())) {
delet_dis = false;
}
}
if (delet_dis) {
ExtensionRunner runner = ExtensionRunnerFactory.get();
runner.uninstallExtension(item.getFileName());
parent.getChildren().remove(this2);
}
});
additionalButtonBox = new HBox(reloadButton, deleteButton);
clickButton.setVisible(item.isFireButtonUsed());
exitButton.setVisible(item.isLeaveButtonVisible());
deleteButton.setVisible(item.isDeleteButtonVisible());
buttonsBox.setSpacing(8);
buttonsBox.setAlignment(Pos.CENTER);
additionalButtonBox.setSpacing(8);
additionalButtonBox.setAlignment(Pos.CENTER);
GridPane.setMargin(buttonsBox, new Insets(0, 5, 0, 5));
GridPane.setMargin(additionalButtonBox, new Insets(0, 5, 0, 5));
add(buttonsBox, 4, 0);
parent.getChildren().add(this);
GridPane this2 = this;
item.onDelete(observable -> parent.getChildren().remove(this2));
initExtension();
}
private Label initNewLabelColumn(String text) {
@ -92,4 +154,51 @@ public class ExtensionItemContainer extends GridPane {
label.setText(text);
return label;
}
private EventHandler<MouseEvent> onExit = null;
private EventHandler<MouseEvent> onClick = null;
void initExtension(){
if (onExit != null) {
exitButton.removeEventHandler(MouseEvent.MOUSE_CLICKED, onExit);
clickButton.removeEventHandler(MouseEvent.MOUSE_CLICKED, onClick);
}
onExit = event -> item.isRemoveClickTrigger();
onClick = event -> item.isClickTrigger();
exitButton.addEventHandler(MouseEvent.MOUSE_CLICKED, onExit);
clickButton.addEventHandler(MouseEvent.MOUSE_CLICKED, onClick);
ExtensionItemContainer this2 = this;
item.onDelete(observable -> {
if (item.isInstalledExtension()) {
setBackground(new Background(new BackgroundFill(Paint.valueOf("#cccccc"),null, null)));
getChildren().remove(buttonsBox);
add(additionalButtonBox, 4, 0);
reloadButton.setVisible(true);
}
else {
parent.getChildren().remove(this2);
}
});
}
void hasReconnected(GEarthExtension extension) {
item = extension;
initExtension();
setBackground(new Background(new BackgroundFill(Paint.valueOf("#ffffff"),null, null)));
getChildren().remove(additionalButtonBox);
if (buttonsBox != null) {
add(buttonsBox, 4, 0);
}
}
//returns null if there is none
String getExtensionFileName() {
if (item.isInstalledExtension()) {
return item.getFileName();
}
return null;
}
}

View File

@ -0,0 +1,45 @@
package main.ui.extensions;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;
/**
* Created by Jonas on 27/09/18.
*/
public class ExtensionItemContainerProducer {
private VBox parent;
private ScrollPane scrollPane;
private final Object lock = new Object();
private int port = -1;
public ExtensionItemContainerProducer(VBox parent, ScrollPane scrollPane) {
this.parent = parent;
this.scrollPane = scrollPane;
}
void extensionConnected(GEarthExtension extension) {
synchronized (lock) {
if (extension.isInstalledExtension()) {
for (Node n : parent.getChildren()) {
if (n instanceof ExtensionItemContainer) {
ExtensionItemContainer container = (ExtensionItemContainer) n;
if (container.getExtensionFileName().equals(extension.getFileName())) {
container.hasReconnected(extension);
return;
}
}
}
}
new ExtensionItemContainer(extension, parent, scrollPane, port);
}
}
void setPort(int port) {
this.port = port;
}
}

View File

@ -83,7 +83,7 @@
<Insets left="3.0" />
</GridPane.margin>
</Label>
<Button fx:id="btn_install" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#installBtnClicked" text="Install" GridPane.columnIndex="3" />
<Button fx:id="btn_install" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#installBtnClicked" text="Install" GridPane.columnIndex="3" />
</children>
</GridPane>
</children>

View File

@ -9,10 +9,19 @@ import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import main.Main;
import main.protocol.*;
import main.ui.SubForm;
import main.ui.extensions.executer.ExecutionInfo;
import main.ui.extensions.executer.ExtensionRunner;
import main.ui.extensions.executer.ExtensionRunnerFactory;
import main.ui.scheduler.ScheduleItem;
import sun.misc.ExtensionInfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.*;
@ -108,6 +117,9 @@ public class Extensions extends SubForm {
public GridPane header_ext;
public ScrollPane scroller;
private ExtensionRunner extensionRunner = null;
private GEarthExtensionsRegistrer extensionsRegistrer = null;
public static class OUTGOING_MESSAGES_IDS {
public static final int ONDOUBLECLICK = 1;
public static final int INFOREQUEST = 2; // backend: implemented
@ -138,6 +150,8 @@ public class Extensions extends SubForm {
}
protected void onParentSet() {
ExtensionItemContainerProducer producer = new ExtensionItemContainerProducer(extensioncontainer, scroller);
getHConnection().addStateChangeListener((oldState, newState) -> {
if (newState == HConnection.State.CONNECTED) {
for (GEarthExtension extension : gEarthExtensions) {
@ -217,7 +231,6 @@ public class Extensions extends SubForm {
});
GEarthExtensionsRegistrer extensionsRegistrer = null;
HashMap<GEarthExtension, GEarthExtension.ReceiveMessageListener> messageListeners = new HashMap<>();
try {
extensionsRegistrer = new GEarthExtensionsRegistrer(new GEarthExtensionsRegistrer.ExtensionRegisterObserver() {
@ -259,7 +272,7 @@ public class Extensions extends SubForm {
if (getHConnection().getState() == HConnection.State.CONNECTED) {
extension.sendMessage(new HPacket(OUTGOING_MESSAGES_IDS.CONNECTIONSTART));
}
Platform.runLater(() -> new ExtensionItemContainer(extension, extensioncontainer, scroller));
Platform.runLater(() -> producer.extensionConnected(extension));
extension.onRemoveClick(observable -> {
try {
extension.getConnection().close();
@ -285,11 +298,25 @@ public class Extensions extends SubForm {
e.printStackTrace();
}
producer.setPort(extensionsRegistrer.getPort());
ext_port.setText(extensionsRegistrer.getPort()+"");
// System.out.println("Extension server registered on port: " + extensionsRegistrer.getPort());
extensionRunner = ExtensionRunnerFactory.get();
extensionRunner.runAllExtensions(extensionsRegistrer.getPort());
}
public void installBtnClicked(ActionEvent actionEvent) {
List<ScheduleItem> list = new ArrayList<>();
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Install extension");
fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("G-Earth extensions", ExecutionInfo.ALLOWEDEXTENSIONTYPES));
File selectedFile = fileChooser.showOpenDialog(parentController.getStage());
if (selectedFile != null) {
extensionRunner.installAndRunExtension(selectedFile.getPath(), extensionsRegistrer.getPort());
}
}
}

View File

@ -1,16 +1,12 @@
package main.ui.extensions;
import javafx.beans.InvalidationListener;
import main.protocol.HMessage;
import main.protocol.HPacket;
import main.protocol.packethandler.PayloadBuffer;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
@ -24,6 +20,13 @@ public class GEarthExtension {
private String version;
private String description;
private boolean fireEventButtonVisible;
private boolean leaveButtonVisible;
private boolean deleteButtonVisible;
private boolean isInstalledExtension; // <- extension is in the extensions directory
private String fileName;
private Socket connection;
//calls callback when the extension is creatd
@ -53,10 +56,7 @@ public class GEarthExtension {
if (packet.headerId() == Extensions.INCOMING_MESSAGES_IDS.EXTENSIONINFO) {
GEarthExtension gEarthExtension = new GEarthExtension(
packet.readString(),
packet.readString(),
packet.readString(),
packet.readString(),
packet,
connection,
onDisconnectedCallback
);
@ -70,11 +70,19 @@ public class GEarthExtension {
}
private GEarthExtension(String title, String author, String version, String description, Socket connection, OnDisconnectedCallback onDisconnectedCallback) {
this.title = title;
this.author = author;
this.version = version;
this.description = description;
private GEarthExtension(HPacket extensionInfo, Socket connection, OnDisconnectedCallback onDisconnectedCallback) {
this.title = extensionInfo.readString();
this.author = extensionInfo.readString();
this.version = extensionInfo.readString();
this.description = extensionInfo.readString();
this.fireEventButtonVisible = extensionInfo.readBoolean();
this.isInstalledExtension = extensionInfo.readBoolean();
this.fileName = extensionInfo.readString();
this.leaveButtonVisible = extensionInfo.readBoolean();
this.deleteButtonVisible = extensionInfo.readBoolean();
this.connection = connection;
GEarthExtension selff = this;
@ -126,20 +134,31 @@ public class GEarthExtension {
public String getAuthor() {
return author;
}
public String getDescription() {
return description;
}
public String getTitle() {
return title;
}
public String getVersion() {
return version;
}
public boolean isFireButtonUsed() {
return fireEventButtonVisible;
}
public String getFileName() {
return fileName;
}
public boolean isDeleteButtonVisible() {
return deleteButtonVisible;
}
public boolean isLeaveButtonVisible() {
return leaveButtonVisible;
}
public boolean isInstalledExtension() {
return isInstalledExtension;
}
public boolean closeConnection() {
try {

View File

@ -0,0 +1,39 @@
package main.ui.extensions.executer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Jonas on 22/09/18.
*/
public class ExecutionInfo {
private static Map<String, String> extensionTypeToExecutionCommand;
public final static List<String> ALLOWEDEXTENSIONTYPES;
public final static String EXTENSIONSDIRECTORY = "Extensions";
static {
extensionTypeToExecutionCommand = new HashMap<>();
extensionTypeToExecutionCommand.put("*.jar","java -jar {path}");
extensionTypeToExecutionCommand.put("*.py","python {path}");
extensionTypeToExecutionCommand.put("*.py3","python3 {path}");
extensionTypeToExecutionCommand.put("*.sh","{path}");
extensionTypeToExecutionCommand.put("*.exe","{path}");
for(String type : extensionTypeToExecutionCommand.keySet()) {
extensionTypeToExecutionCommand.put(
type,
extensionTypeToExecutionCommand.get(type) + " -p {port} -f {filename}"
);
}
ALLOWEDEXTENSIONTYPES = new ArrayList<>(extensionTypeToExecutionCommand.keySet());
}
public static String getExecutionCommand(String type) {
return extensionTypeToExecutionCommand.get(type);
}
}

View File

@ -0,0 +1,21 @@
package main.ui.extensions.executer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by Jonas on 21/09/18.
*/
public interface ExtensionRunner {
void runAllExtensions(int port);
void installAndRunExtension(String path, int port);
void tryRunExtension(String path, int port);
void uninstallExtension(String path);
}

View File

@ -0,0 +1,17 @@
package main.ui.extensions.executer;
/**
* Created by Jonas on 22/09/18.
*/
public class ExtensionRunnerFactory {
private static ExtensionRunner runner = obtain();
public static ExtensionRunner get() {
return runner;
}
private static ExtensionRunner obtain() {
return new NormalExtensionRunner();
}
}

View File

@ -0,0 +1,128 @@
package main.ui.extensions.executer;
import main.Main;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.Arrays;
import java.util.Random;
/**
* Created by Jonas on 22/09/18.
*/
public class NormalExtensionRunner implements ExtensionRunner {
public static final String JARPATH = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParent();
@Override
public void runAllExtensions(int port) {
if (dirExists(ExecutionInfo.EXTENSIONSDIRECTORY)){
File folder =
new File(JARPATH +
FileSystems.getDefault().getSeparator()+
ExecutionInfo.EXTENSIONSDIRECTORY);
File[] childs = folder.listFiles();
for (File file : childs) {
tryRunExtension(file.getPath(), port);
}
}
}
@Override
public void installAndRunExtension(String path, int port) {
if (!dirExists(ExecutionInfo.EXTENSIONSDIRECTORY)) {
createDirectory(ExecutionInfo.EXTENSIONSDIRECTORY);
}
String name = Paths.get(path).getFileName().toString();
String[] split = name.split("\\.");
String ext = "*." + split[split.length - 1];
String realname = String.join(".",Arrays.copyOf(split, split.length-1));
String newname = realname + "-" + getRandomString() + ext.substring(1);
Path originalPath = Paths.get(path);
Path newPath = Paths.get(
JARPATH,
ExecutionInfo.EXTENSIONSDIRECTORY,
newname
);
try {
Files.copy(
originalPath,
newPath
);
addExecPermission(newPath.toString());
tryRunExtension(newPath.toString(), port);
} catch (IOException e) {
e.printStackTrace();
}
}
public void tryRunExtension(String path, int port) {
try {
Runtime.getRuntime().exec(
ExecutionInfo.getExecutionCommand(getFileExtension(path))
.replace("{path}", path)
.replace("{port}", port+"")
.replace("{filename}", Paths.get(path).getFileName().toString())
);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void uninstallExtension(String filename) {
try {
Files.delete(Paths.get(
JARPATH,
ExecutionInfo.EXTENSIONSDIRECTORY,
filename
));
} catch (IOException e) {
e.printStackTrace();
}
}
private void addExecPermission(String path) {
//not needed at first sight
}
private String getFileExtension(String path) {
String name = Paths.get(path).getFileName().toString();
String[] split = name.split("\\.");
return "*." + split[split.length - 1];
}
private boolean dirExists(String dir) {
return Files.isDirectory(Paths.get(JARPATH, dir));
}
private void createDirectory(String dir) {
if (!dirExists(dir)) {
try {
Files.createDirectories(Paths.get(JARPATH, dir));
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String getRandomString() {
StringBuilder builder = new StringBuilder();
Random r = new Random();
for (int i = 0; i < 10; i++) {
builder.append(r.nextInt(10));
}
return builder.toString();
}
}

View File

@ -12,7 +12,7 @@ public class Info extends SubForm {
public void initialize() {
String[] lines = {
"G-Earth",
"G-Earth 0.1.1",
"Linux Habbo Packet Manipulator",
"",
"Made by:",

View File

@ -8,7 +8,7 @@ import java.util.Map;
/**
* Created by Jonas on 04/04/18.
*/
class GnomeTerminalLogger extends SimpleTerminalLogger {
class LinuxTerminalLogger extends SimpleTerminalLogger {
public final static Map<String, String> colorizePackets;
static {

View File

@ -1,14 +1,19 @@
package main.ui.logger.loggerdisplays;
import main.misc.OSValidator;
/**
* Created by Jonas on 04/04/18.
*/
public class PacketLoggerFactory {
public static PacketLogger get() {
if (System.getenv("XDG_CURRENT_DESKTOP") != null && System.getenv("XDG_CURRENT_DESKTOP").toLowerCase().contains("gnome")) {
return new GnomeTerminalLogger();
if (OSValidator.isUnix()) {
return new LinuxTerminalLogger();
}
// if (System.getenv("XDG_CURRENT_DESKTOP") != null && System.getenv("XDG_CURRENT_DESKTOP").toLowerCase().contains("gnome")) {
// return new GnomeTerminalLogger();
// }
return new SimpleTerminalLogger();
}