mirror of
https://github.com/sirjonasxx/G-Earth.git
synced 2025-01-18 16:26:26 +01:00
Merge branch 'webviewLogger' into anime-edition
This commit is contained in:
commit
3e1acde242
@ -13,7 +13,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth-Parent</artifactId>
|
<artifactId>G-Earth-Parent</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
<relativePath>../../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -106,7 +106,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth</artifactId>
|
<artifactId>G-Earth</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.3</version>
|
||||||
<!--<scope>provided</scope>-->
|
<!--<scope>provided</scope>-->
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth-Parent</artifactId>
|
<artifactId>G-Earth-Parent</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
<relativePath>../../</relativePath>
|
<relativePath>../../</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@ -106,7 +106,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth</artifactId>
|
<artifactId>G-Earth</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.3</version>
|
||||||
<!--<scope>provided</scope>-->
|
<!--<scope>provided</scope>-->
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -8,22 +8,21 @@
|
|||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<javafx.version>1.8</javafx.version>
|
<javafx.version>1.8</javafx.version>
|
||||||
|
<jettyVersion>9.4.35.v20201120</jettyVersion>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth-Parent</artifactId>
|
<artifactId>G-Earth-Parent</artifactId>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|
||||||
|
|
||||||
<!-- this builds a non-standalone JAR file -->
|
<!-- this builds a non-standalone JAR file -->
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
@ -36,7 +35,7 @@
|
|||||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
<addClasspath>true</addClasspath>
|
<addClasspath>true</addClasspath>
|
||||||
<classpathPrefix>lib/</classpathPrefix>
|
<classpathPrefix>lib/</classpathPrefix>
|
||||||
<mainClass>gearth.J11Main</mainClass>
|
<mainClass>gearth.Main</mainClass>
|
||||||
<useUniqueVersions>false</useUniqueVersions>
|
<useUniqueVersions>false</useUniqueVersions>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
@ -58,7 +57,7 @@
|
|||||||
<outputDirectory>${project.build.directory}/bin</outputDirectory>
|
<outputDirectory>${project.build.directory}/bin</outputDirectory>
|
||||||
<archive>
|
<archive>
|
||||||
<manifest>
|
<manifest>
|
||||||
<mainClass>gearth.J11Main</mainClass>
|
<mainClass>gearth.Main</mainClass>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
<descriptorRefs>
|
<descriptorRefs>
|
||||||
@ -86,6 +85,11 @@
|
|||||||
<copy file="target/bin/G-Earth.jar" todir="../Build/Windows_32bit/"/>
|
<copy file="target/bin/G-Earth.jar" todir="../Build/Windows_32bit/"/>
|
||||||
<copy file="target/bin/G-Earth.jar" todir="../Build/Windows_64bit/"/>
|
<copy file="target/bin/G-Earth.jar" todir="../Build/Windows_64bit/"/>
|
||||||
|
|
||||||
|
<copy file="src/main/resources/build/messages.json" todir="../Build/Mac/"/>
|
||||||
|
<copy file="src/main/resources/build/messages.json" todir="../Build/Linux/"/>
|
||||||
|
<copy file="src/main/resources/build/messages.json" todir="../Build/Windows_32bit/"/>
|
||||||
|
<copy file="src/main/resources/build/messages.json" todir="../Build/Windows_64bit/"/>
|
||||||
|
|
||||||
<copy todir="../Build/Mac/">
|
<copy todir="../Build/Mac/">
|
||||||
<fileset dir="src/main/resources/build/mac" includes="**/*" />
|
<fileset dir="src/main/resources/build/mac" includes="**/*" />
|
||||||
</copy>
|
</copy>
|
||||||
@ -123,6 +127,7 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- <dependency>-->
|
<!-- <dependency>-->
|
||||||
<!-- <groupId>org.openjfx</groupId>-->
|
<!-- <groupId>org.openjfx</groupId>-->
|
||||||
@ -152,13 +157,51 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.tulskiy</groupId>
|
<groupId>com.github.tulskiy</groupId>
|
||||||
<artifactId>jkeymaster</artifactId>
|
<artifactId>jkeymaster</artifactId>
|
||||||
<version>1.2</version>
|
<version>1.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>slf4j-jdk14</artifactId>
|
<artifactId>slf4j-jdk14</artifactId>
|
||||||
<version>2.0.0-alpha0</version>
|
<version>2.0.0-alpha0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.maven/maven-artifact -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-artifact</artifactId>
|
||||||
|
<version>3.6.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.websocket</groupId>
|
||||||
|
<artifactId>javax.websocket-api</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-server</artifactId>
|
||||||
|
<version>${jettyVersion}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
|
<artifactId>javax-websocket-server-impl</artifactId>
|
||||||
|
<version>${jettyVersion}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-http</artifactId>
|
||||||
|
<version>${jettyVersion}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>G-Earth</groupId>
|
||||||
|
<artifactId>G-Wasm</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package gearth;
|
|
||||||
|
|
||||||
public class J11Main {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Main.main(args);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +1,53 @@
|
|||||||
package gearth;
|
package gearth;
|
||||||
|
|
||||||
import gearth.misc.AdminValidator;
|
import gearth.misc.AdminValidator;
|
||||||
|
import gearth.ui.GEarthController;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.layout.FlowPane;
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.scene.layout.Region;
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.web.WebView;
|
import javafx.scene.web.WebView;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import gearth.ui.GEarthController;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
// run as root issue Invalid MIT-MAGIC-COOKIE-1 key fix: https://stackoverflow.com/questions/48139447/invalid-mit-magic-cookie-1-key
|
// 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 {
|
public class Main extends Application {
|
||||||
|
|
||||||
public static Application main;
|
public static Application main;
|
||||||
public static String version = "1.1";
|
public static String version = "1.3";
|
||||||
private static String gitApi = "https://api.github.com/repos/sirjonasxx/G-Earth/releases/latest";
|
private static String gitApi = "https://api.github.com/repos/sirjonasxx/G-Earth/releases/latest";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception{
|
public void start(Stage primaryStage) throws Exception{
|
||||||
main = this;
|
main = this;
|
||||||
|
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/gearth/ui/G-Earth.fxml"));
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("ui/G-Earth.fxml"));
|
||||||
Parent root = loader.load();
|
Parent root = loader.load();
|
||||||
GEarthController companion = loader.getController();
|
GEarthController companion = loader.getController();
|
||||||
companion.setStage(primaryStage);
|
companion.setStage(primaryStage);
|
||||||
|
|
||||||
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("/gearth/G-EarthLogoSmaller.png")));
|
primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("G-EarthLogoSmaller.png")));
|
||||||
|
|
||||||
// TODO fix
|
|
||||||
primaryStage.setResizable(false);
|
primaryStage.setResizable(false);
|
||||||
// primaryStage.setResizable(true);
|
|
||||||
// primaryStage.onShownProperty().addListener(e -> {
|
|
||||||
// Platform.runLater(() -> primaryStage.setResizable(false));
|
|
||||||
// });
|
|
||||||
|
|
||||||
//primaryStage.initStyle(StageStyle.UNDECORATED);
|
|
||||||
primaryStage.setTitle("G-Earth " + version);
|
primaryStage.setTitle("G-Earth " + version);
|
||||||
primaryStage.setScene(new Scene(root, 650, 295));
|
primaryStage.setScene(new Scene(root, 650, 295));
|
||||||
primaryStage.show();
|
primaryStage.show();
|
||||||
primaryStage.getScene().getStylesheets().add(getClass().getResource("/gearth/ui/bootstrap3.css").toExternalForm());
|
primaryStage.getScene().getStylesheets().add(getClass().getResource("ui/bootstrap3.css").toExternalForm());
|
||||||
|
|
||||||
primaryStage.setOnCloseRequest( event -> {
|
primaryStage.setOnCloseRequest( event -> {
|
||||||
companion.exit();
|
companion.exit();
|
||||||
@ -58,21 +57,17 @@ public class Main extends Application {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
new Thread(() -> {
|
// new Thread(() -> {
|
||||||
if (!AdminValidator.isAdmin()) {
|
// if (!AdminValidator.isAdmin()) {
|
||||||
Platform.runLater(() -> {
|
// Platform.runLater(() -> {
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR, "G-Earth needs admin privileges in order to work properly, please restart G-Earth with admin permissions unless you know what you're doing", ButtonType.OK);
|
// Alert alert = new Alert(Alert.AlertType.ERROR, "G-Earth needs admin privileges in order to work properly, please restart G-Earth with admin permissions unless you know what you're doing", ButtonType.OK);
|
||||||
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
// alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
alert.setResizable(false);
|
// alert.setResizable(false);
|
||||||
// alert.setResizable(true);
|
// alert.show();
|
||||||
// alert.onShownProperty().addListener(e -> {
|
// });
|
||||||
// Platform.runLater(() -> alert.setResizable(false));
|
//
|
||||||
// });
|
// }
|
||||||
alert.show();
|
// }).start();
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
@ -83,7 +78,7 @@ public class Main extends Application {
|
|||||||
if (!gitv.equals(version)) {
|
if (!gitv.equals(version)) {
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
String body = (String)object.get("body");
|
String body = (String)object.get("body");
|
||||||
boolean isForcedUpdate = body.contains("<F>");
|
boolean isForcedUpdate = body.contains("(!)");
|
||||||
|
|
||||||
Alert alert = new Alert(isForcedUpdate ? Alert.AlertType.ERROR : Alert.AlertType.INFORMATION, "G-Earth is outdated!", ButtonType.OK);
|
Alert alert = new Alert(isForcedUpdate ? Alert.AlertType.ERROR : Alert.AlertType.INFORMATION, "G-Earth is outdated!", ButtonType.OK);
|
||||||
|
|
||||||
@ -103,11 +98,6 @@ public class Main extends Application {
|
|||||||
webView.setPrefSize(500, 200);
|
webView.setPrefSize(500, 200);
|
||||||
|
|
||||||
alert.setResizable(false);
|
alert.setResizable(false);
|
||||||
// alert.setResizable(true);
|
|
||||||
// alert.onShownProperty().addListener(e -> {
|
|
||||||
// Platform.runLater(() -> alert.setResizable(false));
|
|
||||||
// });
|
|
||||||
|
|
||||||
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
alert.getDialogPane().setContent(fp);
|
alert.getDialogPane().setContent(fp);
|
||||||
if (isForcedUpdate) {
|
if (isForcedUpdate) {
|
||||||
|
@ -298,7 +298,13 @@ public abstract class Extension implements IExtension {
|
|||||||
public boolean requestFlags(FlagsCheckListener flagRequestCallback) {
|
public boolean requestFlags(FlagsCheckListener flagRequestCallback) {
|
||||||
if (this.flagRequestCallback != null) return false;
|
if (this.flagRequestCallback != null) return false;
|
||||||
this.flagRequestCallback = flagRequestCallback;
|
this.flagRequestCallback = flagRequestCallback;
|
||||||
return true;
|
try {
|
||||||
|
writeToStream(new HPacket(NetworkExtensionInfo.INCOMING_MESSAGES_IDS.REQUESTFLAGS).toBytes());
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ import gearth.protocol.HPacket;
|
|||||||
public abstract class ExtensionForm implements IExtension {
|
public abstract class ExtensionForm implements IExtension {
|
||||||
|
|
||||||
volatile Extension extension;
|
volatile Extension extension;
|
||||||
volatile Stage primaryStage;
|
protected volatile Stage primaryStage;
|
||||||
|
|
||||||
protected static void runExtensionForm(String[] args, Class<? extends ExtensionForm> extension) {
|
protected static void runExtensionForm(String[] args, Class<? extends ExtensionForm> extension) {
|
||||||
ExtensionFormLauncher launcher = new ExtensionFormLauncher();
|
ExtensionFormLauncher launcher = new ExtensionFormLauncher();
|
||||||
|
@ -6,6 +6,7 @@ import gearth.misc.harble_api.HarbleAPI;
|
|||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
import gearth.protocol.HPacket;
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -30,7 +31,7 @@ public class HashSupport {
|
|||||||
|
|
||||||
extension.onConnect((host, port, hotelversion, cachePath) -> {
|
extension.onConnect((host, port, hotelversion, cachePath) -> {
|
||||||
// synchronized (lock) {
|
// synchronized (lock) {
|
||||||
harbleAPI = new HarbleAPI(hotelversion, cachePath);
|
harbleAPI = new HarbleAPI(new File(cachePath));
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4,14 +4,14 @@ import gearth.protocol.HPacket;
|
|||||||
|
|
||||||
public class HEntityUpdate {
|
public class HEntityUpdate {
|
||||||
private int index;
|
private int index;
|
||||||
private boolean isController;
|
private boolean isController = false;
|
||||||
|
|
||||||
private HPoint tile;
|
private HPoint tile;
|
||||||
private HPoint movingTo;
|
private HPoint movingTo = null;
|
||||||
|
|
||||||
private HSign sign;
|
private HSign sign = null;
|
||||||
private HStance stance;
|
private HStance stance = null;
|
||||||
private HAction action;
|
private HAction action = null;
|
||||||
private HDirection headFacing;
|
private HDirection headFacing;
|
||||||
private HDirection bodyFacing;
|
private HDirection bodyFacing;
|
||||||
|
|
||||||
|
@ -71,7 +71,6 @@ public class HarbleAPI {
|
|||||||
|
|
||||||
private boolean success = false;
|
private boolean success = false;
|
||||||
private String fullPath = null;
|
private String fullPath = null;
|
||||||
private String revision = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cache file must be generated first within G-Earth, inb4 20 extensions requesting it at the same time
|
* cache file must be generated first within G-Earth, inb4 20 extensions requesting it at the same time
|
||||||
@ -92,22 +91,18 @@ public class HarbleAPI {
|
|||||||
if (Cacher.cacheFileExists(possibleCachedMessagesPath)) {
|
if (Cacher.cacheFileExists(possibleCachedMessagesPath)) {
|
||||||
JSONObject object = Cacher.getCacheContents(possibleCachedMessagesPath);
|
JSONObject object = Cacher.getCacheContents(possibleCachedMessagesPath);
|
||||||
success = true;
|
success = true;
|
||||||
revision = hotelversion;
|
|
||||||
fullPath = Cacher.getCacheDir() + File.separator + possibleCachedMessagesPath;
|
fullPath = Cacher.getCacheDir() + File.separator + possibleCachedMessagesPath;
|
||||||
parse(object);
|
parse(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public HarbleAPI(String hotelversion, String path_to_file) {
|
public HarbleAPI(File f) {
|
||||||
|
|
||||||
File f = new File(path_to_file);
|
|
||||||
if (f.exists() && !f.isDirectory()) {
|
if (f.exists() && !f.isDirectory()) {
|
||||||
try {
|
try {
|
||||||
String contents = String.join("\n", Files.readAllLines(f.toPath()));
|
String contents = String.join("\n", Files.readAllLines(f.toPath()));
|
||||||
JSONObject object = new JSONObject(contents);
|
JSONObject object = new JSONObject(contents);
|
||||||
success = true;
|
success = true;
|
||||||
revision = hotelversion;
|
fullPath = f.getAbsolutePath();
|
||||||
fullPath = path_to_file;
|
|
||||||
parse(object);
|
parse(object);
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -118,15 +113,16 @@ public class HarbleAPI {
|
|||||||
|
|
||||||
private void addMessage(HMessage.Direction direction, JSONObject object) {
|
private void addMessage(HMessage.Direction direction, JSONObject object) {
|
||||||
String name;
|
String name;
|
||||||
try {
|
String hash;
|
||||||
name = object.getString("Name");
|
try { name = object.getString("Name"); }
|
||||||
} catch (Exception e) {
|
catch (Exception e) { name = null; }
|
||||||
name = null;
|
try { hash = object.getString("Hash"); }
|
||||||
}
|
catch (Exception e) { hash = null; }
|
||||||
String hash = object.getString("Hash");
|
|
||||||
Integer headerId = object.getInt("Id");
|
|
||||||
String structure;
|
|
||||||
|
|
||||||
|
|
||||||
|
int headerId = object.getInt("Id");
|
||||||
|
|
||||||
|
String structure;
|
||||||
try {
|
try {
|
||||||
structure = object.getString("Structure");
|
structure = object.getString("Structure");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -218,10 +214,6 @@ public class HarbleAPI {
|
|||||||
return nameToMessage.get(name);
|
return nameToMessage.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getRevision() {
|
|
||||||
return revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
if (success) {
|
if (success) {
|
||||||
return fullPath;
|
return fullPath;
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package gearth.misc.harble_api;
|
package gearth.misc.harble_api;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
import org.jsoup.Connection;
|
import org.jsoup.Connection;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 10/11/2018.
|
* Created by Jonas on 10/11/2018.
|
||||||
@ -36,6 +39,20 @@ public class HarbleAPIFetcher {
|
|||||||
public static HarbleAPI HARBLEAPI = null;
|
public static HarbleAPI HARBLEAPI = null;
|
||||||
|
|
||||||
public synchronized static void fetch(String hotelversion) {
|
public synchronized static void fetch(String hotelversion) {
|
||||||
|
// if unity
|
||||||
|
if (!(hotelversion.toLowerCase().contains("production") || hotelversion.toLowerCase().contains("release"))) {
|
||||||
|
try {
|
||||||
|
HARBLEAPI = new HarbleAPI(
|
||||||
|
new File(new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI())
|
||||||
|
.getParentFile(), "messages.json"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
HARBLEAPI = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String cacheName = CACHE_PREFIX + hotelversion;
|
String cacheName = CACHE_PREFIX + hotelversion;
|
||||||
|
|
||||||
if (Cacher.cacheFileExists(cacheName)) {
|
if (Cacher.cacheFileExists(cacheName)) {
|
||||||
|
@ -39,12 +39,18 @@ public class PacketStringUtils {
|
|||||||
packet = replaceAll(packet, "\\{i:(-?[0-9]+)}",
|
packet = replaceAll(packet, "\\{i:(-?[0-9]+)}",
|
||||||
m -> toString(ByteBuffer.allocate(4).putInt(Integer.parseInt(m.group(1))).array()));
|
m -> toString(ByteBuffer.allocate(4).putInt(Integer.parseInt(m.group(1))).array()));
|
||||||
|
|
||||||
|
packet = replaceAll(packet, "\\{l:(-?[0-9]+)}",
|
||||||
|
m -> toString(ByteBuffer.allocate(8).putLong(Integer.parseInt(m.group(1))).array()));
|
||||||
|
|
||||||
packet = replaceAll(packet, "\\{d:(-?[0-9]*\\.[0-9]*)}",
|
packet = replaceAll(packet, "\\{d:(-?[0-9]*\\.[0-9]*)}",
|
||||||
m -> toString(ByteBuffer.allocate(8).putDouble(Double.parseDouble(m.group(1))).array()));
|
m -> toString(ByteBuffer.allocate(8).putDouble(Double.parseDouble(m.group(1))).array()));
|
||||||
|
|
||||||
packet = replaceAll(packet, "\\{u:([0-9]+)}",
|
packet = replaceAll(packet, "\\{u:([0-9]+)}",
|
||||||
m -> "[" + (Integer.parseInt(m.group(1))/256) + "][" + (Integer.parseInt(m.group(1)) % 256) + "]");
|
m -> "[" + (Integer.parseInt(m.group(1))/256) + "][" + (Integer.parseInt(m.group(1)) % 256) + "]");
|
||||||
|
|
||||||
|
packet = replaceAll(packet, "\\{h:([0-9]+)}",
|
||||||
|
m -> "[" + (Integer.parseInt(m.group(1))/256) + "][" + (Integer.parseInt(m.group(1)) % 256) + "]");
|
||||||
|
|
||||||
packet = replaceAll(packet, "\\{b:([Ff]alse|[Tt]rue)}",
|
packet = replaceAll(packet, "\\{b:([Ff]alse|[Tt]rue)}",
|
||||||
m -> m.group(1).toLowerCase().equals("true") ? "[1]" : "[0]");
|
m -> m.group(1).toLowerCase().equals("true") ? "[1]" : "[0]");
|
||||||
|
|
||||||
@ -174,7 +180,7 @@ public class PacketStringUtils {
|
|||||||
packet.resetReadIndex();
|
packet.resetReadIndex();
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("{l}{u:").append(packet.headerId()).append("}");
|
builder.append("{l}{h:").append(packet.headerId()).append("}");
|
||||||
|
|
||||||
buildExpressionFromGivenStructure(packet, struct, 0, builder);
|
buildExpressionFromGivenStructure(packet, struct, 0, builder);
|
||||||
packet.setReadIndex(oldReadIndex);
|
packet.setReadIndex(oldReadIndex);
|
||||||
@ -196,7 +202,7 @@ public class PacketStringUtils {
|
|||||||
}
|
}
|
||||||
else if (c == 'i') builder.append("{i:").append(prevInt = p.readInteger()).append('}');
|
else if (c == 'i') builder.append("{i:").append(prevInt = p.readInteger()).append('}');
|
||||||
else if (c == 's') builder.append("{s:\"").append(
|
else if (c == 's') builder.append("{s:\"").append(
|
||||||
new String(p.readString().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)
|
p.readString(StandardCharsets.UTF_8)
|
||||||
.replace("\\", "\\\\") // \ -> \\
|
.replace("\\", "\\\\") // \ -> \\
|
||||||
.replace("\"", "\\\"") // " -> \"
|
.replace("\"", "\\\"") // " -> \"
|
||||||
.replace("\r", "\\r") // CR -> \r
|
.replace("\r", "\\r") // CR -> \r
|
||||||
@ -204,6 +210,8 @@ public class PacketStringUtils {
|
|||||||
else if (c == 'd') builder.append("{d:").append(p.readDouble()).append('}');
|
else if (c == 'd') builder.append("{d:").append(p.readDouble()).append('}');
|
||||||
else if (c == 'b') builder.append("{b:").append(p.readByte()).append('}');
|
else if (c == 'b') builder.append("{b:").append(p.readByte()).append('}');
|
||||||
else if (c == 'B') builder.append("{b:").append(p.readBoolean()).append('}');
|
else if (c == 'B') builder.append("{b:").append(p.readBoolean()).append('}');
|
||||||
|
else if (c == 'l') builder.append("{l:").append(p.readLong()).append('}');
|
||||||
|
else if (c == 'u') builder.append("{u:").append(p.readShort()).append('}');
|
||||||
else return;
|
else return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,16 +240,16 @@ public class PacketStringUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws InvalidPacketException {
|
public static void main(String[] args) throws InvalidPacketException {
|
||||||
HPacket p1 = fromString("{l}{u:1129}{s:\"\\\\\\\\\"}{i:0}{i:0}");
|
HPacket p1 = fromString("{l}{h:1129}{s:\"\\\\\\\\\"}{i:0}{i:0}");
|
||||||
System.out.println(p1.toExpression());
|
System.out.println(p1.toExpression());
|
||||||
HPacket p1_2 = fromString(p1.toExpression());
|
HPacket p1_2 = fromString(p1.toExpression());
|
||||||
System.out.println(p1_2.toExpression());
|
System.out.println(p1_2.toExpression());
|
||||||
|
|
||||||
HPacket p2 = fromString("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}");
|
HPacket p2 = fromString("{l}{h:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}");
|
||||||
System.out.println(p2);
|
System.out.println(p2);
|
||||||
|
|
||||||
System.out.println(structureEquals(
|
System.out.println(structureEquals(
|
||||||
new HPacket("{l}{u:5}{s:\"asdas\"}"),
|
new HPacket("{l}{h:5}{s:\"asdas\"}"),
|
||||||
"s"
|
"s"
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ import java.util.List;
|
|||||||
|
|
||||||
public class StructurePredictor {
|
public class StructurePredictor {
|
||||||
|
|
||||||
HPacket packet;
|
private HPacket packet;
|
||||||
String structure; // null if not found/ didnt try to find
|
private String structure; // null if not found/ didnt try to find
|
||||||
|
|
||||||
public StructurePredictor(HPacket packet) {
|
public StructurePredictor(HPacket packet) {
|
||||||
this.packet = packet;
|
this.packet = packet;
|
||||||
@ -44,17 +44,12 @@ public class StructurePredictor {
|
|||||||
while (index < packet.getBytesLength()) {
|
while (index < packet.getBytesLength()) {
|
||||||
double currentLogScore = dynamic[index - 6].logScore;
|
double currentLogScore = dynamic[index - 6].logScore;
|
||||||
for (TypeChecker typeChecker : typeCheckers) {
|
for (TypeChecker typeChecker : typeCheckers) {
|
||||||
if (typeChecker.canRead(index)) {
|
if (!typeChecker.canRead(index)) continue;
|
||||||
double score = typeChecker.score(index);
|
|
||||||
double newScore = currentLogScore + Math.log(score);
|
double newScore = currentLogScore + Math.log(typeChecker.score(index));
|
||||||
int nextIndex = typeChecker.nextIndex(index) - 6;
|
int nextIndex = typeChecker.nextIndex(index) - 6;
|
||||||
if (dynamic[nextIndex] == null || newScore > dynamic[nextIndex].logScore) {
|
if (dynamic[nextIndex] == null || newScore > dynamic[nextIndex].logScore) {
|
||||||
dynamic[nextIndex] = new SubStructure(
|
dynamic[nextIndex] = new SubStructure(index - 6, typeChecker.getStructCode(), newScore);
|
||||||
index - 6,
|
|
||||||
typeChecker.getStructCode(),
|
|
||||||
newScore
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
@ -80,39 +75,4 @@ public class StructurePredictor {
|
|||||||
public String getStructure() {
|
public String getStructure() {
|
||||||
return structure;
|
return structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
HPacket[] packets = new HPacket[] {
|
|
||||||
new HPacket("{l}{u:500}{i:20}"),
|
|
||||||
new HPacket(4002, "test"),
|
|
||||||
new HPacket(4002, "test", 0, true),
|
|
||||||
new HPacket(4002, "test", "testtsd", 54452, true, false),
|
|
||||||
new HPacket(4002, "test", 46564554, "testtsd", 54452, true, false),
|
|
||||||
new HPacket(4002, "test", 0, 46564554, "testtsd", 54452, true, false),
|
|
||||||
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, true, false),
|
|
||||||
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, ""),
|
|
||||||
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, ""),
|
|
||||||
new HPacket(4002, -1, "test", 0, 46564554, "testtsd", -1, 54452, false, true, 0),
|
|
||||||
new HPacket(4002, -1, (byte) 5, "test", 0, 46564554, "testtsd", -1, 54452, false, true, 0),
|
|
||||||
new HPacket(4002, "", 20, 0),
|
|
||||||
new HPacket(4002, 1),
|
|
||||||
new HPacket(4002, 0, 0),
|
|
||||||
new HPacket(4002, 0, 0, 42, false),
|
|
||||||
new HPacket(4002, 0, ""),
|
|
||||||
new HPacket("[0][0][0]F[0] [0][0][0] [0][0][0][5][0]\u0013ACH_FriendListSize5[0][0][0]U[0][0][0] [0][0][0][0][0][0][0][0][0][0][0]Z[0][0][6]social[0][0][0][0][0][13][0][0][0][2]"),
|
|
||||||
new HPacket("[0][0][0]?[0] [0][0][0][4][0][0][0][4][0][10]ACH_Login4[0][0][0]\u000F[0][0][0]\u001C[0][0][0][0][0][0][0][0][0][0][0][2][0][0][8]identity[0][0][0][0][0]\u0014[0][0][0][0]"),
|
|
||||||
new HPacket("[0][0][0][6]\u000Ew[0][0][0][0]"),
|
|
||||||
new HPacket("[0][0][0]'[3] [0][5]Login[0][6]socket[0]\u000Eclient.auth_ok[0][0][0][0][0][0]"),
|
|
||||||
new HPacket(4002, false, ""),
|
|
||||||
new HPacket("{l}{u:145}[0][0][0]ÿÿÿÿ[0]"),
|
|
||||||
// new HPacket("[0][0][1]p[13]1[0][0][0][12][0][10]MOUSE_ZOOM[0][0][1][0]\u0015HABBO_CLUB_OFFER_BETA[0][0][1][0]\u000EUSE_GUIDE_TOOL[0]&requirement.unfulfilled.helper_level_4[0][0]\u000FBUILDER_AT_WORK[0](requirement.unfulfilled.group_membership[0][0]\u000FCALL_ON_HELPERS[0][0][1][0]\u001FNAVIGATOR_ROOM_THUMBNAIL_CAMERA[0][0][1][0][7]CITIZEN[0][0][1][0]\u0012JUDGE_CHAT_REVIEWS[0]&requirement.unfulfilled.helper_level_6[0][0][5]TRADE[0][0][1][0][6]CAMERA[0][0][1][0]\u0014VOTE_IN_COMPETITIONS[0][0][1][0]\u0018NAVIGATOR_PHASE_TWO_2014[0][0][1]")
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
for (HPacket packet : packets) {
|
|
||||||
StructurePredictor structurePredictor = new StructurePredictor(packet);
|
|
||||||
System.out.println(structurePredictor.getStructure());
|
|
||||||
System.out.println(structurePredictor.getExpression());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gearth.misc.packetrepresentation.prediction.checkers;
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
import gearth.protocol.HPacket;
|
import gearth.protocol.HPacket;
|
||||||
|
import gearth.services.Constants;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ public class IntegerChecker extends TypeChecker<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4 bytes that read [0][2]xy could be a string
|
// 4 bytes that read [0][2]xy could be a string
|
||||||
if (ushortTest >= 2 && ushortTest <= 6 && StringChecker.canReadString(hPacket, index)) {
|
if (ushortTest == 2 && StringChecker.canReadString(hPacket, index)) {
|
||||||
return (1 - StringChecker.scoreString(hPacket.readString(index)));
|
return (1 - StringChecker.scoreString(hPacket.readString(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
public class LongChecker extends TypeChecker<Long> {
|
||||||
|
|
||||||
|
private IntegerChecker integerChecker;
|
||||||
|
|
||||||
|
protected LongChecker(HPacket hPacket) {
|
||||||
|
super("l", hPacket);
|
||||||
|
integerChecker = new IntegerChecker(hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return index >= 6 && !(index + 8 > hPacket.getBytesLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
int split1 = hPacket.readInteger(index);
|
||||||
|
int split2 = hPacket.readInteger(index + 4);
|
||||||
|
|
||||||
|
int zeros = 0;
|
||||||
|
for (int i = index + 4; i < index + 8; i++) {
|
||||||
|
zeros += hPacket.readByte(i) == 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split2 > 256 * 256 * 3 && split1 == 0 && zeros < 2) {
|
||||||
|
return integerChecker.score(index) * integerChecker.score(index + 4) + 0.0000000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Long get(int index) {
|
||||||
|
return hPacket.readLong(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + 8;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package gearth.misc.packetrepresentation.prediction.checkers;
|
||||||
|
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
public class ShortChecker extends TypeChecker {
|
||||||
|
|
||||||
|
private BooleanChecker booleanChecker;
|
||||||
|
private ByteChecker byteChecker;
|
||||||
|
|
||||||
|
protected ShortChecker(HPacket hPacket) {
|
||||||
|
super("u", hPacket);
|
||||||
|
booleanChecker = new BooleanChecker(hPacket);
|
||||||
|
byteChecker = new ByteChecker(hPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRead(int index) {
|
||||||
|
return index >= 6 && !(index + 2 > hPacket.getBytesLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double score(int index) {
|
||||||
|
short val = hPacket.readShort(index);
|
||||||
|
|
||||||
|
if (index == 6 && val == 0 && hPacket.length() == nextIndexSafe(index)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val < 1000) {
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
double leftMinScore;
|
||||||
|
double rightMinScore;
|
||||||
|
if (booleanChecker.canRead(index)) leftMinScore = booleanChecker.score(index);
|
||||||
|
else leftMinScore = byteChecker.score(index);
|
||||||
|
if (booleanChecker.canRead(index+1)) rightMinScore = booleanChecker.score(index+1);
|
||||||
|
else rightMinScore = byteChecker.score(index+1);
|
||||||
|
|
||||||
|
return leftMinScore * rightMinScore + 0.00000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Object get(int index) {
|
||||||
|
return hPacket.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int nextIndexSafe(int index) {
|
||||||
|
return index + 2;
|
||||||
|
}
|
||||||
|
}
|
@ -2,18 +2,27 @@ package gearth.misc.packetrepresentation.prediction.checkers;
|
|||||||
|
|
||||||
import gearth.protocol.HPacket;
|
import gearth.protocol.HPacket;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static gearth.services.Constants.UNITY_PACKETS;
|
||||||
|
|
||||||
public class TypeCheckerProducer {
|
public class TypeCheckerProducer {
|
||||||
|
|
||||||
public static List<TypeChecker> getValidators(HPacket packet) {
|
public static List<TypeChecker> getValidators(HPacket packet) {
|
||||||
return Arrays.asList(
|
List<TypeChecker> typeCheckers = new ArrayList<>(Arrays.asList(
|
||||||
new BooleanChecker(packet),
|
new BooleanChecker(packet),
|
||||||
new ByteChecker(packet),
|
new ByteChecker(packet),
|
||||||
new IntegerChecker(packet),
|
new IntegerChecker(packet),
|
||||||
new StringChecker(packet)
|
new StringChecker(packet)));
|
||||||
);
|
|
||||||
|
if (UNITY_PACKETS) {
|
||||||
|
typeCheckers.add(new LongChecker(packet));
|
||||||
|
typeCheckers.add(new ShortChecker(packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeCheckers;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ import gearth.misc.listenerpattern.Observable;
|
|||||||
import gearth.protocol.connection.HProxy;
|
import gearth.protocol.connection.HProxy;
|
||||||
import gearth.protocol.connection.HState;
|
import gearth.protocol.connection.HState;
|
||||||
import gearth.protocol.connection.proxy.ProxyProvider;
|
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||||
|
import gearth.protocol.connection.proxy.flash.FlashProxyProvider;
|
||||||
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||||
import gearth.protocol.connection.proxy.unix.LinuxRawIpProxyProvider;
|
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
|
||||||
import gearth.protocol.connection.proxy.windows.WindowsRawIpProxyProvider;
|
import gearth.protocol.connection.proxy.unity.UnityProxyProvider;
|
||||||
import gearth.services.extensionhandler.ExtensionHandler;
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -60,6 +61,12 @@ public class HConnection {
|
|||||||
startMITM();
|
startMITM();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startUnity() {
|
||||||
|
HConnection selff = this;
|
||||||
|
proxyProvider = new UnityProxyProvider(proxy -> selff.proxy = proxy, selff::setState, this);
|
||||||
|
startMITM();
|
||||||
|
}
|
||||||
|
|
||||||
private void startMITM() {
|
private void startMITM() {
|
||||||
try {
|
try {
|
||||||
if (proxyProvider != null) {
|
if (proxyProvider != null) {
|
||||||
@ -166,7 +173,7 @@ public class HConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRawIpMode() {
|
public boolean isRawIpMode() {
|
||||||
return proxyProvider != null && proxyProvider instanceof LinuxRawIpProxyProvider;
|
return proxyProvider != null && proxyProvider instanceof LinuxRawIpFlashProxyProvider;
|
||||||
// WindowsRawIpProxyProvider extends LinuxRawIpProxyProvider
|
// WindowsRawIpProxyProvider extends LinuxRawIpProxyProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import gearth.misc.packetrepresentation.PacketStringUtils;
|
|||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -36,7 +37,7 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
public HPacket(int header) {
|
public HPacket(int header) {
|
||||||
packetInBytes = new byte[]{0,0,0,2,0,0};
|
packetInBytes = new byte[]{0,0,0,2,0,0};
|
||||||
replaceUShort(4, header);
|
replaceShort(4, (short)header);
|
||||||
isEdited = false;
|
isEdited = false;
|
||||||
}
|
}
|
||||||
public HPacket(int header, byte[] bytes) {
|
public HPacket(int header, byte[] bytes) {
|
||||||
@ -126,7 +127,7 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int headerId() {
|
public int headerId() {
|
||||||
return readUshort(4);
|
return readShort(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readInteger(){
|
public int readInteger(){
|
||||||
@ -180,34 +181,49 @@ public class HPacket implements StringifyAble {
|
|||||||
return java.nio.ByteBuffer.wrap(btarray).getLong();
|
return java.nio.ByteBuffer.wrap(btarray).getLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readString() {
|
|
||||||
String r = readString(readIndex);
|
public String readString(Charset charset) {
|
||||||
readIndex += (2 + r.length());
|
String r = readString(readIndex, charset);
|
||||||
|
readIndex += (2 + readUshort(readIndex));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
public String readString(int index) {
|
public String readString(int index, Charset charset) {
|
||||||
int length = readUshort(index);
|
int length = readUshort(index);
|
||||||
index+=2;
|
index+=2;
|
||||||
|
return readString(index, length, charset);
|
||||||
return readString(index, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readString(int index, int length) {
|
public String readString() {
|
||||||
|
return readString(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
public String readString(int index) {
|
||||||
|
return readString(index, StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readString(int index, int length, Charset charset) {
|
||||||
byte[] x = new byte[length];
|
byte[] x = new byte[length];
|
||||||
for (int i = 0; i < x.length; i++) { x[i] = readByte(index); index++; }
|
for (int i = 0; i < x.length; i++) { x[i] = readByte(index); index++; }
|
||||||
return new String(x, StandardCharsets.ISO_8859_1);
|
return new String(x, charset);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readLongString() {
|
|
||||||
String r = readLongString(readIndex);
|
public String readLongString(Charset charset) {
|
||||||
readIndex += (4 + r.length());
|
String r = readLongString(readIndex, charset);
|
||||||
|
readIndex += (4 + readInteger(readIndex));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
public String readLongString(int index) {
|
public String readLongString(int index, Charset charset) {
|
||||||
int length = readInteger(index);
|
int length = readInteger(index);
|
||||||
index += 4;
|
index += 4;
|
||||||
|
|
||||||
return readString(index, length);
|
return readString(index, length, charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readLongString() {
|
||||||
|
return readLongString(StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
public String readLongString(int index) {
|
||||||
|
return readLongString(index, StandardCharsets.ISO_8859_1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean readBoolean() {
|
public boolean readBoolean() {
|
||||||
@ -231,6 +247,14 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public HPacket replaceLong(int index, long l) {
|
||||||
|
isEdited = true;
|
||||||
|
ByteBuffer b = ByteBuffer.allocate(8).putLong(l);
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
packetInBytes[index + j] = b.array()[j];
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public HPacket replaceDouble(int index, double d) {
|
public HPacket replaceDouble(int index, double d) {
|
||||||
isEdited = true;
|
isEdited = true;
|
||||||
ByteBuffer b = ByteBuffer.allocate(8).putDouble(d);
|
ByteBuffer b = ByteBuffer.allocate(8).putDouble(d);
|
||||||
@ -267,10 +291,11 @@ public class HPacket implements StringifyAble {
|
|||||||
packetInBytes[index + 1] = b.array()[1];
|
packetInBytes[index + 1] = b.array()[1];
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public HPacket replaceString(int index, String s) {
|
|
||||||
|
public HPacket replaceString(int index, String s, Charset charset) {
|
||||||
isEdited = true;
|
isEdited = true;
|
||||||
byte[] sbytes = s.getBytes(StandardCharsets.ISO_8859_1);
|
byte[] sbytes = s.getBytes(charset);
|
||||||
int mover = s.length() - readUshort(index);
|
int mover = sbytes.length - readUshort(index);
|
||||||
|
|
||||||
if (mover != 0) {
|
if (mover != 0) {
|
||||||
byte[] newPacket = Arrays.copyOf(packetInBytes, packetInBytes.length + mover);
|
byte[] newPacket = Arrays.copyOf(packetInBytes, packetInBytes.length + mover);
|
||||||
@ -283,7 +308,7 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i = index + 2 + s.length();
|
int i = index + 2 + sbytes.length;
|
||||||
while (i < newPacket.length) {
|
while (i < newPacket.length) {
|
||||||
newPacket[i] = packetInBytes[i - mover];
|
newPacket[i] = packetInBytes[i - mover];
|
||||||
i++;
|
i++;
|
||||||
@ -294,13 +319,17 @@ public class HPacket implements StringifyAble {
|
|||||||
fixLength();
|
fixLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
replaceUShort(index, s.length());
|
replaceUShort(index, sbytes.length);
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < sbytes.length; i++) {
|
||||||
packetInBytes[index + 2 + i] = sbytes[i];
|
packetInBytes[index + 2 + i] = sbytes[i];
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HPacket replaceString(int index, String s) {
|
||||||
|
return replaceString(index, s, StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean canReadString(int index) {
|
private boolean canReadString(int index) {
|
||||||
if (index < packetInBytes.length - 1) {
|
if (index < packetInBytes.length - 1) {
|
||||||
int l = readUshort(index);
|
int l = readUshort(index);
|
||||||
@ -394,6 +423,16 @@ public class HPacket implements StringifyAble {
|
|||||||
fixLength();
|
fixLength();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public HPacket appendLong(long l) {
|
||||||
|
isEdited = true;
|
||||||
|
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 8);
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocate(8).putLong(l);
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
packetInBytes[packetInBytes.length - 8 + j] = byteBuffer.array()[j];
|
||||||
|
}
|
||||||
|
fixLength();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public HPacket appendDouble(double d) {
|
public HPacket appendDouble(double d) {
|
||||||
isEdited = true;
|
isEdited = true;
|
||||||
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 8);
|
packetInBytes = Arrays.copyOf(packetInBytes, packetInBytes.length + 8);
|
||||||
@ -445,18 +484,27 @@ public class HPacket implements StringifyAble {
|
|||||||
fixLength();
|
fixLength();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public HPacket appendString(String s, Charset charset) {
|
||||||
|
isEdited = true;
|
||||||
|
appendUShort(s.getBytes(charset).length);
|
||||||
|
appendBytes(s.getBytes(charset));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
public HPacket appendString(String s) {
|
public HPacket appendString(String s) {
|
||||||
|
return appendString(s, StandardCharsets.ISO_8859_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HPacket appendLongString(String s, Charset charset) {
|
||||||
isEdited = true;
|
isEdited = true;
|
||||||
appendUShort(s.length());
|
appendInt(s.getBytes(charset).length);
|
||||||
appendBytes(s.getBytes(StandardCharsets.ISO_8859_1));
|
appendBytes(s.getBytes(charset));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HPacket appendLongString(String s) {
|
public HPacket appendLongString(String s) {
|
||||||
isEdited = true;
|
return appendLongString(s, StandardCharsets.ISO_8859_1);
|
||||||
appendInt(s.length());
|
|
||||||
appendBytes(s.getBytes(StandardCharsets.ISO_8859_1));
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public HPacket appendObject(Object o) throws InvalidParameterException {
|
public HPacket appendObject(Object o) throws InvalidParameterException {
|
||||||
isEdited = true;
|
isEdited = true;
|
||||||
|
|
||||||
@ -472,6 +520,9 @@ public class HPacket implements StringifyAble {
|
|||||||
else if (o instanceof Boolean) {
|
else if (o instanceof Boolean) {
|
||||||
appendBoolean((Boolean) o);
|
appendBoolean((Boolean) o);
|
||||||
}
|
}
|
||||||
|
else if (o instanceof Long) {
|
||||||
|
appendLong((Long) o);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw new InvalidParameterException();
|
throw new InvalidParameterException();
|
||||||
}
|
}
|
||||||
@ -479,20 +530,6 @@ public class HPacket implements StringifyAble {
|
|||||||
return this;
|
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() {
|
public boolean isReplaced() {
|
||||||
return isEdited;
|
return isEdited;
|
||||||
}
|
}
|
||||||
@ -507,25 +544,44 @@ public class HPacket implements StringifyAble {
|
|||||||
isEdited = edited;
|
isEdited = edited;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toExpression(HMessage.Direction direction) {
|
private String getHarbleStructure(HMessage.Direction direction) {
|
||||||
if (isCorrupted()) return "";
|
|
||||||
|
|
||||||
HarbleAPI.HarbleMessage msg;
|
HarbleAPI.HarbleMessage msg;
|
||||||
if (HarbleAPIFetcher.HARBLEAPI != null &&
|
if (HarbleAPIFetcher.HARBLEAPI != null &&
|
||||||
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
|
((msg = HarbleAPIFetcher.HARBLEAPI.getHarbleMessageFromHeaderId(direction, headerId())) != null)) {
|
||||||
if (msg.getStructure() != null) {
|
if (msg.getStructure() != null && structureEquals(msg.getStructure())) {
|
||||||
return PacketStringUtils.toExpressionFromGivenStructure(this, msg.getStructure());
|
return msg.getStructure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return toExpression();
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toExpression(HMessage.Direction direction) {
|
||||||
|
if (isCorrupted()) return "";
|
||||||
|
|
||||||
|
String structure = getHarbleStructure(direction);
|
||||||
|
if (structure != null) {
|
||||||
|
return PacketStringUtils.toExpressionFromGivenStructure(this, structure);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PacketStringUtils.predictedExpression(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns "" if not found or not sure enough
|
* returns "" if not found or not sure enough
|
||||||
* dont hate on the coding quality in this function, its pretty effective.
|
|
||||||
*/
|
*/
|
||||||
public String toExpression() {
|
public String toExpression() {
|
||||||
if (isCorrupted()) return "";
|
if (isCorrupted()) return "";
|
||||||
|
|
||||||
|
String structure1 = getHarbleStructure(HMessage.Direction.TOCLIENT);
|
||||||
|
String structure2 = getHarbleStructure(HMessage.Direction.TOSERVER);
|
||||||
|
if (structure1 != null && structure2 == null) {
|
||||||
|
return PacketStringUtils.toExpressionFromGivenStructure(this, structure1);
|
||||||
|
}
|
||||||
|
else if (structure1 == null && structure2 != null) {
|
||||||
|
return PacketStringUtils.toExpressionFromGivenStructure(this, structure2);
|
||||||
|
}
|
||||||
|
|
||||||
return PacketStringUtils.predictedExpression(this);
|
return PacketStringUtils.predictedExpression(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,7 +607,7 @@ public class HPacket implements StringifyAble {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
HPacket packet = new HPacket("{l}{u:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}{d:1.4}");
|
HPacket packet = new HPacket("{l}{h:4564}{i:3}{i:0}{s:\"hi\"}{i:0}{i:1}{s:\"how\"}{i:3}{b:1}{b:2}{b:3}{i:2}{s:\"r u\"}{i:1}{b:120}{i:2}{b:true}{d:1.4}");
|
||||||
|
|
||||||
String str = PacketStringUtils.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
String str = PacketStringUtils.toExpressionFromGivenStructure(packet, "i(isi(b))iBd");
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package gearth.protocol.connection;
|
||||||
|
|
||||||
|
public enum HClient {
|
||||||
|
UNITY,
|
||||||
|
FLASH
|
||||||
|
}
|
@ -1,11 +1,13 @@
|
|||||||
package gearth.protocol.connection;
|
package gearth.protocol.connection;
|
||||||
|
|
||||||
import gearth.protocol.packethandler.IncomingPacketHandler;
|
import gearth.protocol.packethandler.PacketHandler;
|
||||||
import gearth.protocol.packethandler.OutgoingPacketHandler;
|
|
||||||
|
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
|
|
||||||
public class HProxy {
|
public class HProxy {
|
||||||
|
|
||||||
|
private final HClient hClient;
|
||||||
|
|
||||||
private volatile String input_domain; //string representation of the domain to intercept
|
private volatile String input_domain; //string representation of the domain to intercept
|
||||||
private volatile String actual_domain; //dns resolved domain (ignoring hosts file)
|
private volatile String actual_domain; //dns resolved domain (ignoring hosts file)
|
||||||
private volatile int actual_port; //port of the server
|
private volatile int actual_port; //port of the server
|
||||||
@ -15,13 +17,14 @@ public class HProxy {
|
|||||||
|
|
||||||
private volatile ServerSocket proxy_server = null; //listener for the client
|
private volatile ServerSocket proxy_server = null; //listener for the client
|
||||||
|
|
||||||
private volatile IncomingPacketHandler inHandler = null; //connection with client (only initialized when verified habbo connection)
|
private volatile PacketHandler inHandler = null; //connection with client (only initialized when verified habbo connection)
|
||||||
private volatile OutgoingPacketHandler outHandler = null; //connection with server (only initialized when verified habbo connection)
|
private volatile PacketHandler outHandler = null; //connection with server (only initialized when verified habbo connection)
|
||||||
|
|
||||||
private volatile String hotelVersion = "";
|
private volatile String hotelVersion = "";
|
||||||
private volatile AsyncPacketSender asyncPacketSender = null;
|
private volatile AsyncPacketSender asyncPacketSender = null;
|
||||||
|
|
||||||
public HProxy(String input_domain, String actual_domain, int actual_port, int intercept_port, String intercept_host) {
|
public HProxy(HClient hClient, String input_domain, String actual_domain, int actual_port, int intercept_port, String intercept_host) {
|
||||||
|
this.hClient = hClient;
|
||||||
this.input_domain = input_domain;
|
this.input_domain = input_domain;
|
||||||
this.actual_domain = actual_domain;
|
this.actual_domain = actual_domain;
|
||||||
this.actual_port = actual_port;
|
this.actual_port = actual_port;
|
||||||
@ -33,7 +36,7 @@ public class HProxy {
|
|||||||
this.proxy_server = socket;
|
this.proxy_server = socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyProxy(IncomingPacketHandler incomingHandler, OutgoingPacketHandler outgoingHandler, String hotelVersion) {
|
public void verifyProxy(PacketHandler incomingHandler, PacketHandler outgoingHandler, String hotelVersion) {
|
||||||
this.inHandler = incomingHandler;
|
this.inHandler = incomingHandler;
|
||||||
this.outHandler = outgoingHandler;
|
this.outHandler = outgoingHandler;
|
||||||
this.hotelVersion = hotelVersion;
|
this.hotelVersion = hotelVersion;
|
||||||
@ -64,11 +67,11 @@ public class HProxy {
|
|||||||
return intercept_host;
|
return intercept_host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IncomingPacketHandler getInHandler() {
|
public PacketHandler getInHandler() {
|
||||||
return inHandler;
|
return inHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutgoingPacketHandler getOutHandler() {
|
public PacketHandler getOutHandler() {
|
||||||
return outHandler;
|
return outHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,4 +82,8 @@ public class HProxy {
|
|||||||
public AsyncPacketSender getAsyncPacketSender() {
|
public AsyncPacketSender getAsyncPacketSender() {
|
||||||
return asyncPacketSender;
|
return asyncPacketSender;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HClient gethClient() {
|
||||||
|
return hClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,129 +1,10 @@
|
|||||||
package gearth.protocol.connection.proxy;
|
package gearth.protocol.connection.proxy;
|
||||||
|
|
||||||
import gearth.protocol.HConnection;
|
|
||||||
import gearth.protocol.connection.HProxy;
|
|
||||||
import gearth.protocol.connection.HProxySetter;
|
|
||||||
import gearth.protocol.connection.HState;
|
|
||||||
import gearth.protocol.connection.HStateSetter;
|
|
||||||
import gearth.protocol.memory.Rc4Obtainer;
|
|
||||||
import gearth.protocol.packethandler.IncomingPacketHandler;
|
|
||||||
import gearth.protocol.packethandler.OutgoingPacketHandler;
|
|
||||||
import gearth.protocol.packethandler.PacketHandler;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.scene.control.Alert;
|
|
||||||
import javafx.scene.control.ButtonType;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Socket;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
|
|
||||||
public abstract class ProxyProvider {
|
public interface ProxyProvider {
|
||||||
|
|
||||||
protected final HProxySetter proxySetter;
|
void start() throws IOException;
|
||||||
protected final HStateSetter stateSetter;
|
void abort();
|
||||||
protected final HConnection hConnection;
|
|
||||||
|
|
||||||
private Semaphore abortSemaphore = null;
|
|
||||||
|
|
||||||
public ProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection){
|
|
||||||
this.proxySetter = proxySetter;
|
|
||||||
this.stateSetter = stateSetter;
|
|
||||||
this.hConnection = hConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void startProxyThread(Socket client, Socket server, HProxy proxy) throws IOException, InterruptedException {
|
|
||||||
final boolean[] datastream = new boolean[1];
|
|
||||||
server.setTcpNoDelay(true);
|
|
||||||
client.setTcpNoDelay(true);
|
|
||||||
|
|
||||||
client.setSoTimeout(0);
|
|
||||||
server.setSoTimeout(0);
|
|
||||||
|
|
||||||
if (HConnection.DEBUG) System.out.println(server.getLocalAddress().getHostAddress() + ": " + server.getLocalPort());
|
|
||||||
Rc4Obtainer rc4Obtainer = new Rc4Obtainer(hConnection);
|
|
||||||
|
|
||||||
OutgoingPacketHandler outgoingHandler = new OutgoingPacketHandler(server.getOutputStream(), hConnection.getTrafficObservables(), hConnection.getExtensionHandler());
|
|
||||||
IncomingPacketHandler incomingHandler = new IncomingPacketHandler(client.getOutputStream(), hConnection.getTrafficObservables(), outgoingHandler, hConnection.getExtensionHandler());
|
|
||||||
rc4Obtainer.setPacketHandlers(outgoingHandler, incomingHandler);
|
|
||||||
|
|
||||||
Semaphore abort = new Semaphore(0);
|
|
||||||
|
|
||||||
outgoingHandler.addOnDatastreamConfirmedListener(hotelVersion -> {
|
|
||||||
incomingHandler.setAsDataStream();
|
|
||||||
proxy.verifyProxy(incomingHandler, outgoingHandler, hotelVersion);
|
|
||||||
proxySetter.setProxy(proxy);
|
|
||||||
datastream[0] = true;
|
|
||||||
abortSemaphore = abort;
|
|
||||||
onConnect();
|
|
||||||
});
|
|
||||||
|
|
||||||
handleInputStream(client, outgoingHandler, abort);
|
|
||||||
handleInputStream(server, incomingHandler, abort);
|
|
||||||
|
|
||||||
// abort can be acquired as soon as one of the sockets is closed
|
|
||||||
abort.acquire();
|
|
||||||
try {
|
|
||||||
if (!server.isClosed()) server.close();
|
|
||||||
if (!client.isClosed()) client.close();
|
|
||||||
if (HConnection.DEBUG) System.out.println("STOP");
|
|
||||||
if (datastream[0]) {
|
|
||||||
onConnectEnd();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleInputStream(Socket socket, PacketHandler packetHandler, Semaphore abort) {
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
int readLength;
|
|
||||||
byte[] buffer = new byte[10000];
|
|
||||||
while (!socket.isClosed() &&
|
|
||||||
(hConnection.getState() == HState.WAITING_FOR_CLIENT || hConnection.getState() == HState.CONNECTED) &&
|
|
||||||
(readLength = socket.getInputStream().read(buffer)) != -1) {
|
|
||||||
packetHandler.act(Arrays.copyOf(buffer, readLength));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException ignore) {
|
|
||||||
// System.err.println(packetHandler instanceof IncomingPacketHandler ? "incoming" : "outgoing");
|
|
||||||
// ignore.printStackTrace();
|
|
||||||
} finally {
|
|
||||||
abort.release();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public abstract void start() throws IOException;
|
|
||||||
public void abort() {
|
|
||||||
if (abortSemaphore != null) {
|
|
||||||
abortSemaphore.release();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
stateSetter.setState(HState.NOT_CONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onConnect() {
|
|
||||||
stateSetter.setState(HState.CONNECTED);
|
|
||||||
}
|
|
||||||
protected void onConnectEnd() {
|
|
||||||
proxySetter.setProxy(null);
|
|
||||||
abortSemaphore = null;
|
|
||||||
stateSetter.setState(HState.NOT_CONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void showInvalidConnectionError() {
|
|
||||||
Platform.runLater(() -> {
|
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR, "You entered invalid connection information, G-Earth could not connect", ButtonType.OK);
|
|
||||||
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
|
||||||
alert.setResizable(false);
|
|
||||||
alert.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@ import gearth.misc.OSValidator;
|
|||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HProxySetter;
|
import gearth.protocol.connection.HProxySetter;
|
||||||
import gearth.protocol.connection.HStateSetter;
|
import gearth.protocol.connection.HStateSetter;
|
||||||
import gearth.protocol.connection.proxy.unix.LinuxRawIpProxyProvider;
|
import gearth.protocol.connection.proxy.flash.NormalFlashProxyProvider;
|
||||||
import gearth.protocol.connection.proxy.windows.WindowsRawIpProxyProvider;
|
import gearth.protocol.connection.proxy.flash.FlashProxyProvider;
|
||||||
|
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
|
||||||
|
import gearth.protocol.connection.proxy.flash.windows.WindowsRawIpFlashProxyProvider;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
@ -67,7 +69,7 @@ public class ProxyProviderFactory {
|
|||||||
|
|
||||||
// checks if host is a raw IP instead of a domain
|
// checks if host is a raw IP instead of a domain
|
||||||
// TODO support ipv6 (not only here, also in IPmapper)
|
// TODO support ipv6 (not only here, also in IPmapper)
|
||||||
static boolean hostIsIpAddress(String host){
|
public static boolean hostIsIpAddress(String host){
|
||||||
for (char c : host.toCharArray()) {
|
for (char c : host.toCharArray()) {
|
||||||
if (c != '.' && (c < '0' || c > '9')) {
|
if (c != '.' && (c < '0' || c > '9')) {
|
||||||
return false;
|
return false;
|
||||||
@ -79,7 +81,6 @@ public class ProxyProviderFactory {
|
|||||||
public ProxyProvider provide() {
|
public ProxyProvider provide() {
|
||||||
return provide(autoDetectHosts);
|
return provide(autoDetectHosts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProxyProvider provide(String domain, int port) {
|
public ProxyProvider provide(String domain, int port) {
|
||||||
List<Object> additionalCachedHotels = Cacher.getList(HOTELS_CACHE_KEY);
|
List<Object> additionalCachedHotels = Cacher.getList(HOTELS_CACHE_KEY);
|
||||||
if (additionalCachedHotels == null) {
|
if (additionalCachedHotels == null) {
|
||||||
@ -92,12 +93,12 @@ public class ProxyProviderFactory {
|
|||||||
|
|
||||||
if (hostIsIpAddress(domain)) {
|
if (hostIsIpAddress(domain)) {
|
||||||
if (OSValidator.isWindows()) {
|
if (OSValidator.isWindows()) {
|
||||||
if (WindowsRawIpProxyProvider.isNoneConnected(domain) &&
|
if (WindowsRawIpFlashProxyProvider.isNoneConnected(domain) &&
|
||||||
(!socksConfig.useSocks() || socksConfig.onlyUseIfNeeded()) ) {
|
(!socksConfig.useSocks() || socksConfig.onlyUseIfNeeded()) ) {
|
||||||
return new WindowsRawIpProxyProvider(proxySetter, stateSetter, hConnection, domain, port, false);
|
return new WindowsRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, false);
|
||||||
}
|
}
|
||||||
else if (socksConfig.useSocks()) {
|
else if (socksConfig.useSocks()) {
|
||||||
return new WindowsRawIpProxyProvider(proxySetter, stateSetter, hConnection, domain, port, true);
|
return new WindowsRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
@ -112,7 +113,7 @@ public class ProxyProviderFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else if (OSValidator.isUnix() || OSValidator.isMac()) {
|
else if (OSValidator.isUnix() || OSValidator.isMac()) {
|
||||||
return new LinuxRawIpProxyProvider(proxySetter, stateSetter, hConnection, domain, port, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
|
return new LinuxRawIpFlashProxyProvider(proxySetter, stateSetter, hConnection, domain, port, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -123,9 +124,8 @@ public class ProxyProviderFactory {
|
|||||||
return provide(potentialHost);
|
return provide(potentialHost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProxyProvider provide(List<String> potentialHosts) {
|
private ProxyProvider provide(List<String> potentialHosts) {
|
||||||
return new NormalProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
|
return new NormalFlashProxyProvider(proxySetter, stateSetter, hConnection, potentialHosts, socksConfig.useSocks() && !socksConfig.onlyUseIfNeeded());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setSocksConfig(SocksConfiguration configuration) {
|
public static void setSocksConfig(SocksConfiguration configuration) {
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
package gearth.protocol.connection.proxy.flash;
|
||||||
|
|
||||||
|
import gearth.protocol.HConnection;
|
||||||
|
import gearth.protocol.connection.HProxy;
|
||||||
|
import gearth.protocol.connection.HProxySetter;
|
||||||
|
import gearth.protocol.connection.HState;
|
||||||
|
import gearth.protocol.connection.HStateSetter;
|
||||||
|
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||||
|
import gearth.protocol.memory.Rc4Obtainer;
|
||||||
|
import gearth.protocol.packethandler.flash.IncomingFlashPacketHandler;
|
||||||
|
import gearth.protocol.packethandler.flash.OutgoingFlashPacketHandler;
|
||||||
|
import gearth.protocol.packethandler.flash.FlashPacketHandler;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
public abstract class FlashProxyProvider implements ProxyProvider {
|
||||||
|
|
||||||
|
protected final HProxySetter proxySetter;
|
||||||
|
protected final HStateSetter stateSetter;
|
||||||
|
protected final HConnection hConnection;
|
||||||
|
|
||||||
|
private Semaphore abortSemaphore = null;
|
||||||
|
|
||||||
|
public FlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection){
|
||||||
|
this.proxySetter = proxySetter;
|
||||||
|
this.stateSetter = stateSetter;
|
||||||
|
this.hConnection = hConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startProxyThread(Socket client, Socket server, HProxy proxy) throws IOException, InterruptedException {
|
||||||
|
final boolean[] datastream = new boolean[1];
|
||||||
|
server.setTcpNoDelay(true);
|
||||||
|
client.setTcpNoDelay(true);
|
||||||
|
|
||||||
|
client.setSoTimeout(0);
|
||||||
|
server.setSoTimeout(0);
|
||||||
|
|
||||||
|
if (HConnection.DEBUG) System.out.println(server.getLocalAddress().getHostAddress() + ": " + server.getLocalPort());
|
||||||
|
Rc4Obtainer rc4Obtainer = new Rc4Obtainer(hConnection);
|
||||||
|
|
||||||
|
OutgoingFlashPacketHandler outgoingHandler = new OutgoingFlashPacketHandler(server.getOutputStream(), hConnection.getTrafficObservables(), hConnection.getExtensionHandler());
|
||||||
|
IncomingFlashPacketHandler incomingHandler = new IncomingFlashPacketHandler(client.getOutputStream(), hConnection.getTrafficObservables(), outgoingHandler, hConnection.getExtensionHandler());
|
||||||
|
rc4Obtainer.setFlashPacketHandlers(outgoingHandler, incomingHandler);
|
||||||
|
|
||||||
|
Semaphore abort = new Semaphore(0);
|
||||||
|
|
||||||
|
outgoingHandler.addOnDatastreamConfirmedListener(hotelVersion -> {
|
||||||
|
incomingHandler.setAsDataStream();
|
||||||
|
proxy.verifyProxy(incomingHandler, outgoingHandler, hotelVersion);
|
||||||
|
proxySetter.setProxy(proxy);
|
||||||
|
datastream[0] = true;
|
||||||
|
abortSemaphore = abort;
|
||||||
|
onConnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
handleInputStream(client, outgoingHandler, abort);
|
||||||
|
handleInputStream(server, incomingHandler, abort);
|
||||||
|
|
||||||
|
// abort can be acquired as soon as one of the sockets is closed
|
||||||
|
abort.acquire();
|
||||||
|
try {
|
||||||
|
if (!server.isClosed()) server.close();
|
||||||
|
if (!client.isClosed()) client.close();
|
||||||
|
if (HConnection.DEBUG) System.out.println("STOP");
|
||||||
|
if (datastream[0]) {
|
||||||
|
onConnectEnd();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleInputStream(Socket socket, FlashPacketHandler flashPacketHandler, Semaphore abort) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
int readLength;
|
||||||
|
byte[] buffer = new byte[10000];
|
||||||
|
while (!socket.isClosed() &&
|
||||||
|
(hConnection.getState() == HState.WAITING_FOR_CLIENT || hConnection.getState() == HState.CONNECTED) &&
|
||||||
|
(readLength = socket.getInputStream().read(buffer)) != -1) {
|
||||||
|
flashPacketHandler.act(Arrays.copyOf(buffer, readLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ignore) {
|
||||||
|
// System.err.println(packetHandler instanceof IncomingPacketHandler ? "incoming" : "outgoing");
|
||||||
|
// ignore.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
abort.release();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public abstract void start() throws IOException;
|
||||||
|
public void abort() {
|
||||||
|
if (abortSemaphore != null) {
|
||||||
|
abortSemaphore.release();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stateSetter.setState(HState.NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onConnect() {
|
||||||
|
stateSetter.setState(HState.CONNECTED);
|
||||||
|
}
|
||||||
|
protected void onConnectEnd() {
|
||||||
|
proxySetter.setProxy(null);
|
||||||
|
abortSemaphore = null;
|
||||||
|
stateSetter.setState(HState.NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showInvalidConnectionError() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR, "You entered invalid connection information, G-Earth could not connect", ButtonType.OK);
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.setResizable(false);
|
||||||
|
alert.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,21 +1,19 @@
|
|||||||
package gearth.protocol.connection.proxy;
|
package gearth.protocol.connection.proxy.flash;
|
||||||
|
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HProxy;
|
import gearth.protocol.connection.*;
|
||||||
import gearth.protocol.connection.HProxySetter;
|
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||||
import gearth.protocol.connection.HState;
|
import gearth.protocol.connection.proxy.SocksConfiguration;
|
||||||
import gearth.protocol.connection.HStateSetter;
|
|
||||||
import gearth.protocol.hostreplacer.hostsfile.HostReplacer;
|
import gearth.protocol.hostreplacer.hostsfile.HostReplacer;
|
||||||
import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory;
|
import gearth.protocol.hostreplacer.hostsfile.HostReplacerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class NormalProxyProvider extends ProxyProvider {
|
public class NormalFlashProxyProvider extends FlashProxyProvider {
|
||||||
|
|
||||||
private List<String> potentialHosts;
|
private List<String> potentialHosts;
|
||||||
|
|
||||||
@ -29,7 +27,7 @@ public class NormalProxyProvider extends ProxyProvider {
|
|||||||
private boolean useSocks;
|
private boolean useSocks;
|
||||||
|
|
||||||
|
|
||||||
public NormalProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List<String> potentialHosts, boolean useSocks) {
|
public NormalFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, List<String> potentialHosts, boolean useSocks) {
|
||||||
super(proxySetter, stateSetter, hConnection);
|
super(proxySetter, stateSetter, hConnection);
|
||||||
this.potentialHosts = potentialHosts;
|
this.potentialHosts = potentialHosts;
|
||||||
this.useSocks = useSocks;
|
this.useSocks = useSocks;
|
||||||
@ -72,7 +70,7 @@ public class NormalProxyProvider extends ProxyProvider {
|
|||||||
|
|
||||||
int intercept_port = port;
|
int intercept_port = port;
|
||||||
String intercept_host = "127.0." + (c / 254) + "." + (1 + c % 254);
|
String intercept_host = "127.0." + (c / 254) + "." + (1 + c % 254);
|
||||||
potentialProxies.add(new HProxy(input_dom, actual_dom, port, intercept_port, intercept_host));
|
potentialProxies.add(new HProxy(HClient.FLASH, input_dom, actual_dom, port, intercept_port, intercept_host));
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,26 +1,19 @@
|
|||||||
package gearth.protocol.connection.proxy.unix;
|
package gearth.protocol.connection.proxy.flash.unix;
|
||||||
|
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HProxy;
|
import gearth.protocol.connection.*;
|
||||||
import gearth.protocol.connection.HProxySetter;
|
import gearth.protocol.connection.proxy.flash.FlashProxyProvider;
|
||||||
import gearth.protocol.connection.HState;
|
|
||||||
import gearth.protocol.connection.HStateSetter;
|
|
||||||
import gearth.protocol.connection.proxy.ProxyProvider;
|
|
||||||
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||||
import gearth.protocol.connection.proxy.SocksConfiguration;
|
import gearth.protocol.connection.proxy.SocksConfiguration;
|
||||||
import gearth.protocol.hostreplacer.ipmapping.IpMapper;
|
import gearth.protocol.hostreplacer.ipmapping.IpMapper;
|
||||||
import gearth.protocol.hostreplacer.ipmapping.IpMapperFactory;
|
import gearth.protocol.hostreplacer.ipmapping.IpMapperFactory;
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.scene.control.Alert;
|
|
||||||
import javafx.scene.control.ButtonType;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
public class LinuxRawIpProxyProvider extends ProxyProvider {
|
public class LinuxRawIpFlashProxyProvider extends FlashProxyProvider {
|
||||||
|
|
||||||
private volatile String input_host;
|
private volatile String input_host;
|
||||||
private volatile int input_port;
|
private volatile int input_port;
|
||||||
@ -30,7 +23,7 @@ public class LinuxRawIpProxyProvider extends ProxyProvider {
|
|||||||
|
|
||||||
private boolean useSocks;
|
private boolean useSocks;
|
||||||
|
|
||||||
public LinuxRawIpProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, String input_host, int input_port, boolean useSocks) {
|
public LinuxRawIpFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, String input_host, int input_port, boolean useSocks) {
|
||||||
super(proxySetter, stateSetter, hConnection);
|
super(proxySetter, stateSetter, hConnection);
|
||||||
this.input_host = input_host;
|
this.input_host = input_host;
|
||||||
this.input_port = input_port;
|
this.input_port = input_port;
|
||||||
@ -50,7 +43,7 @@ public class LinuxRawIpProxyProvider extends ProxyProvider {
|
|||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
stateSetter.setState(HState.PREPARING);
|
stateSetter.setState(HState.PREPARING);
|
||||||
proxy = new HProxy(input_host, input_host, input_port, input_port, "0.0.0.0");
|
proxy = new HProxy(HClient.FLASH, input_host, input_host, input_port, input_port, "0.0.0.0");
|
||||||
|
|
||||||
maybeRemoveMapping();
|
maybeRemoveMapping();
|
||||||
|
|
@ -1,35 +1,23 @@
|
|||||||
package gearth.protocol.connection.proxy.windows;
|
package gearth.protocol.connection.proxy.flash.windows;
|
||||||
|
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HProxy;
|
|
||||||
import gearth.protocol.connection.HProxySetter;
|
import gearth.protocol.connection.HProxySetter;
|
||||||
import gearth.protocol.connection.HState;
|
import gearth.protocol.connection.HState;
|
||||||
import gearth.protocol.connection.HStateSetter;
|
import gearth.protocol.connection.HStateSetter;
|
||||||
import gearth.protocol.connection.proxy.ProxyProvider;
|
import gearth.protocol.connection.proxy.flash.unix.LinuxRawIpFlashProxyProvider;
|
||||||
import gearth.protocol.connection.proxy.unix.LinuxRawIpProxyProvider;
|
|
||||||
import gearth.protocol.hostreplacer.ipmapping.IpMapper;
|
|
||||||
import gearth.protocol.hostreplacer.ipmapping.IpMapperFactory;
|
|
||||||
import javafx.application.Platform;
|
|
||||||
import javafx.scene.control.Alert;
|
|
||||||
import javafx.scene.control.ButtonType;
|
|
||||||
import javafx.scene.layout.Region;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.*;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
// windows raw ip proxy provider extends the Linux one with the exception that it does not want to close
|
// windows raw ip proxy provider extends the Linux one with the exception that it does not want to close
|
||||||
// the IP redirect on connect
|
// the IP redirect on connect
|
||||||
public class WindowsRawIpProxyProvider extends LinuxRawIpProxyProvider {
|
public class WindowsRawIpFlashProxyProvider extends LinuxRawIpFlashProxyProvider {
|
||||||
|
|
||||||
private boolean hasMapped = false;
|
private boolean hasMapped = false;
|
||||||
|
|
||||||
public WindowsRawIpProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, String input_host, int input_port, boolean useSocks) {
|
public WindowsRawIpFlashProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, String input_host, int input_port, boolean useSocks) {
|
||||||
super(proxySetter, stateSetter, hConnection, input_host, input_port, useSocks);
|
super(proxySetter, stateSetter, hConnection, input_host, input_port, useSocks);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
package gearth.protocol.connection.proxy.unity;
|
||||||
|
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.annotations.JsrParamIdText;
|
||||||
|
|
||||||
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
// tells which port the packethandler is running on
|
||||||
|
// server gets closed afterwards
|
||||||
|
@ServerEndpoint(value = "/portrequest")
|
||||||
|
public class PortRequester {
|
||||||
|
|
||||||
|
private final int packetHandlerPort;
|
||||||
|
|
||||||
|
public PortRequester(int port) {
|
||||||
|
this.packetHandlerPort = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session) throws IOException {
|
||||||
|
session.getBasicRemote().sendText("port " + packetHandlerPort);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package gearth.protocol.connection.proxy.unity;
|
||||||
|
|
||||||
|
import javax.websocket.server.ServerEndpointConfig;
|
||||||
|
|
||||||
|
public class PortRequesterConfig extends ServerEndpointConfig.Configurator {
|
||||||
|
|
||||||
|
private final int packetHandlerPort;
|
||||||
|
|
||||||
|
public PortRequesterConfig(int packetHandlerPort) {
|
||||||
|
this.packetHandlerPort = packetHandlerPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
|
||||||
|
return (T)new PortRequester(packetHandlerPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package gearth.protocol.connection.proxy.unity;
|
||||||
|
|
||||||
|
import gearth.protocol.HConnection;
|
||||||
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
import gearth.protocol.connection.*;
|
||||||
|
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||||
|
import gearth.protocol.packethandler.unity.UnityPacketHandler;
|
||||||
|
|
||||||
|
import javax.websocket.*;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
@ServerEndpoint(value = "/packethandler")
|
||||||
|
public class UnityCommunicator {
|
||||||
|
|
||||||
|
private final HProxySetter proxySetter;
|
||||||
|
private final HStateSetter stateSetter;
|
||||||
|
private final HConnection hConnection;
|
||||||
|
private final ProxyProvider proxyProvider;
|
||||||
|
|
||||||
|
private HProxy hProxy = null;
|
||||||
|
private String allowedSession = null;
|
||||||
|
private String revision = null;
|
||||||
|
|
||||||
|
public UnityCommunicator(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, ProxyProvider proxyProvider) {
|
||||||
|
this.proxySetter = proxySetter;
|
||||||
|
this.stateSetter = stateSetter;
|
||||||
|
this.hConnection = hConnection;
|
||||||
|
this.proxyProvider = proxyProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session) throws IOException {
|
||||||
|
session.setMaxBinaryMessageBufferSize(1024 * 1024 * 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnMessage
|
||||||
|
public void onMessage(byte[] b, Session session) throws IOException {
|
||||||
|
if (allowedSession != null && !session.getId().equals(allowedSession)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (revision == null) {
|
||||||
|
revision = new String(b, StandardCharsets.ISO_8859_1);
|
||||||
|
allowedSession = session.getId();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
byte[] packet = Arrays.copyOfRange(b, 1, b.length);
|
||||||
|
|
||||||
|
if (hProxy == null && b[0] == 1) {
|
||||||
|
HPacket maybe = new HPacket(packet);
|
||||||
|
if (maybe.getBytesLength() > 6 && maybe.headerId() == 4000) {
|
||||||
|
hProxy = new HProxy(HClient.UNITY, "", "", -1, -1, "");
|
||||||
|
hProxy.verifyProxy(
|
||||||
|
new UnityPacketHandler(hConnection.getExtensionHandler(), hConnection.getTrafficObservables(), session, HMessage.Direction.TOCLIENT),
|
||||||
|
new UnityPacketHandler(hConnection.getExtensionHandler(), hConnection.getTrafficObservables(), session, HMessage.Direction.TOSERVER),
|
||||||
|
revision
|
||||||
|
);
|
||||||
|
proxySetter.setProxy(hProxy);
|
||||||
|
stateSetter.setState(HState.CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hProxy != null && b[0] == 0) {
|
||||||
|
hProxy.getInHandler().act(packet);
|
||||||
|
}
|
||||||
|
else if (hProxy != null && b[0] == 1) {
|
||||||
|
hProxy.getOutHandler().act(packet);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proxyProvider.abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClose
|
||||||
|
public void onClose(Session session) throws IOException {
|
||||||
|
proxyProvider.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable throwable) {
|
||||||
|
proxyProvider.abort();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package gearth.protocol.connection.proxy.unity;
|
||||||
|
|
||||||
|
import gearth.protocol.HConnection;
|
||||||
|
import gearth.protocol.connection.HProxySetter;
|
||||||
|
import gearth.protocol.connection.HStateSetter;
|
||||||
|
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||||
|
|
||||||
|
import javax.websocket.server.ServerEndpointConfig;
|
||||||
|
|
||||||
|
public class UnityCommunicatorConfig extends ServerEndpointConfig.Configurator {
|
||||||
|
private final HProxySetter proxySetter;
|
||||||
|
private final HStateSetter stateSetter;
|
||||||
|
private final HConnection hConnection;
|
||||||
|
private final ProxyProvider proxyProvider;
|
||||||
|
|
||||||
|
public UnityCommunicatorConfig(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection, ProxyProvider proxyProvider) {
|
||||||
|
this.proxySetter = proxySetter;
|
||||||
|
this.stateSetter = stateSetter;
|
||||||
|
this.hConnection = hConnection;
|
||||||
|
this.proxyProvider = proxyProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <T> T getEndpointInstance(Class<T> clazz) throws InstantiationException {
|
||||||
|
return (T)new UnityCommunicator(proxySetter, stateSetter, hConnection, proxyProvider);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
package gearth.protocol.connection.proxy.unity;
|
||||||
|
|
||||||
|
import gearth.protocol.HConnection;
|
||||||
|
import gearth.protocol.StateChangeListener;
|
||||||
|
import gearth.protocol.connection.HProxySetter;
|
||||||
|
import gearth.protocol.connection.HState;
|
||||||
|
import gearth.protocol.connection.HStateSetter;
|
||||||
|
import gearth.protocol.connection.proxy.ProxyProvider;
|
||||||
|
import gearth.services.unity_tools.GUnityFileServer;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.handler.HandlerList;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||||
|
|
||||||
|
import javax.websocket.server.ServerContainer;
|
||||||
|
import javax.websocket.server.ServerEndpointConfig;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static gearth.services.unity_tools.GUnityFileServer.FILESERVER_PORT;
|
||||||
|
|
||||||
|
public class UnityProxyProvider implements ProxyProvider {
|
||||||
|
|
||||||
|
private final HProxySetter proxySetter;
|
||||||
|
private final HStateSetter stateSetter;
|
||||||
|
private final HConnection hConnection;
|
||||||
|
|
||||||
|
private Server packetHandlerServer = null;
|
||||||
|
|
||||||
|
public UnityProxyProvider(HProxySetter proxySetter, HStateSetter stateSetter, HConnection hConnection) {
|
||||||
|
this.proxySetter = proxySetter;
|
||||||
|
this.stateSetter = stateSetter;
|
||||||
|
this.hConnection = hConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() throws IOException {
|
||||||
|
// https://happyhyppo.ro/2016/03/21/minimal-websockets-communication-with-javajetty-and-angularjs/
|
||||||
|
|
||||||
|
try {
|
||||||
|
int port = 9040;
|
||||||
|
boolean fail = true;
|
||||||
|
while (fail && port < 9100) {
|
||||||
|
try {
|
||||||
|
packetHandlerServer = new Server(port);
|
||||||
|
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
|
context.setContextPath("/ws");
|
||||||
|
|
||||||
|
HandlerList handlers = new HandlerList();
|
||||||
|
handlers.setHandlers(new Handler[] { context });
|
||||||
|
|
||||||
|
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context);
|
||||||
|
wscontainer.addEndpoint(ServerEndpointConfig.Builder
|
||||||
|
.create(UnityCommunicator.class, "/packethandler") // the endpoint url
|
||||||
|
.configurator(new UnityCommunicatorConfig(proxySetter, stateSetter, hConnection, this))
|
||||||
|
.build());
|
||||||
|
packetHandlerServer.setHandler(handlers);
|
||||||
|
packetHandlerServer.start();
|
||||||
|
fail = false;
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
port++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
startPortRequestServer(port);
|
||||||
|
startUnityFileServer();
|
||||||
|
stateSetter.setState(HState.WAITING_FOR_CLIENT);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
stateSetter.setState(HState.NOT_CONNECTED);
|
||||||
|
try {
|
||||||
|
packetHandlerServer.stop();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void abort() {
|
||||||
|
if (packetHandlerServer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Server abortThis = packetHandlerServer;
|
||||||
|
stateSetter.setState(HState.ABORTING);
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
abortThis.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
stateSetter.setState(HState.NOT_CONNECTED);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
packetHandlerServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startUnityFileServer() throws Exception {
|
||||||
|
Server server = new Server(FILESERVER_PORT);
|
||||||
|
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
|
context.setContextPath("/");
|
||||||
|
|
||||||
|
context.addServlet(new ServletHolder(new GUnityFileServer()), "/*");
|
||||||
|
|
||||||
|
HandlerList handlers = new HandlerList();
|
||||||
|
handlers.setHandlers(new Handler[] { context });
|
||||||
|
server.setHandler(handlers);
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
StateChangeListener fileServerCloser = new StateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(HState oldState, HState newState) {
|
||||||
|
if (oldState == HState.WAITING_FOR_CLIENT || newState == HState.NOT_CONNECTED) {
|
||||||
|
hConnection.getStateObservable().removeListener(this);
|
||||||
|
try {
|
||||||
|
server.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hConnection.getStateObservable().addListener(fileServerCloser);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPortRequestServer(int packetHandlerPort) throws Exception {
|
||||||
|
Server portRequestServer = new Server(9039);
|
||||||
|
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
|
context.setContextPath("/ws");
|
||||||
|
|
||||||
|
HandlerList handlers = new HandlerList();
|
||||||
|
handlers.setHandlers(new Handler[] { context });
|
||||||
|
portRequestServer.setHandler(handlers);
|
||||||
|
|
||||||
|
ServerContainer wscontainer = WebSocketServerContainerInitializer.configureContext(context);
|
||||||
|
wscontainer.addEndpoint(ServerEndpointConfig.Builder
|
||||||
|
.create(PortRequester.class, "/portrequest") // the endpoint url
|
||||||
|
.configurator(new PortRequesterConfig(packetHandlerPort))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
portRequestServer.start();
|
||||||
|
|
||||||
|
StateChangeListener portRequesterCloser = new StateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(HState oldState, HState newState) {
|
||||||
|
if (oldState == HState.WAITING_FOR_CLIENT || newState == HState.NOT_CONNECTED) {
|
||||||
|
hConnection.getStateObservable().removeListener(this);
|
||||||
|
try {
|
||||||
|
portRequestServer.stop();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
hConnection.getStateObservable().addListener(portRequesterCloser);
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,9 @@ import gearth.protocol.HPacket;
|
|||||||
import gearth.protocol.crypto.RC4;
|
import gearth.protocol.crypto.RC4;
|
||||||
import gearth.protocol.memory.habboclient.HabboClient;
|
import gearth.protocol.memory.habboclient.HabboClient;
|
||||||
import gearth.protocol.memory.habboclient.HabboClientFactory;
|
import gearth.protocol.memory.habboclient.HabboClientFactory;
|
||||||
import gearth.protocol.packethandler.*;
|
import gearth.protocol.packethandler.flash.BufferChangeListener;
|
||||||
|
import gearth.protocol.packethandler.flash.FlashPacketHandler;
|
||||||
|
import gearth.protocol.packethandler.PayloadBuffer;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
@ -25,17 +27,17 @@ public class Rc4Obtainer {
|
|||||||
public static final boolean DEBUG = false;
|
public static final boolean DEBUG = false;
|
||||||
|
|
||||||
private HabboClient client;
|
private HabboClient client;
|
||||||
private List<PacketHandler> packetHandlers;
|
private List<FlashPacketHandler> flashPacketHandlers;
|
||||||
|
|
||||||
public Rc4Obtainer(HConnection hConnection) {
|
public Rc4Obtainer(HConnection hConnection) {
|
||||||
client = HabboClientFactory.get(hConnection);
|
client = HabboClientFactory.get(hConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setPacketHandlers(PacketHandler... packetHandlers) {
|
public void setFlashPacketHandlers(FlashPacketHandler... flashPacketHandlers) {
|
||||||
this.packetHandlers = Arrays.asList(packetHandlers);
|
this.flashPacketHandlers = Arrays.asList(flashPacketHandlers);
|
||||||
|
|
||||||
for (PacketHandler handler : packetHandlers) {
|
for (FlashPacketHandler handler : flashPacketHandlers) {
|
||||||
BufferChangeListener bufferChangeListener = new BufferChangeListener() {
|
BufferChangeListener bufferChangeListener = new BufferChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void act() {
|
public void act() {
|
||||||
@ -53,10 +55,10 @@ public class Rc4Obtainer {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void onSendFirstEncryptedMessage(PacketHandler packetHandler) {
|
private void onSendFirstEncryptedMessage(FlashPacketHandler flashPacketHandler) {
|
||||||
if (!HConnection.DECRYPTPACKETS) return;
|
if (!HConnection.DECRYPTPACKETS) return;
|
||||||
|
|
||||||
packetHandlers.forEach(PacketHandler::block);
|
flashPacketHandlers.forEach(FlashPacketHandler::block);
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
|
||||||
@ -67,8 +69,8 @@ public class Rc4Obtainer {
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
while (!worked && i < 4) {
|
while (!worked && i < 4) {
|
||||||
worked = (i % 2 == 0) ?
|
worked = (i % 2 == 0) ?
|
||||||
onSendFirstEncryptedMessage(packetHandler, client.getRC4cached()) :
|
onSendFirstEncryptedMessage(flashPacketHandler, client.getRC4cached()) :
|
||||||
onSendFirstEncryptedMessage(packetHandler, client.getRC4possibilities());
|
onSendFirstEncryptedMessage(flashPacketHandler, client.getRC4possibilities());
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,16 +109,16 @@ public class Rc4Obtainer {
|
|||||||
System.out.println("Cracked RC4 in " + (endTime - startTime) + "ms");
|
System.out.println("Cracked RC4 in " + (endTime - startTime) + "ms");
|
||||||
}
|
}
|
||||||
|
|
||||||
packetHandlers.forEach(PacketHandler::unblock);
|
flashPacketHandlers.forEach(FlashPacketHandler::unblock);
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onSendFirstEncryptedMessage(PacketHandler packetHandler, List<byte[]> potentialRC4tables) {
|
private boolean onSendFirstEncryptedMessage(FlashPacketHandler flashPacketHandler, List<byte[]> potentialRC4tables) {
|
||||||
for (byte[] possible : potentialRC4tables) {
|
for (byte[] possible : potentialRC4tables) {
|
||||||
|
|
||||||
byte[] encBuffer = new byte[packetHandler.getEncryptedBuffer().size()];
|
byte[] encBuffer = new byte[flashPacketHandler.getEncryptedBuffer().size()];
|
||||||
for (int i = 0; i < encBuffer.length; i++) {
|
for (int i = 0; i < encBuffer.length; i++) {
|
||||||
encBuffer[i] = packetHandler.getEncryptedBuffer().get(i);
|
encBuffer[i] = flashPacketHandler.getEncryptedBuffer().get(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
@ -124,7 +126,7 @@ public class Rc4Obtainer {
|
|||||||
byte[] keycpy = Arrays.copyOf(possible, possible.length);
|
byte[] keycpy = Arrays.copyOf(possible, possible.length);
|
||||||
RC4 rc4Tryout = new RC4(keycpy, i, j);
|
RC4 rc4Tryout = new RC4(keycpy, i, j);
|
||||||
|
|
||||||
if (packetHandler.getMessageSide() == HMessage.Direction.TOSERVER) rc4Tryout.undoRc4(encBuffer);
|
if (flashPacketHandler.getMessageSide() == HMessage.Direction.TOSERVER) rc4Tryout.undoRc4(encBuffer);
|
||||||
if (rc4Tryout.couldBeFresh()) {
|
if (rc4Tryout.couldBeFresh()) {
|
||||||
byte[] encDataCopy = Arrays.copyOf(encBuffer, encBuffer.length);
|
byte[] encDataCopy = Arrays.copyOf(encBuffer, encBuffer.length);
|
||||||
RC4 rc4TryCopy = rc4Tryout.deepCopy();
|
RC4 rc4TryCopy = rc4Tryout.deepCopy();
|
||||||
@ -135,7 +137,7 @@ public class Rc4Obtainer {
|
|||||||
HPacket[] checker = payloadBuffer.pushAndReceive(decoded);
|
HPacket[] checker = payloadBuffer.pushAndReceive(decoded);
|
||||||
|
|
||||||
if (payloadBuffer.peak().length == 0) {
|
if (payloadBuffer.peak().length == 0) {
|
||||||
packetHandler.setRc4(rc4Tryout);
|
flashPacketHandler.setRc4(rc4Tryout);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package gearth.protocol.packethandler;
|
||||||
|
|
||||||
|
public class ByteArrayUtils {
|
||||||
|
|
||||||
|
public static 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,125 +1,32 @@
|
|||||||
package gearth.protocol.packethandler;
|
package gearth.protocol.packethandler;
|
||||||
|
|
||||||
import gearth.misc.listenerpattern.Observable;
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HConnection;
|
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
import gearth.protocol.HPacket;
|
|
||||||
import gearth.protocol.TrafficListener;
|
import gearth.protocol.TrafficListener;
|
||||||
import gearth.protocol.crypto.RC4;
|
|
||||||
import gearth.services.extensionhandler.ExtensionHandler;
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
import gearth.services.extensionhandler.OnHMessageHandled;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class PacketHandler {
|
public abstract class PacketHandler {
|
||||||
|
|
||||||
protected static final boolean DEBUG = false;
|
protected final ExtensionHandler extensionHandler;
|
||||||
|
private final Object[] trafficObservables; //get notified on packet send
|
||||||
|
protected final PayloadBuffer payloadBuffer;
|
||||||
|
protected volatile int currentIndex = 0;
|
||||||
|
protected final Object sendLock = new Object();
|
||||||
|
|
||||||
private volatile PayloadBuffer payloadBuffer = new PayloadBuffer();
|
protected PacketHandler(ExtensionHandler extensionHandler, Object[] trafficObservables) {
|
||||||
private volatile OutputStream out;
|
|
||||||
private volatile ExtensionHandler extensionHandler;
|
|
||||||
private volatile Object[] trafficObservables; //get notified on packet send
|
|
||||||
private volatile boolean isTempBlocked = false;
|
|
||||||
volatile boolean isDataStream = false;
|
|
||||||
private volatile int currentIndex = 0;
|
|
||||||
|
|
||||||
private final Object manipulationLock = new Object();
|
|
||||||
private final Object sendLock = new Object();
|
|
||||||
|
|
||||||
private RC4 decryptcipher = null;
|
|
||||||
private RC4 encryptcipher = null;
|
|
||||||
|
|
||||||
private volatile List<Byte> tempEncryptedBuffer = new ArrayList<>();
|
|
||||||
volatile boolean isEncryptedStream = false;
|
|
||||||
|
|
||||||
|
|
||||||
PacketHandler(OutputStream outputStream, Object[] trafficObservables, ExtensionHandler extensionHandler) {
|
|
||||||
this.trafficObservables = trafficObservables;
|
|
||||||
this.extensionHandler = extensionHandler;
|
this.extensionHandler = extensionHandler;
|
||||||
out = outputStream;
|
this.trafficObservables = trafficObservables;
|
||||||
}
|
this.payloadBuffer = new PayloadBuffer();
|
||||||
|
|
||||||
public boolean isDataStream() {return isDataStream;}
|
|
||||||
public void setAsDataStream() {
|
|
||||||
isDataStream = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEncryptedStream() {
|
|
||||||
return isEncryptedStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void act(byte[] buffer) throws IOException {
|
|
||||||
if (!isDataStream) {
|
|
||||||
out.write(buffer);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferChangeObservable.fireEvent();
|
|
||||||
|
|
||||||
if (!isEncryptedStream) {
|
|
||||||
payloadBuffer.push(buffer);
|
|
||||||
}
|
|
||||||
else if (!HConnection.DECRYPTPACKETS) {
|
|
||||||
synchronized (sendLock) {
|
|
||||||
out.write(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (decryptcipher == null) {
|
|
||||||
for (int i = 0; i < buffer.length; i++) {
|
|
||||||
tempEncryptedBuffer.add(buffer[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
byte[] tm = decryptcipher.rc4(buffer);
|
|
||||||
if (DEBUG) {
|
|
||||||
printForDebugging(tm);
|
|
||||||
}
|
|
||||||
payloadBuffer.push(tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isTempBlocked) {
|
|
||||||
flush();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setRc4(RC4 rc4) {
|
public abstract void sendToStream(byte[] buffer);
|
||||||
this.decryptcipher = rc4.deepCopy();
|
|
||||||
this.encryptcipher = rc4.deepCopy();
|
|
||||||
|
|
||||||
byte[] encrbuffer = new byte[tempEncryptedBuffer.size()];
|
public abstract void act(byte[] buffer) throws IOException;
|
||||||
for (int i = 0; i < tempEncryptedBuffer.size(); i++) {
|
|
||||||
encrbuffer[i] = tempEncryptedBuffer.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
protected void notifyListeners(int i, HMessage message) {
|
||||||
act(encrbuffer);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
tempEncryptedBuffer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
private void notifyListeners(int i, HMessage message) {
|
|
||||||
((Observable<TrafficListener>) trafficObservables[i]).fireEvent(trafficListener -> {
|
((Observable<TrafficListener>) trafficObservables[i]).fireEvent(trafficListener -> {
|
||||||
message.getPacket().resetReadIndex();
|
message.getPacket().resetReadIndex();
|
||||||
trafficListener.onCapture(message);
|
trafficListener.onCapture(message);
|
||||||
@ -127,72 +34,4 @@ public abstract class PacketHandler {
|
|||||||
message.getPacket().resetReadIndex();
|
message.getPacket().resetReadIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendToStream(byte[] buffer) {
|
|
||||||
synchronized (sendLock) {
|
|
||||||
try {
|
|
||||||
out.write(
|
|
||||||
(!isEncryptedStream)
|
|
||||||
? buffer
|
|
||||||
: encryptcipher.rc4(buffer)
|
|
||||||
);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void flush() throws IOException {
|
|
||||||
synchronized (manipulationLock) {
|
|
||||||
HPacket[] hpackets = payloadBuffer.receive();
|
|
||||||
|
|
||||||
for (HPacket hpacket : hpackets){
|
|
||||||
HMessage hMessage = new HMessage(hpacket, getMessageSide(), currentIndex);
|
|
||||||
boolean isencrypted = isEncryptedStream;
|
|
||||||
|
|
||||||
OnHMessageHandled afterExtensionIntercept = hMessage1 -> {
|
|
||||||
if (isDataStream) {
|
|
||||||
notifyListeners(2, hMessage1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hMessage1.isBlocked()) {
|
|
||||||
synchronized (sendLock) {
|
|
||||||
out.write(
|
|
||||||
(!isencrypted)
|
|
||||||
? hMessage1.getPacket().toBytes()
|
|
||||||
: encryptcipher.rc4(hMessage1.getPacket().toBytes())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isDataStream) {
|
|
||||||
notifyListeners(0, hMessage);
|
|
||||||
notifyListeners(1, hMessage);
|
|
||||||
extensionHandler.handle(hMessage, afterExtensionIntercept);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
afterExtensionIntercept.finished(hMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract HMessage.Direction getMessageSide();
|
|
||||||
|
|
||||||
public List<Byte> getEncryptedBuffer() {
|
|
||||||
return tempEncryptedBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void printForDebugging(byte[] bytes);
|
|
||||||
|
|
||||||
private Observable<BufferChangeListener> bufferChangeObservable = new Observable<>(BufferChangeListener::act);
|
|
||||||
public Observable<BufferChangeListener> getBufferChangeObservable() {
|
|
||||||
return bufferChangeObservable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getCurrentIndex() {
|
|
||||||
return currentIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ public class PayloadBuffer {
|
|||||||
return receive();
|
return receive();
|
||||||
}
|
}
|
||||||
public void push(byte[] tcpData) {
|
public void push(byte[] tcpData) {
|
||||||
buffer = buffer.length == 0 ? tcpData.clone() : combineByteArrays(buffer, tcpData);
|
buffer = buffer.length == 0 ? tcpData.clone() : ByteArrayUtils.combineByteArrays(buffer, tcpData);
|
||||||
}
|
}
|
||||||
public HPacket[] receive() {
|
public HPacket[] receive() {
|
||||||
if (buffer.length < 6) return new HPacket[0];
|
if (buffer.length < 6) return new HPacket[0];
|
||||||
@ -30,14 +30,6 @@ public class PayloadBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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() {
|
public byte[] peak() {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package gearth.protocol.packethandler;
|
package gearth.protocol.packethandler.flash;
|
||||||
|
|
||||||
|
|
||||||
public interface BufferChangeListener {
|
public interface BufferChangeListener {
|
@ -0,0 +1,182 @@
|
|||||||
|
package gearth.protocol.packethandler.flash;
|
||||||
|
|
||||||
|
import gearth.misc.listenerpattern.Observable;
|
||||||
|
import gearth.protocol.HConnection;
|
||||||
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
import gearth.protocol.TrafficListener;
|
||||||
|
import gearth.protocol.crypto.RC4;
|
||||||
|
import gearth.protocol.packethandler.PacketHandler;
|
||||||
|
import gearth.protocol.packethandler.PayloadBuffer;
|
||||||
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
|
import gearth.services.extensionhandler.OnHMessageHandled;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class FlashPacketHandler extends PacketHandler {
|
||||||
|
|
||||||
|
protected static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private volatile OutputStream out;
|
||||||
|
private volatile boolean isTempBlocked = false;
|
||||||
|
volatile boolean isDataStream = false;
|
||||||
|
|
||||||
|
private final Object manipulationLock = new Object();
|
||||||
|
|
||||||
|
private RC4 decryptcipher = null;
|
||||||
|
private RC4 encryptcipher = null;
|
||||||
|
|
||||||
|
private volatile List<Byte> tempEncryptedBuffer = new ArrayList<>();
|
||||||
|
volatile boolean isEncryptedStream = false;
|
||||||
|
|
||||||
|
|
||||||
|
FlashPacketHandler(OutputStream outputStream, Object[] trafficObservables, ExtensionHandler extensionHandler) {
|
||||||
|
super(extensionHandler, trafficObservables);
|
||||||
|
out = outputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDataStream() {return isDataStream;}
|
||||||
|
public void setAsDataStream() {
|
||||||
|
isDataStream = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEncryptedStream() {
|
||||||
|
return isEncryptedStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void act(byte[] buffer) throws IOException {
|
||||||
|
if (!isDataStream) {
|
||||||
|
out.write(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferChangeObservable.fireEvent();
|
||||||
|
|
||||||
|
if (!isEncryptedStream) {
|
||||||
|
payloadBuffer.push(buffer);
|
||||||
|
}
|
||||||
|
else if (!HConnection.DECRYPTPACKETS) {
|
||||||
|
synchronized (sendLock) {
|
||||||
|
out.write(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (decryptcipher == null) {
|
||||||
|
for (int i = 0; i < buffer.length; i++) {
|
||||||
|
tempEncryptedBuffer.add(buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte[] tm = decryptcipher.rc4(buffer);
|
||||||
|
if (DEBUG) {
|
||||||
|
printForDebugging(tm);
|
||||||
|
}
|
||||||
|
payloadBuffer.push(tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTempBlocked) {
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setRc4(RC4 rc4) {
|
||||||
|
this.decryptcipher = rc4.deepCopy();
|
||||||
|
this.encryptcipher = rc4.deepCopy();
|
||||||
|
|
||||||
|
byte[] encrbuffer = new byte[tempEncryptedBuffer.size()];
|
||||||
|
for (int i = 0; i < tempEncryptedBuffer.size(); i++) {
|
||||||
|
encrbuffer[i] = tempEncryptedBuffer.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
act(encrbuffer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
tempEncryptedBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void block() {
|
||||||
|
isTempBlocked = true;
|
||||||
|
}
|
||||||
|
public void unblock() {
|
||||||
|
try {
|
||||||
|
flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
isTempBlocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendToStream(byte[] buffer) {
|
||||||
|
synchronized (sendLock) {
|
||||||
|
try {
|
||||||
|
out.write(
|
||||||
|
(!isEncryptedStream)
|
||||||
|
? buffer
|
||||||
|
: encryptcipher.rc4(buffer)
|
||||||
|
);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException {
|
||||||
|
synchronized (manipulationLock) {
|
||||||
|
HPacket[] hpackets = payloadBuffer.receive();
|
||||||
|
|
||||||
|
for (HPacket hpacket : hpackets){
|
||||||
|
HMessage hMessage = new HMessage(hpacket, getMessageSide(), currentIndex);
|
||||||
|
boolean isencrypted = isEncryptedStream;
|
||||||
|
|
||||||
|
OnHMessageHandled afterExtensionIntercept = hMessage1 -> {
|
||||||
|
if (isDataStream) {
|
||||||
|
notifyListeners(2, hMessage1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hMessage1.isBlocked()) {
|
||||||
|
synchronized (sendLock) {
|
||||||
|
out.write(
|
||||||
|
(!isencrypted)
|
||||||
|
? hMessage1.getPacket().toBytes()
|
||||||
|
: encryptcipher.rc4(hMessage1.getPacket().toBytes())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isDataStream) {
|
||||||
|
notifyListeners(0, hMessage);
|
||||||
|
notifyListeners(1, hMessage);
|
||||||
|
extensionHandler.handle(hMessage, afterExtensionIntercept);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
afterExtensionIntercept.finished(hMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract HMessage.Direction getMessageSide();
|
||||||
|
|
||||||
|
public List<Byte> getEncryptedBuffer() {
|
||||||
|
return tempEncryptedBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void printForDebugging(byte[] bytes);
|
||||||
|
|
||||||
|
private Observable<BufferChangeListener> bufferChangeObservable = new Observable<>(BufferChangeListener::act);
|
||||||
|
public Observable<BufferChangeListener> getBufferChangeObservable() {
|
||||||
|
return bufferChangeObservable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentIndex() {
|
||||||
|
return currentIndex;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package gearth.protocol.packethandler;
|
package gearth.protocol.packethandler.flash;
|
||||||
|
|
||||||
import gearth.misc.listenerpattern.Observable;
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
@ -6,13 +6,11 @@ import gearth.protocol.HPacket;
|
|||||||
import gearth.protocol.TrafficListener;
|
import gearth.protocol.TrafficListener;
|
||||||
import gearth.services.extensionhandler.ExtensionHandler;
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class IncomingPacketHandler extends PacketHandler {
|
public class IncomingFlashPacketHandler extends FlashPacketHandler {
|
||||||
|
|
||||||
public IncomingPacketHandler(OutputStream outputStream, Object[] trafficObservables, OutgoingPacketHandler outgoingHandler, ExtensionHandler extensionHandler) {
|
public IncomingFlashPacketHandler(OutputStream outputStream, Object[] trafficObservables, OutgoingFlashPacketHandler outgoingHandler, ExtensionHandler extensionHandler) {
|
||||||
super(outputStream, trafficObservables, extensionHandler);
|
super(outputStream, trafficObservables, extensionHandler);
|
||||||
|
|
||||||
TrafficListener listener = new TrafficListener() {
|
TrafficListener listener = new TrafficListener() {
|
@ -1,4 +1,4 @@
|
|||||||
package gearth.protocol.packethandler;
|
package gearth.protocol.packethandler.flash;
|
||||||
|
|
||||||
public interface OnDatastreamConfirmedListener {
|
public interface OnDatastreamConfirmedListener {
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package gearth.protocol.packethandler;
|
package gearth.protocol.packethandler.flash;
|
||||||
|
|
||||||
import gearth.misc.listenerpattern.Observable;
|
import gearth.misc.listenerpattern.Observable;
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
@ -7,13 +7,10 @@ import gearth.services.extensionhandler.ExtensionHandler;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class OutgoingPacketHandler extends PacketHandler {
|
public class OutgoingFlashPacketHandler extends FlashPacketHandler {
|
||||||
|
|
||||||
public OutgoingPacketHandler(OutputStream outputStream, Object[] trafficObservables, ExtensionHandler extensionHandler) {
|
public OutgoingFlashPacketHandler(OutputStream outputStream, Object[] trafficObservables, ExtensionHandler extensionHandler) {
|
||||||
super(outputStream, trafficObservables, extensionHandler);
|
super(outputStream, trafficObservables, extensionHandler);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
|||||||
|
package gearth.protocol.packethandler.unity;
|
||||||
|
|
||||||
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
|
import gearth.protocol.packethandler.ByteArrayUtils;
|
||||||
|
import gearth.protocol.packethandler.PacketHandler;
|
||||||
|
import gearth.protocol.packethandler.PayloadBuffer;
|
||||||
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
|
import gearth.services.extensionhandler.OnHMessageHandled;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class UnityPacketHandler extends PacketHandler {
|
||||||
|
|
||||||
|
private final Session session;
|
||||||
|
private final HMessage.Direction direction;
|
||||||
|
|
||||||
|
public UnityPacketHandler(ExtensionHandler extensionHandler, Object[] trafficObservables, Session session, HMessage.Direction direction) {
|
||||||
|
super(extensionHandler, trafficObservables);
|
||||||
|
this.session = session;
|
||||||
|
this.direction = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendToStream(byte[] buffer) {
|
||||||
|
byte[] prefix = new byte[]{(direction == HMessage.Direction.TOCLIENT ? ((byte)0) : ((byte)1))};
|
||||||
|
byte[] combined = ByteArrayUtils.combineByteArrays(prefix, buffer);
|
||||||
|
|
||||||
|
session.getAsyncRemote().sendBinary(ByteBuffer.wrap(combined));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void act(byte[] buffer) throws IOException {
|
||||||
|
HMessage hMessage = new HMessage(new HPacket(buffer), direction, currentIndex);
|
||||||
|
|
||||||
|
OnHMessageHandled afterExtensionIntercept = hMessage1 -> {
|
||||||
|
notifyListeners(2, hMessage1);
|
||||||
|
|
||||||
|
if (!hMessage1.isBlocked()) {
|
||||||
|
sendToStream(hMessage1.getPacket().toBytes());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
notifyListeners(0, hMessage);
|
||||||
|
notifyListeners(1, hMessage);
|
||||||
|
extensionHandler.handle(hMessage, afterExtensionIntercept);
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
}
|
7
G-Earth/src/main/java/gearth/services/Constants.java
Normal file
7
G-Earth/src/main/java/gearth/services/Constants.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package gearth.services;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static volatile boolean UNITY_PACKETS = false;
|
||||||
|
|
||||||
|
}
|
@ -212,6 +212,27 @@ public class ExtensionHandler {
|
|||||||
protected void manipulatedPacket(HMessage hMessage) {
|
protected void manipulatedPacket(HMessage hMessage) {
|
||||||
onExtensionRespond(extension, hMessage);
|
onExtensionRespond(extension, hMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void packetToStringRequest(HPacket packet) {
|
||||||
|
String s = "";
|
||||||
|
String expression = "";
|
||||||
|
try {
|
||||||
|
s = packet.toString();
|
||||||
|
if (packet.length() < 3000) {
|
||||||
|
expression = packet.toExpression();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
extension.packetToStringResponse(s, expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void stringToPacketRequest(String string) {
|
||||||
|
HPacket packet = new HPacket(string);
|
||||||
|
extension.stringToPacketResponse(packet);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
extension.getExtensionObservable().addListener(listener);
|
extension.getExtensionObservable().addListener(listener);
|
||||||
|
@ -12,4 +12,7 @@ public abstract class ExtensionListener {
|
|||||||
protected void log(String text) {}
|
protected void log(String text) {}
|
||||||
protected void hasClosed() {}
|
protected void hasClosed() {}
|
||||||
|
|
||||||
|
protected void packetToStringRequest(HPacket packet) {}
|
||||||
|
protected void stringToPacketRequest(String string) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ import gearth.services.extensionhandler.extensions.listeners.OmRemoveClickListen
|
|||||||
import gearth.services.extensionhandler.extensions.listeners.OnClickListener;
|
import gearth.services.extensionhandler.extensions.listeners.OnClickListener;
|
||||||
import gearth.services.extensionhandler.extensions.listeners.OnDeleteListener;
|
import gearth.services.extensionhandler.extensions.listeners.OnDeleteListener;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public abstract class GEarthExtension {
|
public abstract class GEarthExtension {
|
||||||
|
|
||||||
|
|
||||||
@ -40,6 +42,8 @@ public abstract class GEarthExtension {
|
|||||||
public abstract void connectionEnd();
|
public abstract void connectionEnd();
|
||||||
public abstract void init();
|
public abstract void init();
|
||||||
public abstract void close();
|
public abstract void close();
|
||||||
|
public abstract void packetToStringResponse(String string, String expression);
|
||||||
|
public abstract void stringToPacketResponse(HPacket packet);
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@ -78,6 +82,19 @@ public abstract class GEarthExtension {
|
|||||||
protected void hasClosed() {
|
protected void hasClosed() {
|
||||||
extensionObservable.fireEvent(ExtensionListener::hasClosed);
|
extensionObservable.fireEvent(ExtensionListener::hasClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void packetToStringRequest(HPacket packet) {
|
||||||
|
int orgIndex = packet.getReadIndex();
|
||||||
|
extensionObservable.fireEvent(listener -> {
|
||||||
|
packet.setReadIndex(6);
|
||||||
|
listener.packetToStringRequest(packet);
|
||||||
|
});
|
||||||
|
packet.setReadIndex(orgIndex);
|
||||||
|
}
|
||||||
|
protected void stringToPacketRequest(String string) {
|
||||||
|
extensionObservable.fireEvent(l -> l.stringToPacketRequest(string));
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import java.io.DataInputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 21/06/18.
|
* Created by Jonas on 21/06/18.
|
||||||
@ -88,6 +89,14 @@ public class NetworkExtension extends GEarthExtension {
|
|||||||
else if (message.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONCONSOLELOG) {
|
else if (message.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.EXTENSIONCONSOLELOG) {
|
||||||
log(message.readString());
|
log(message.readString());
|
||||||
}
|
}
|
||||||
|
else if (message.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.PACKETTOSTRING_REQUEST) {
|
||||||
|
HPacket p = new HPacket(new byte[0]);
|
||||||
|
p.constructFromString(message.readLongString());
|
||||||
|
packetToStringRequest(p);
|
||||||
|
}
|
||||||
|
else if (message.headerId() == NetworkExtensionInfo.INCOMING_MESSAGES_IDS.STRINGTOPACKET_REQUEST) {
|
||||||
|
stringToPacketRequest(message.readLongString(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,4 +220,19 @@ public class NetworkExtension extends GEarthExtension {
|
|||||||
connection.close();
|
connection.close();
|
||||||
} catch (IOException ignored) { }
|
} catch (IOException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packetToStringResponse(String string, String expression) {
|
||||||
|
HPacket packet = new HPacket(NetworkExtensionInfo.OUTGOING_MESSAGES_IDS.PACKETTOSTRING_RESPONSE);
|
||||||
|
packet.appendLongString(string);
|
||||||
|
packet.appendLongString(expression, StandardCharsets.UTF_8);
|
||||||
|
sendMessage(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stringToPacketResponse(HPacket packetFromString) {
|
||||||
|
HPacket packet = new HPacket(NetworkExtensionInfo.OUTGOING_MESSAGES_IDS.STRINGTOPACKET_RESPONSE);
|
||||||
|
packet.appendLongString(packetFromString.stringify());
|
||||||
|
sendMessage(packet);
|
||||||
|
}
|
||||||
}
|
}
|
@ -87,6 +87,9 @@ public class NetworkExtensionInfo {
|
|||||||
public static final int CONNECTIONSTART = 5;
|
public static final int CONNECTIONSTART = 5;
|
||||||
public static final int CONNECTIONEND = 6;
|
public static final int CONNECTIONEND = 6;
|
||||||
public static final int INIT = 7;
|
public static final int INIT = 7;
|
||||||
|
|
||||||
|
public static final int PACKETTOSTRING_RESPONSE = 20;
|
||||||
|
public static final int STRINGTOPACKET_RESPONSE = 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,6 +98,10 @@ public class NetworkExtensionInfo {
|
|||||||
public static final int MANIPULATEDPACKET = 2;
|
public static final int MANIPULATEDPACKET = 2;
|
||||||
public static final int REQUESTFLAGS = 3;
|
public static final int REQUESTFLAGS = 3;
|
||||||
public static final int SENDMESSAGE = 4;
|
public static final int SENDMESSAGE = 4;
|
||||||
|
|
||||||
|
public static final int PACKETTOSTRING_REQUEST = 20;
|
||||||
|
public static final int STRINGTOPACKET_REQUEST = 21;
|
||||||
|
|
||||||
public static final int EXTENSIONCONSOLELOG = 98;
|
public static final int EXTENSIONCONSOLELOG = 98;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,7 @@ import javafx.application.Platform;
|
|||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 16/10/18.
|
* Created by Jonas on 16/10/18.
|
||||||
@ -16,15 +14,24 @@ import java.util.Random;
|
|||||||
public class Authenticator {
|
public class Authenticator {
|
||||||
|
|
||||||
private static Map<String, String> cookies = new HashMap<>();
|
private static Map<String, String> cookies = new HashMap<>();
|
||||||
|
private static Set<String> perma_cookies = new HashSet<>();
|
||||||
|
|
||||||
public static String generateCookieForExtension(String filename) {
|
public static String generateCookieForExtension(String filename) {
|
||||||
String cookie = getRandomCookie();
|
String cookie = getRandomCookie();
|
||||||
cookies.put(filename, cookie);
|
cookies.put(filename, cookie);
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
public static String generatePermanentCookie() {
|
||||||
|
String cookie = getRandomCookie();
|
||||||
|
perma_cookies.add(cookie);
|
||||||
return cookie;
|
return cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean evaluate(NetworkExtension extension) {
|
public static boolean evaluate(NetworkExtension extension) {
|
||||||
|
if (extension.getCookie() != null && perma_cookies.contains(extension.getCookie())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (extension.isInstalledExtension()) {
|
if (extension.isInstalledExtension()) {
|
||||||
return claimSession(extension.getFileName(), extension.getCookie());
|
return claimSession(extension.getFileName(), extension.getCookie());
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gearth.services.extensionhandler.extensions.implementations.simple;
|
package gearth.services.extensionhandler.extensions.implementations.simple;
|
||||||
|
|
||||||
import gearth.protocol.HMessage;
|
import gearth.protocol.HMessage;
|
||||||
|
import gearth.protocol.HPacket;
|
||||||
import gearth.services.extensionhandler.extensions.GEarthExtension;
|
import gearth.services.extensionhandler.extensions.GEarthExtension;
|
||||||
|
|
||||||
public class ExampleExtension extends GEarthExtension {
|
public class ExampleExtension extends GEarthExtension {
|
||||||
@ -105,4 +106,18 @@ public class ExampleExtension extends GEarthExtension {
|
|||||||
// finish up and call "hasClosed()"
|
// finish up and call "hasClosed()"
|
||||||
hasClosed();
|
hasClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ignore these
|
||||||
|
@Override
|
||||||
|
public void packetToStringResponse(String string, String expression) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stringToPacketResponse(HPacket packet) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
205
G-Earth/src/main/java/gearth/services/gpython/GPythonShell.java
Normal file
205
G-Earth/src/main/java/gearth/services/gpython/GPythonShell.java
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
|
import gearth.ui.extra.ExtraController;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.Hyperlink;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.FlowPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class GPythonShell {
|
||||||
|
|
||||||
|
private final String extensionName;
|
||||||
|
private final int port;
|
||||||
|
private final String cookie;
|
||||||
|
|
||||||
|
public GPythonShell(String extensionName, int port, String cookie) {
|
||||||
|
this.extensionName = extensionName;
|
||||||
|
this.port = port;
|
||||||
|
this.cookie = cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launch(OnQtConsoleLaunch onLaunch) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
// launch the jupyter console
|
||||||
|
ProcessBuilder gConsoleBuilder = new ProcessBuilder("python", "-m", "jupyter", "console", "--simple-prompt");
|
||||||
|
Process gConsole = gConsoleBuilder.start();
|
||||||
|
|
||||||
|
InputStreamReader in = new InputStreamReader(gConsole.getInputStream());
|
||||||
|
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(gConsole.getOutputStream()));
|
||||||
|
|
||||||
|
readUntilExpectInput(in);
|
||||||
|
|
||||||
|
// obtain jupyter kernel name
|
||||||
|
List<String> sysargs = enterCommandAndAwait(out, in, "import sys; sys.argv");
|
||||||
|
String kernelName = extractKernelName(sysargs);
|
||||||
|
|
||||||
|
InputStream initScriptResource = getClass().getResourceAsStream("init_script.py");
|
||||||
|
List<String> initScript = new BufferedReader(new InputStreamReader(initScriptResource,
|
||||||
|
StandardCharsets.UTF_8)).lines().collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (String line : initScript) {
|
||||||
|
line = line.replace("$G_PYTHON_SHELL_TITLE$", extensionName)
|
||||||
|
.replace("$G_EARTH_PORT$", "" + port)
|
||||||
|
.replace("$COOKIE$", cookie);
|
||||||
|
enterCommandAndAwait(out, in, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBuilder qtConsoleBuilder = new ProcessBuilder("python", "-m", "jupyter", "qtconsole",
|
||||||
|
"--ConsoleWidget.include_other_output", "True",
|
||||||
|
"--ConsoleWidget.gui_completion", "'droplist'",
|
||||||
|
// "--ConsoleWidget.other_output_prefix", "'[G-Earth]'",
|
||||||
|
// "--JupyterWidget.in_prompt", "'>>>: '",
|
||||||
|
// "--JupyterWidget.out_prompt", "''",
|
||||||
|
"--KernelManager.autorestart", "False",
|
||||||
|
"--JupyterConsoleApp.confirm_exit", "False",
|
||||||
|
"--JupyterConsoleApp.existing", kernelName);
|
||||||
|
Process qtConsole = qtConsoleBuilder.start();
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
qtConsole.waitFor();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
enterCommandAndAwait(out, in, "ext.stop()");
|
||||||
|
enterCommand(out, "exit()");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
onLaunch.launched(false);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
showError();
|
||||||
|
onLaunch.launched(true);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> readUntilExpectInput(InputStreamReader in) throws IOException {
|
||||||
|
List<String> readings = new ArrayList<>();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
int c;
|
||||||
|
while ((c = in.read()) != -1) {
|
||||||
|
char character = (char)c;
|
||||||
|
if (character == '\n') {
|
||||||
|
String reading = builder.toString();
|
||||||
|
if (reading.endsWith("\r")) {
|
||||||
|
reading = reading.substring(0, reading.length() - 1);
|
||||||
|
}
|
||||||
|
if (reading.matches("Out\\[[0-9+]]: .*")) {
|
||||||
|
reading = reading.replaceAll("^Out\\[[0-9+]]: ", "");
|
||||||
|
if (reading.equals("")) {
|
||||||
|
builder = new StringBuilder();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
readings.add(reading);
|
||||||
|
builder = new StringBuilder();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder.append(character);
|
||||||
|
|
||||||
|
if (builder.toString().matches("In \\[[0-9]+]: ") && !in.ready()) {
|
||||||
|
return readings;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private void enterCommand(BufferedWriter out, String command) throws IOException {
|
||||||
|
out.write(command);
|
||||||
|
out.newLine();
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
private List<String> enterCommandAndAwait(BufferedWriter out, InputStreamReader in, String command) throws IOException {
|
||||||
|
enterCommand(out, command);
|
||||||
|
return readUntilExpectInput(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String extractKernelName(List<String> inputArgs) {
|
||||||
|
// null if not found
|
||||||
|
|
||||||
|
String joined = String.join("", inputArgs);
|
||||||
|
String paramsFull = joined.replaceAll("^[^\\[]*\\[", "").replaceAll("][^]]*$", "");
|
||||||
|
List<String> params = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean backslashed = false;
|
||||||
|
int beginParameterIndex = -1;
|
||||||
|
for (int i = 0; i < paramsFull.length(); i++) {
|
||||||
|
char c = paramsFull.charAt(i);
|
||||||
|
if (c == '\'' && !backslashed) {
|
||||||
|
if (beginParameterIndex == -1) {
|
||||||
|
beginParameterIndex = i + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.add(paramsFull.substring(beginParameterIndex, i));
|
||||||
|
beginParameterIndex = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
backslashed = c == '\\' && !backslashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < params.size() - 1; i++) {
|
||||||
|
if (params.get(i).equals("-f")) {
|
||||||
|
return "'" + params.get(i+1) + "'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showError() {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR, "G-Python error", ButtonType.OK);
|
||||||
|
alert.setTitle("G-Python error");
|
||||||
|
|
||||||
|
FlowPane fp = new FlowPane();
|
||||||
|
Label lbl = new Label("Something went wrong launching the G-Python shell," +
|
||||||
|
System.lineSeparator() + "are you sure you followed the installation guide correctly?" +
|
||||||
|
System.lineSeparator() + System.lineSeparator() + "More information here:");
|
||||||
|
Hyperlink link = new Hyperlink(ExtraController.INFO_URL_GPYTHON);
|
||||||
|
fp.getChildren().addAll(lbl, link);
|
||||||
|
link.setOnAction(event -> {
|
||||||
|
Main.main.getHostServices().showDocument(link.getText());
|
||||||
|
event.consume();
|
||||||
|
});
|
||||||
|
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.getDialogPane().setContent(fp);
|
||||||
|
alert.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtensionName() {
|
||||||
|
return extensionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
GPythonShell shell = new GPythonShell("test", 9092, "cookie");
|
||||||
|
shell.launch((b) -> {
|
||||||
|
System.out.println("launched");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
import org.apache.maven.artifact.versioning.ComparableVersion;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GPythonVersionUtils {
|
||||||
|
|
||||||
|
private static final String MIN_GPYTHON_VERSION = "0.1";
|
||||||
|
private static final String MIN_PYTHON_VERSION = "3.2";
|
||||||
|
|
||||||
|
// returns null if python not installed
|
||||||
|
public static String pythonVersion() {
|
||||||
|
List<String> commandOutput = executeCommand("python", "--version");
|
||||||
|
if (commandOutput.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String maybeVersion = commandOutput.get(0);
|
||||||
|
if (!maybeVersion.contains("Python")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maybeVersion.split(" ")[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean validInstallation() {
|
||||||
|
// validates if user has all dependencies installed
|
||||||
|
String pythonVersion = pythonVersion();
|
||||||
|
if (pythonVersion == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparableVersion version = new ComparableVersion(pythonVersion);
|
||||||
|
if (version.compareTo(new ComparableVersion(MIN_PYTHON_VERSION)) < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> allPackages = executeCommand("python", "-m", "pip", "list");
|
||||||
|
allPackages = allPackages.subList(2, allPackages.size());
|
||||||
|
|
||||||
|
String qtconsole = getPackageVersion(allPackages, "qtconsole");
|
||||||
|
String pyqt5 = getPackageVersion(allPackages, "pyqt5");
|
||||||
|
String jupyterConsole = getPackageVersion(allPackages, "jupyter-console");
|
||||||
|
String gPython = getPackageVersion(allPackages, "g-python");
|
||||||
|
|
||||||
|
if (qtconsole == null || pyqt5 == null || jupyterConsole == null || gPython == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComparableVersion gVersion = new ComparableVersion(gPython);
|
||||||
|
return gVersion.compareTo(new ComparableVersion(MIN_GPYTHON_VERSION)) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// null if not found
|
||||||
|
private static String getPackageVersion(List<String> allPackages, String pkg) {
|
||||||
|
pkg = pkg.toLowerCase();
|
||||||
|
|
||||||
|
for (String maybePkg : allPackages) {
|
||||||
|
String[] split = maybePkg.split(" +");
|
||||||
|
if (split[0].toLowerCase().equals(pkg)) {
|
||||||
|
return split[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> executeCommand(String... command) {
|
||||||
|
List<String> output = new ArrayList<>();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
output.add(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args) {
|
||||||
|
// System.out.println(validInstallation());
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package gearth.services.gpython;
|
||||||
|
|
||||||
|
public interface OnQtConsoleLaunch {
|
||||||
|
|
||||||
|
void launched(boolean failed);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
package gearth.services.unity_tools;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
|
import gearth.misc.Cacher;
|
||||||
|
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class GUnityFileServer extends HttpServlet
|
||||||
|
{
|
||||||
|
|
||||||
|
public final static int FILESERVER_PORT = 9089;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
response.addHeader("Access-Control-Allow-Origin", "*");
|
||||||
|
String path = request.getPathInfo();
|
||||||
|
|
||||||
|
if (path.equals("/ping")) {
|
||||||
|
response.setStatus(200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = request.getParameter("blabla");
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
response.setStatus(404);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
response.addHeader("ETag", createETag());
|
||||||
|
|
||||||
|
String revision = url.split("/")[4];
|
||||||
|
|
||||||
|
if (path.equals("/prod")) getProd(revision, response);
|
||||||
|
else if (path.equals("/data")) getData(revision, response);
|
||||||
|
else if (path.equals("/wasm/code")) getWasmCode(revision, response);
|
||||||
|
else if (path.equals("/wasm/framework")) getWasmFramework(revision, response);
|
||||||
|
else if (path.equals("/unityloader")) getUnityLoader(revision, response);
|
||||||
|
else if (path.equals("/version")) getVersion(revision, response, url);
|
||||||
|
else if (path.equals("/logo")) getLogo(response);
|
||||||
|
else {
|
||||||
|
response.setStatus(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setStatus(200);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
response.setStatus(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getRandomHexString(int numchars){
|
||||||
|
Random r = new Random();
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
while(sb.length() < numchars){
|
||||||
|
sb.append(Integer.toHexString(r.nextInt()));
|
||||||
|
}
|
||||||
|
return sb.toString().substring(0, numchars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createETag() {
|
||||||
|
return "W/\"" + getRandomHexString(6) + "-" + getRandomHexString(13) + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDir(String revision) {
|
||||||
|
return Cacher.getCacheDir() + File.separator + "UNITY-" + revision + File.separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void fileResponse(String file, HttpServletResponse response, String contentType) throws IOException {
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
InputStream in = new FileInputStream(file);
|
||||||
|
// response.setContentType(contentType);
|
||||||
|
|
||||||
|
byte[] bytes = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = in.read(bytes)) != -1) {
|
||||||
|
out.write(bytes, 0, bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void getProd(String revision, HttpServletResponse response) throws IOException {
|
||||||
|
UnityWebModifyer unitywebModifyer = new UnityWebModifyer(revision, getDir(revision));
|
||||||
|
unitywebModifyer.modifyAllFiles();
|
||||||
|
|
||||||
|
fileResponse(getDir(revision) + UnityWebModifyer.UNITY_PROD, response, "application/json");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getData(String revision, HttpServletResponse response) throws IOException {
|
||||||
|
// application/vnd.unity
|
||||||
|
fileResponse(getDir(revision) + UnityWebModifyer.UNITY_DATA, response, "application/vnd.unity");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getWasmCode(String revision, HttpServletResponse response) throws IOException {
|
||||||
|
fileResponse(getDir(revision) + UnityWebModifyer.UNITY_CODE, response, "application/vnd.unity");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getWasmFramework(String revision, HttpServletResponse response) throws IOException {
|
||||||
|
fileResponse(getDir(revision) + UnityWebModifyer.UNITY_FRAMEWORK, response, "application/vnd.unity");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getUnityLoader(String revision, HttpServletResponse response) throws IOException {
|
||||||
|
UnityWebModifyer unitywebModifyer = new UnityWebModifyer(revision, getDir(revision));
|
||||||
|
unitywebModifyer.modifyAllFiles();
|
||||||
|
|
||||||
|
fileResponse(getDir(revision) + UnityWebModifyer.UNITY_LOADER, response, "text/javascript");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getVersion(String revision, HttpServletResponse response, String url) throws IOException {
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()));
|
||||||
|
|
||||||
|
String version = in.readLine();
|
||||||
|
String realVersion = version.split(" ")[0];
|
||||||
|
|
||||||
|
response.getOutputStream().print(realVersion + " - G-Earth by sirjonasxx");
|
||||||
|
response.getOutputStream().close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getLogo(HttpServletResponse response) throws IOException {
|
||||||
|
OutputStream out = response.getOutputStream();
|
||||||
|
InputStream in = Main.class.getResourceAsStream("G-EarthLogo.png");
|
||||||
|
|
||||||
|
byte[] bytes = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = in.read(bytes)) != -1) {
|
||||||
|
out.write(bytes, 0, bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,176 @@
|
|||||||
|
package gearth.services.unity_tools;
|
||||||
|
|
||||||
|
import wasm.disassembly.InvalidOpCodeException;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class UnityWebModifyer {
|
||||||
|
|
||||||
|
public final static String UNITY_PROD = "habbo2020-global-prod.json";
|
||||||
|
public final static String UNITY_DATA = "habbo2020-global-prod.data.unityweb";
|
||||||
|
public final static String UNITY_CODE = "habbo2020-global-prod.wasm.code.unityweb";
|
||||||
|
public final static String UNITY_FRAMEWORK = "habbo2020-global-prod.wasm.framework.unityweb";
|
||||||
|
public final static String UNITY_LOADER = "UnityLoader.js";
|
||||||
|
|
||||||
|
private final static String UNITYFILES_URL = "https://images.habbo.com/habbo-webgl-clients/{revision}/WebGL/habbo2020-global-prod/Build/";
|
||||||
|
|
||||||
|
private final String revision;
|
||||||
|
private final File saveFolder;
|
||||||
|
private final String currentUrl;
|
||||||
|
|
||||||
|
|
||||||
|
public UnityWebModifyer(String revision, String saveFolder) {
|
||||||
|
this.revision = revision;
|
||||||
|
this.currentUrl = UNITYFILES_URL.replace("{revision}", revision);
|
||||||
|
this.saveFolder = new File(saveFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean modifyAllFiles() {
|
||||||
|
if (saveFolder.exists()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
saveFolder.mkdirs();
|
||||||
|
|
||||||
|
try {
|
||||||
|
modifyProdFile();
|
||||||
|
modifyDataFile();
|
||||||
|
modifyCodeFile();
|
||||||
|
modifyFrameworkFile();
|
||||||
|
modifyUnityLoader();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
saveFolder.delete();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return urls for: data, code & framework file
|
||||||
|
private void modifyProdFile() throws IOException {
|
||||||
|
String prodUrl = currentUrl + UNITY_PROD;
|
||||||
|
|
||||||
|
URLConnection connection = new URL(prodUrl).openConnection();
|
||||||
|
InputStream is = connection.getInputStream();
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
FileWriter fileWriter = new FileWriter(new File(saveFolder, UNITY_PROD));
|
||||||
|
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
bufferedWriter.write(line);
|
||||||
|
bufferedWriter.newLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferedWriter.close();
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadToFile(URL url, File file) throws IOException {
|
||||||
|
BufferedInputStream in = new BufferedInputStream(url.openStream());
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||||
|
byte[] dataBuffer = new byte[1024];
|
||||||
|
int bytesRead;
|
||||||
|
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
|
||||||
|
fileOutputStream.write(dataBuffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
fileOutputStream.close();
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyDataFile() throws IOException {
|
||||||
|
File dataFile = new File(saveFolder, UNITY_DATA);
|
||||||
|
URL dataUrl = new URL(currentUrl + UNITY_DATA);
|
||||||
|
downloadToFile(dataUrl, dataFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyCodeFile() throws IOException, InvalidOpCodeException {
|
||||||
|
File codeFile = new File(saveFolder, UNITY_CODE);
|
||||||
|
URL codeUrl = new URL(currentUrl + UNITY_CODE);
|
||||||
|
downloadToFile(codeUrl, codeFile);
|
||||||
|
|
||||||
|
new WasmCodePatcher(codeFile.getAbsolutePath()).patch();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String insertFrameworkCode(String fileContents, int index, String codeName) throws IOException {
|
||||||
|
BufferedReader code = new BufferedReader(new InputStreamReader(UnityWebModifyer.class.getResourceAsStream(codeName), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
String firstPart = fileContents.substring(0, index);
|
||||||
|
String lastPart = fileContents.substring(index);
|
||||||
|
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
stringBuilder.append(firstPart);
|
||||||
|
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
String line;
|
||||||
|
while ((line = code.readLine()) != null) {
|
||||||
|
stringBuilder.append(line);
|
||||||
|
stringBuilder.append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
stringBuilder.append(lastPart);
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyFrameworkFile() throws IOException {
|
||||||
|
File frameworkFile = new File(saveFolder, UNITY_FRAMEWORK);
|
||||||
|
URL frameworkUrl = new URL(currentUrl + UNITY_FRAMEWORK);
|
||||||
|
downloadToFile(frameworkUrl, frameworkFile);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] encoded = Files.readAllBytes(Paths.get(frameworkFile.getAbsolutePath()));
|
||||||
|
String contents = new String(encoded, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
contents = insertFrameworkCode(contents, 0, "js_code/unity_code.js");
|
||||||
|
|
||||||
|
String exportSearch = "Module.asmLibraryArg,buffer);Module[\"asm\"]=asm;";
|
||||||
|
int exportIndex = contents.indexOf(exportSearch) + exportSearch.length();
|
||||||
|
contents = insertFrameworkCode(contents, exportIndex, "js_code/unity_exports.js");
|
||||||
|
|
||||||
|
String importSearch = "if(!env[\"tableBase\"]){env[\"tableBase\"]=0}";
|
||||||
|
int importIndex = contents.indexOf(importSearch) + importSearch.length();
|
||||||
|
contents = insertFrameworkCode(contents, importIndex, "js_code/unity_imports.js");
|
||||||
|
|
||||||
|
contents = contents
|
||||||
|
.replace("var _free", "_free")
|
||||||
|
.replace("var _malloc", "_malloc")
|
||||||
|
.replace("{{RevisionName}}", revision);
|
||||||
|
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(frameworkFile));
|
||||||
|
writer.write(contents);
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void modifyUnityLoader() throws IOException {
|
||||||
|
File loaderFile = new File(saveFolder, UNITY_LOADER);
|
||||||
|
URL loaderUrl = new URL(currentUrl + UNITY_LOADER);
|
||||||
|
downloadToFile(loaderUrl, loaderFile);
|
||||||
|
|
||||||
|
byte[] encoded = Files.readAllBytes(Paths.get(loaderFile.getAbsolutePath()));
|
||||||
|
String contents = new String(encoded, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
contents = contents.replace("o.result.responseHeaders[e]==a.getResponseHeader(e)", "false");
|
||||||
|
contents = contents.replace("i.responseHeaders[e]=o.getResponseHeader(e)",
|
||||||
|
"const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');\n" +
|
||||||
|
" if (e === \"ETag\") {\n" +
|
||||||
|
" i.responseHeaders[e] = \"W/\\\"\" + genRanHex(6) + \"-\" + genRanHex(13) + \"\\\"\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" else {\n" +
|
||||||
|
" i.responseHeaders[e] = o.getResponseHeader(e)\n" +
|
||||||
|
" }");
|
||||||
|
|
||||||
|
BufferedWriter writer = new BufferedWriter(new FileWriter(loaderFile));
|
||||||
|
writer.write(contents);
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package gearth.services.unity_tools;
|
||||||
|
|
||||||
|
import gearth.services.unity_tools.codepatcher.IncomingPacketPatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.OutgoingPacketPatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.ReturnBytePatcher;
|
||||||
|
import gearth.services.unity_tools.codepatcher.SetKeyPatcher;
|
||||||
|
import wasm.disassembly.InvalidOpCodeException;
|
||||||
|
import wasm.disassembly.modules.Module;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class WasmCodePatcher {
|
||||||
|
|
||||||
|
private String file;
|
||||||
|
|
||||||
|
public WasmCodePatcher(String file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void patch() throws IOException, InvalidOpCodeException {
|
||||||
|
Module module = new Module(file, Arrays.asList(
|
||||||
|
new SetKeyPatcher(),
|
||||||
|
new ReturnBytePatcher(),
|
||||||
|
new OutgoingPacketPatcher(),
|
||||||
|
new IncomingPacketPatcher()
|
||||||
|
));
|
||||||
|
module.assembleToFile(file);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,225 @@
|
|||||||
|
//package gearth.services.unity_tools;
|
||||||
|
//
|
||||||
|
//import wasm.disassembly.InvalidOpCodeException;
|
||||||
|
//import wasm.disassembly.instructions.Expression;
|
||||||
|
//import wasm.disassembly.instructions.Instr;
|
||||||
|
//import wasm.disassembly.instructions.InstrType;
|
||||||
|
//import wasm.disassembly.instructions.control.CallInstr;
|
||||||
|
//import wasm.disassembly.instructions.variable.LocalVariableInstr;
|
||||||
|
//import wasm.disassembly.modules.Module;
|
||||||
|
//import wasm.disassembly.modules.indices.FuncIdx;
|
||||||
|
//import wasm.disassembly.modules.indices.LocalIdx;
|
||||||
|
//import wasm.disassembly.modules.indices.TypeIdx;
|
||||||
|
//import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
//import wasm.disassembly.modules.sections.export.Export;
|
||||||
|
//import wasm.disassembly.modules.sections.export.ExportDesc;
|
||||||
|
//import wasm.disassembly.modules.sections.imprt.Import;
|
||||||
|
//import wasm.disassembly.modules.sections.imprt.ImportDesc;
|
||||||
|
//import wasm.disassembly.types.FuncType;
|
||||||
|
//import wasm.disassembly.types.ResultType;
|
||||||
|
//import wasm.disassembly.types.ValType;
|
||||||
|
//import wasm.misc.Function;
|
||||||
|
//
|
||||||
|
//import java.io.*;
|
||||||
|
//import java.util.*;
|
||||||
|
//
|
||||||
|
//public class WasmCodePatcherOld {
|
||||||
|
//
|
||||||
|
// private String file;
|
||||||
|
//
|
||||||
|
// public WasmCodePatcherOld(String file) {
|
||||||
|
// this.file = file;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void patch() throws IOException, InvalidOpCodeException {
|
||||||
|
// Module module = new Module(file);
|
||||||
|
//
|
||||||
|
// FuncIdx returnByteId = findReturnByteFunc(module);
|
||||||
|
// FuncIdx setkey = findSetKeyFunc(module);
|
||||||
|
// FuncIdx outgoingIdx = findOutFunc(module);
|
||||||
|
// FuncIdx incomingIdx = findInFunc(module);
|
||||||
|
//
|
||||||
|
// hook(module, setkey, "g_chacha_setkey");
|
||||||
|
// copyEmptyHook(module, returnByteId, "_gearth_returnbyte_copy", "g_chacha_returnbyte");
|
||||||
|
// copyEmptyHook(module, outgoingIdx, "_gearth_outgoing_copy", "g_outgoing_packet");
|
||||||
|
// copyEmptyHook(module, incomingIdx, "_gearth_incoming_copy", "g_incoming_packet");
|
||||||
|
//
|
||||||
|
// module.assembleToFile(file);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// private FuncIdx findOutFunc(Module module) {
|
||||||
|
// TypeIdx expectedTypeIdx = module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// ));
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx currentIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Func func = module.getCodeSection().getByIdx(currentIdx);
|
||||||
|
// if (func.getLocalss().size() != 0) continue;
|
||||||
|
// if (!module.getFunctionSection().getByIdx(currentIdx).equals(expectedTypeIdx)) continue;
|
||||||
|
//
|
||||||
|
// List<Instr> expression = func.getExpression().getInstructions();
|
||||||
|
//
|
||||||
|
// if (expression.size() != 6) continue;
|
||||||
|
//
|
||||||
|
// if (expression.get(0).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(1).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(2).getInstrType() != InstrType.LOCAL_GET) continue;
|
||||||
|
// if (expression.get(3).getInstrType() != InstrType.I32_LOAD) continue;
|
||||||
|
// if (expression.get(4).getInstrType() != InstrType.I32_CONST) continue;
|
||||||
|
// if (expression.get(5).getInstrType() != InstrType.CALL) continue;
|
||||||
|
//
|
||||||
|
// return currentIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findSetKeyFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
// InstrType.I32_EQZ, InstrType.IF, InstrType.BLOCK, InstrType.LOCAL_GET, InstrType.I32_CONST,
|
||||||
|
// InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.I32_CONST, InstrType.I32_CONST, InstrType.I32_CONST,
|
||||||
|
// InstrType.CALL);
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
||||||
|
//
|
||||||
|
// for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
||||||
|
// Instr instr = function.getCode().getInstructions().get(j);
|
||||||
|
// if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findReturnByteFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.singletonList(ValType.I32))
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (function.getLocalsFloored().size() != 0) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != 30) continue;
|
||||||
|
//
|
||||||
|
// List<Instr> expr = function.getCode().getInstructions();
|
||||||
|
// if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) continue;
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
// private FuncIdx findInFunc(Module module) {
|
||||||
|
// FuncType expectedType = new FuncType(
|
||||||
|
// new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
// InstrType.I32_EQZ, InstrType.IF, InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.LOCAL_TEE,
|
||||||
|
// InstrType.IF);
|
||||||
|
//
|
||||||
|
// outerloop:
|
||||||
|
// for (int i = 0; i < module.getCodeSection().getCodesEntries().size(); i++) {
|
||||||
|
// FuncIdx funcIdx = new FuncIdx(i + module.getImportSection().getTotalFuncImports(), module);
|
||||||
|
//
|
||||||
|
// Function function = new Function(module, funcIdx);
|
||||||
|
// if (!function.getFuncType().equals(expectedType)) continue;
|
||||||
|
// if (!(function.getLocalsFloored().size() == 1 && function.getLocalsFloored().get(0) == ValType.I32)) continue;
|
||||||
|
// if (function.getCode().getInstructions().size() != expectedExpr.size()) continue;
|
||||||
|
//
|
||||||
|
// for (int j = 0; j < function.getCode().getInstructions().size(); j++) {
|
||||||
|
// Instr instr = function.getCode().getInstructions().get(j);
|
||||||
|
// if (instr.getInstrType() != expectedExpr.get(j)) continue outerloop;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return funcIdx;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void copyEmptyHook(Module module, FuncIdx orgFuncIdx, String exportName, String hookname) throws InvalidOpCodeException, IOException {
|
||||||
|
// // copies the method, empties the first one
|
||||||
|
// // export the copy
|
||||||
|
// // hooks to the emptied one
|
||||||
|
//
|
||||||
|
// Func func = module.getCodeSection().getByIdx(orgFuncIdx);
|
||||||
|
// FuncType funcType = module.getTypeSection().getByFuncIdx(orgFuncIdx);
|
||||||
|
//
|
||||||
|
// // copy the function
|
||||||
|
// Function copy = new Function(funcType, func.getLocalss(), func.getExpression());
|
||||||
|
// FuncIdx copyIdx = copy.addToModule(module);
|
||||||
|
//
|
||||||
|
// module.getExportSection().getExports().add(new Export(exportName, new ExportDesc(copyIdx)));
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // clear & hook original function, let it return whatever JS returns
|
||||||
|
// Import imp = new Import(
|
||||||
|
// "env",
|
||||||
|
// hookname,
|
||||||
|
// new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// funcType.getParameterType(),
|
||||||
|
// funcType.getResultType()
|
||||||
|
// )))
|
||||||
|
// );
|
||||||
|
// FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
||||||
|
//
|
||||||
|
// CallInstr call = new CallInstr(hookIdx);
|
||||||
|
// List<Instr> newInstrs = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
||||||
|
// newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
||||||
|
// }
|
||||||
|
// newInstrs.add(call);
|
||||||
|
// func.setExpression(new Expression(newInstrs));
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private void hook(Module module, FuncIdx funcIdx, String jsFunctionName) throws InvalidOpCodeException, IOException {
|
||||||
|
// FuncType funcType = module.getTypeSection().getByFuncIdx(funcIdx);
|
||||||
|
//
|
||||||
|
// Import imp = new Import(
|
||||||
|
// "env",
|
||||||
|
// jsFunctionName,
|
||||||
|
// new ImportDesc(module.getTypeSection().getTypeIdxForFuncType(new FuncType(
|
||||||
|
// funcType.getParameterType(),
|
||||||
|
// new ResultType(Collections.emptyList())
|
||||||
|
// )))
|
||||||
|
// );
|
||||||
|
// FuncIdx hookIdx = module.getImportSection().importFunction(imp);
|
||||||
|
//
|
||||||
|
// CallInstr call = new CallInstr(hookIdx);
|
||||||
|
//
|
||||||
|
// Func root = module.getCodeSection().getByIdx(funcIdx);
|
||||||
|
// List<Instr> newInstrs = new ArrayList<>();
|
||||||
|
// for (int i = 0; i < funcType.getParameterType().typeList().size(); i++) {
|
||||||
|
// newInstrs.add(new LocalVariableInstr(InstrType.LOCAL_GET, new LocalIdx(i)));
|
||||||
|
// }
|
||||||
|
// newInstrs.add(call);
|
||||||
|
// newInstrs.addAll(root.getExpression().getInstructions());
|
||||||
|
// root.getExpression().setInstructions(newInstrs);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
@ -0,0 +1,60 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.modules.sections.code.Locals;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IncomingPacketPatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_incoming_packet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_incoming_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (!(code.getLocalss().equals(Collections.singletonList(new Locals(1, ValType.I32)))))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
InstrType.I32_EQZ, InstrType.IF, InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.LOCAL_TEE,
|
||||||
|
InstrType.IF);
|
||||||
|
|
||||||
|
if (code.getExpression().getInstructions().size() != expectedExpr.size()) return false;
|
||||||
|
|
||||||
|
for (int j = 0; j < code.getExpression().getInstructions().size(); j++) {
|
||||||
|
Instr instr = code.getExpression().getInstructions().get(j);
|
||||||
|
if (instr.getInstrType() != expectedExpr.get(j)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class OutgoingPacketPatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_outgoing_packet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_outgoing_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (code.getLocalss().size() != 0) return false;
|
||||||
|
List<Instr> expression = code.getExpression().getInstructions();
|
||||||
|
if (expression.get(0).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(1).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(2).getInstrType() != InstrType.LOCAL_GET) return false;
|
||||||
|
if (expression.get(3).getInstrType() != InstrType.I32_LOAD) return false;
|
||||||
|
if (expression.get(4).getInstrType() != InstrType.I32_CONST) return false;
|
||||||
|
if (expression.get(5).getInstrType() != InstrType.CALL) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ReturnBytePatcher implements StreamReplacement {
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.singletonList(ValType.I32)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOKCOPYEXPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_chacha_returnbyte";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return "_gearth_returnbyte_copy";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (code.getLocalss().size() != 0) return false;
|
||||||
|
if (code.getExpression().getInstructions().size() != 30) return false;
|
||||||
|
List<Instr> expr = code.getExpression().getInstructions();
|
||||||
|
if (expr.get(expr.size() - 1).getInstrType() != InstrType.I32_XOR) return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package gearth.services.unity_tools.codepatcher;
|
||||||
|
|
||||||
|
import wasm.disassembly.instructions.Instr;
|
||||||
|
import wasm.disassembly.instructions.InstrType;
|
||||||
|
import wasm.disassembly.modules.sections.code.Func;
|
||||||
|
import wasm.disassembly.modules.sections.code.Locals;
|
||||||
|
import wasm.disassembly.types.FuncType;
|
||||||
|
import wasm.disassembly.types.ResultType;
|
||||||
|
import wasm.disassembly.types.ValType;
|
||||||
|
import wasm.misc.CodeCompare;
|
||||||
|
import wasm.misc.StreamReplacement;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SetKeyPatcher implements StreamReplacement {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FuncType getFuncType() {
|
||||||
|
return new FuncType(new ResultType(Arrays.asList(ValType.I32, ValType.I32, ValType.I32, ValType.I32)),
|
||||||
|
new ResultType(Collections.emptyList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReplacementType getReplacementType() {
|
||||||
|
return ReplacementType.HOOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getImportName() {
|
||||||
|
return "g_chacha_setkey";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExportName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeCompare getCodeCompare() {
|
||||||
|
return code -> {
|
||||||
|
if (!(code.getLocalss().equals(Collections.singletonList(new Locals(1, ValType.I32)))))
|
||||||
|
return false;
|
||||||
|
List<InstrType> expectedExpr = Arrays.asList(InstrType.I32_CONST, InstrType.I32_LOAD8_S,
|
||||||
|
InstrType.I32_EQZ, InstrType.IF, InstrType.BLOCK, InstrType.LOCAL_GET, InstrType.I32_CONST,
|
||||||
|
InstrType.LOCAL_GET, InstrType.I32_LOAD, InstrType.I32_CONST, InstrType.I32_CONST, InstrType.I32_CONST,
|
||||||
|
InstrType.CALL);
|
||||||
|
|
||||||
|
if (code.getExpression().getInstructions().size() != expectedExpr.size()) return false;
|
||||||
|
|
||||||
|
for (int j = 0; j < code.getExpression().getInstructions().size(); j++) {
|
||||||
|
Instr instr = code.getExpression().getInstructions().get(j);
|
||||||
|
if (instr.getInstrType() != expectedExpr.get(j)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package gearth.ui;
|
package gearth.ui;
|
||||||
|
|
||||||
import gearth.ui.logger.loggerdisplays.PacketLoggerFactory;
|
import gearth.ui.logger.loggerdisplays.PacketLoggerFactory;
|
||||||
|
import javafx.event.Event;
|
||||||
|
import javafx.event.EventHandler;
|
||||||
import javafx.scene.control.Tab;
|
import javafx.scene.control.Tab;
|
||||||
import javafx.scene.control.TabPane;
|
import javafx.scene.control.TabPane;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
@ -44,52 +46,35 @@ public class GEarthController {
|
|||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
tabs = new ArrayList<>();
|
tabs = new ArrayList<>();
|
||||||
|
// must be ordered correctly
|
||||||
tabs.add(connectionController);
|
tabs.add(connectionController);
|
||||||
tabs.add(injectionController);
|
tabs.add(injectionController);
|
||||||
tabs.add(loggerController);
|
tabs.add(loggerController);
|
||||||
tabs.add(toolsController);
|
tabs.add(toolsController);
|
||||||
tabs.add(schedulerController);
|
tabs.add(schedulerController);
|
||||||
|
tabs.add(extensionsController);
|
||||||
tabs.add(extraController);
|
tabs.add(extraController);
|
||||||
tabs.add(infoController);
|
tabs.add(infoController);
|
||||||
tabs.add(extensionsController);
|
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
trySetController();
|
trySetController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Tab> uiTabs = tabBar.getTabs();
|
||||||
|
for (int i = 0; i < uiTabs.size(); i++) {
|
||||||
|
Tab tab = uiTabs.get(i);
|
||||||
|
int[] ii = {i};
|
||||||
|
|
||||||
|
tab.setOnSelectionChanged(event -> {
|
||||||
|
if (tab.isSelected()) {
|
||||||
|
tabs.get(ii[0]).onTabOpened();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (PacketLoggerFactory.usesUIlogger()) {
|
if (PacketLoggerFactory.usesUIlogger()) {
|
||||||
tabBar.getTabs().remove(tab_Logger);
|
tabBar.getTabs().remove(tab_Logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
//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) {
|
public void setStage(Stage stage) {
|
||||||
@ -122,5 +107,4 @@ public class GEarthController {
|
|||||||
tabs.forEach(SubForm::exit);
|
tabs.forEach(SubForm::exit);
|
||||||
hConnection.abort();
|
hConnection.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,10 @@ public class SubForm {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void onTabOpened() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
protected HConnection getHConnection() {
|
protected HConnection getHConnection() {
|
||||||
return parentController.getHConnection();
|
return parentController.getHConnection();
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,8 @@ public class BoxButton extends StackPane {
|
|||||||
|
|
||||||
//paths zijn relatief aan deze classpath
|
//paths zijn relatief aan deze classpath
|
||||||
public BoxButton(String imageName, String imageOnHoverName) {
|
public BoxButton(String imageName, String imageOnHoverName) {
|
||||||
this.image = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/" + imageName));
|
this.image = new Image(getClass().getResourceAsStream("files/" + imageName));
|
||||||
this.imageOnHover = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/" + imageOnHoverName));
|
this.imageOnHover = new Image(getClass().getResourceAsStream("files/" + imageOnHoverName));
|
||||||
this.imageView = new ImageView();
|
this.imageView = new ImageView();
|
||||||
|
|
||||||
setCursor(Cursor.DEFAULT);
|
setCursor(Cursor.DEFAULT);
|
||||||
|
@ -33,10 +33,10 @@ public class PauseResumeButton extends StackPane{
|
|||||||
public PauseResumeButton(boolean isPaused) {
|
public PauseResumeButton(boolean isPaused) {
|
||||||
this.isPaused[0] = isPaused;
|
this.isPaused[0] = isPaused;
|
||||||
|
|
||||||
this.imagePause = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/ButtonPause.png"));
|
this.imagePause = new Image(getClass().getResourceAsStream("files/ButtonPause.png"));
|
||||||
this.imagePauseOnHover = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/ButtonPauseHover.png"));
|
this.imagePauseOnHover = new Image(getClass().getResourceAsStream("files/ButtonPauseHover.png"));
|
||||||
this.imageResume = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/ButtonResume.png"));
|
this.imageResume = new Image(getClass().getResourceAsStream("files/ButtonResume.png"));
|
||||||
this.imageResumeOnHover = new Image(getClass().getResourceAsStream("/gearth/ui/buttons/files/ButtonResumeHover.png"));
|
this.imageResumeOnHover = new Image(getClass().getResourceAsStream("files/ButtonResumeHover.png"));
|
||||||
this.imageView = new ImageView();
|
this.imageView = new ImageView();
|
||||||
|
|
||||||
setCursor(Cursor.DEFAULT);
|
setCursor(Cursor.DEFAULT);
|
||||||
|
@ -98,7 +98,9 @@ public class ConnectionController extends SubForm {
|
|||||||
txtfield_hotelversion.setText(getHConnection().getHotelVersion());
|
txtfield_hotelversion.setText(getHConnection().getHotelVersion());
|
||||||
|
|
||||||
btnConnect.setDisable(getHConnection().getState() == HState.PREPARING || getHConnection().getState() == HState.ABORTING);
|
btnConnect.setDisable(getHConnection().getState() == HState.PREPARING || getHConnection().getState() == HState.ABORTING);
|
||||||
if (!cbx_autodetect.isSelected() && !btnConnect.isDisable()) {
|
|
||||||
|
|
||||||
|
if (!cbx_autodetect.isSelected() && !btnConnect.isDisable() && useFlash()) {
|
||||||
try {
|
try {
|
||||||
int i = Integer.parseInt(inpPort.getEditor().getText());
|
int i = Integer.parseInt(inpPort.getEditor().getText());
|
||||||
btnConnect.setDisable(i < 0 || i >= 256 * 256);
|
btnConnect.setDisable(i < 0 || i >= 256 * 256);
|
||||||
@ -110,6 +112,13 @@ public class ConnectionController extends SubForm {
|
|||||||
|
|
||||||
inpHost.setDisable(getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
inpHost.setDisable(getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
||||||
inpPort.setDisable(getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
inpPort.setDisable(getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
||||||
|
|
||||||
|
cbx_autodetect.setDisable(!useFlash());
|
||||||
|
outHost.setDisable(!useFlash());
|
||||||
|
outPort.setDisable(!useFlash());
|
||||||
|
|
||||||
|
inpHost.setDisable(!useFlash() || getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
||||||
|
inpPort.setDisable(!useFlash() || getHConnection().getState() != HState.NOT_CONNECTED || cbx_autodetect.isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onParentSet(){
|
public void onParentSet(){
|
||||||
@ -134,14 +143,15 @@ public class ConnectionController extends SubForm {
|
|||||||
|
|
||||||
if (newState == HState.CONNECTED) {
|
if (newState == HState.CONNECTED) {
|
||||||
lblState.setText("Connected");
|
lblState.setText("Connected");
|
||||||
outHost.setText(getHConnection().getDomain());
|
|
||||||
outPort.setText(getHConnection().getServerPort()+"");
|
|
||||||
}
|
}
|
||||||
if (newState == HState.WAITING_FOR_CLIENT) {
|
if (newState == HState.WAITING_FOR_CLIENT) {
|
||||||
lblState.setText("Waiting for connection");
|
lblState.setText("Waiting for connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newState == HState.CONNECTED) {
|
if (newState == HState.CONNECTED && useFlash()) {
|
||||||
|
outHost.setText(getHConnection().getDomain());
|
||||||
|
outPort.setText(getHConnection().getServerPort()+"");
|
||||||
|
|
||||||
JSONObject connectionSettings = new JSONObject();
|
JSONObject connectionSettings = new JSONObject();
|
||||||
connectionSettings.put(AUTODETECT_CACHE, cbx_autodetect.isSelected());
|
connectionSettings.put(AUTODETECT_CACHE, cbx_autodetect.isSelected());
|
||||||
connectionSettings.put(HOST_CACHE, inpHost.getEditor().getText());
|
connectionSettings.put(HOST_CACHE, inpHost.getEditor().getText());
|
||||||
@ -158,12 +168,19 @@ public class ConnectionController extends SubForm {
|
|||||||
|
|
||||||
btnConnect.setDisable(true);
|
btnConnect.setDisable(true);
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if (cbx_autodetect.isSelected()) {
|
if (useFlash()) {
|
||||||
getHConnection().start();
|
if (cbx_autodetect.isSelected()) {
|
||||||
|
getHConnection().start();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
getHConnection().start(inpHost.getEditor().getText(), Integer.parseInt(inpPort.getEditor().getText()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getHConnection().start(inpHost.getEditor().getText(), Integer.parseInt(inpPort.getEditor().getText()));
|
getHConnection().startUnity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (HConnection.DEBUG) System.out.println("connecting");
|
if (HConnection.DEBUG) System.out.println("connecting");
|
||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
@ -178,5 +195,12 @@ public class ConnectionController extends SubForm {
|
|||||||
protected void onExit() {
|
protected void onExit() {
|
||||||
getHConnection().abort();
|
getHConnection().abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void changeClientMode() {
|
||||||
|
updateInputUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useFlash() {
|
||||||
|
return parentController.extraController.rd_flash.isSelected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
package gearth.ui.extensions;
|
package gearth.ui.extensions;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
import gearth.services.extensionhandler.ExtensionConnectedListener;
|
import gearth.services.extensionhandler.ExtensionConnectedListener;
|
||||||
import gearth.services.extensionhandler.ExtensionHandler;
|
import gearth.services.extensionhandler.ExtensionHandler;
|
||||||
import gearth.services.extensionhandler.extensions.ExtensionListener;
|
import gearth.services.extensionhandler.extensions.ExtensionListener;
|
||||||
import gearth.services.extensionhandler.extensions.GEarthExtension;
|
import gearth.services.extensionhandler.extensions.GEarthExtension;
|
||||||
import gearth.services.extensionhandler.extensions.implementations.network.NetworkExtensionsProducer;
|
import gearth.services.extensionhandler.extensions.implementations.network.NetworkExtensionsProducer;
|
||||||
|
import gearth.services.extensionhandler.extensions.implementations.network.authentication.Authenticator;
|
||||||
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExecutionInfo;
|
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExecutionInfo;
|
||||||
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunner;
|
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunner;
|
||||||
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunnerFactory;
|
import gearth.services.extensionhandler.extensions.implementations.network.executer.ExtensionRunnerFactory;
|
||||||
|
import gearth.services.gpython.GPythonShell;
|
||||||
|
import gearth.services.gpython.OnQtConsoleLaunch;
|
||||||
import gearth.ui.SubForm;
|
import gearth.ui.SubForm;
|
||||||
import gearth.ui.extensions.logger.ExtensionLogger;
|
import gearth.ui.extensions.logger.ExtensionLogger;
|
||||||
|
import gearth.ui.extra.ExtraController;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.ScrollPane;
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.scene.control.TextField;
|
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.FileChooser;
|
import javafx.stage.FileChooser;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 06/04/18.
|
* Created by Jonas on 06/04/18.
|
||||||
@ -29,12 +35,12 @@ public class ExtensionsController extends SubForm {
|
|||||||
|
|
||||||
|
|
||||||
public Button btn_install;
|
public Button btn_install;
|
||||||
public Button btn_remove;
|
|
||||||
public TextField ext_port;
|
public TextField ext_port;
|
||||||
public VBox extensioncontainer;
|
public VBox extensioncontainer;
|
||||||
public GridPane header_ext;
|
public GridPane header_ext;
|
||||||
public ScrollPane scroller;
|
public ScrollPane scroller;
|
||||||
public Button btn_viewExtensionConsole;
|
public Button btn_viewExtensionConsole;
|
||||||
|
public Button btn_gpython;
|
||||||
|
|
||||||
private ExtensionRunner extensionRunner = null;
|
private ExtensionRunner extensionRunner = null;
|
||||||
private ExtensionHandler extensionHandler;
|
private ExtensionHandler extensionHandler;
|
||||||
@ -98,6 +104,33 @@ public class ExtensionsController extends SubForm {
|
|||||||
else {
|
else {
|
||||||
extensionLogger.hide();
|
extensionLogger.hide();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onTabOpened() {
|
||||||
|
updateGPythonStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateGPythonStatus() {
|
||||||
|
if (!pythonShellLaunching) {
|
||||||
|
btn_gpython.setDisable(!parentController.extraController.useGPython());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private volatile int gpytonShellCounter = 1;
|
||||||
|
private volatile boolean pythonShellLaunching = false;
|
||||||
|
public void gpythonBtnClicked(ActionEvent actionEvent) {
|
||||||
|
pythonShellLaunching = true;
|
||||||
|
Platform.runLater(() -> btn_gpython.setDisable(true));
|
||||||
|
GPythonShell shell = new GPythonShell(
|
||||||
|
"Scripting shell " + gpytonShellCounter++,
|
||||||
|
networkExtensionsProducer.getPort(),
|
||||||
|
Authenticator.generatePermanentCookie()
|
||||||
|
);
|
||||||
|
shell.launch((b) -> {
|
||||||
|
pythonShellLaunching = false;
|
||||||
|
Platform.runLater(this::updateGPythonStatus);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
package gearth.ui.extra;
|
package gearth.ui.extra;
|
||||||
|
|
||||||
|
import gearth.Main;
|
||||||
import gearth.misc.Cacher;
|
import gearth.misc.Cacher;
|
||||||
|
import gearth.misc.packetrepresentation.prediction.checkers.TypeCheckerProducer;
|
||||||
import gearth.protocol.HConnection;
|
import gearth.protocol.HConnection;
|
||||||
import gearth.protocol.connection.HState;
|
import gearth.protocol.connection.HState;
|
||||||
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
import gearth.protocol.connection.proxy.ProxyProviderFactory;
|
||||||
import gearth.protocol.connection.proxy.SocksConfiguration;
|
import gearth.protocol.connection.proxy.SocksConfiguration;
|
||||||
|
import gearth.services.Constants;
|
||||||
|
import gearth.services.gpython.GPythonVersionUtils;
|
||||||
import gearth.ui.SubForm;
|
import gearth.ui.SubForm;
|
||||||
import gearth.ui.info.InfoController;
|
import gearth.ui.info.InfoController;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.layout.FlowPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -16,12 +24,17 @@ import org.json.JSONObject;
|
|||||||
*/
|
*/
|
||||||
public class ExtraController extends SubForm implements SocksConfiguration {
|
public class ExtraController extends SubForm implements SocksConfiguration {
|
||||||
|
|
||||||
|
public static final String INFO_URL_GPYTHON = "https://github.com/sirjonasxx/G-Earth/wiki/G-Python-qtConsole";
|
||||||
|
|
||||||
public static final String NOTEPAD_CACHE_KEY = "notepad_text";
|
public static final String NOTEPAD_CACHE_KEY = "notepad_text";
|
||||||
public static final String SOCKS_CACHE_KEY = "socks_config";
|
public static final String SOCKS_CACHE_KEY = "socks_config";
|
||||||
|
public static final String GPYTHON_CACHE_KEY = "use_gpython";
|
||||||
|
|
||||||
|
public static final String USE_UNITY_CLIENT_CACHE_KEY = "use_unity";
|
||||||
|
|
||||||
public static final String SOCKS_IP = "ip";
|
public static final String SOCKS_IP = "ip";
|
||||||
public static final String SOCKS_PORT = "port";
|
public static final String SOCKS_PORT = "port";
|
||||||
public static final String IGNORE_ONCE = "ignore_once";
|
// public static final String IGNORE_ONCE = "ignore_once";
|
||||||
|
|
||||||
|
|
||||||
public TextArea txtarea_notepad;
|
public TextArea txtarea_notepad;
|
||||||
@ -29,20 +42,32 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
public CheckBox cbx_alwaysOnTop;
|
public CheckBox cbx_alwaysOnTop;
|
||||||
public Hyperlink url_troubleshooting;
|
public Hyperlink url_troubleshooting;
|
||||||
|
|
||||||
|
//TODO add setup link to g-earth wiki
|
||||||
|
public CheckBox cbx_gpython;
|
||||||
|
|
||||||
public CheckBox cbx_advanced;
|
public CheckBox cbx_advanced;
|
||||||
public GridPane grd_advanced;
|
public GridPane grd_advanced;
|
||||||
|
|
||||||
public CheckBox cbx_disableDecryption;
|
public CheckBox cbx_disableDecryption;
|
||||||
public CheckBox cbx_debug;
|
public CheckBox cbx_debug;
|
||||||
|
|
||||||
|
|
||||||
public CheckBox cbx_useSocks;
|
public CheckBox cbx_useSocks;
|
||||||
public GridPane grd_socksInfo;
|
public GridPane grd_socksInfo;
|
||||||
public TextField txt_socksPort;
|
public TextField txt_socksPort;
|
||||||
public TextField txt_socksIp;
|
public TextField txt_socksIp;
|
||||||
public CheckBox cbx_socksUseIfNeeded;
|
|
||||||
|
|
||||||
|
public ToggleGroup tgl_clientMode;
|
||||||
|
public RadioButton rd_unity;
|
||||||
|
public RadioButton rd_flash;
|
||||||
|
public GridPane grd_clientSelection;
|
||||||
|
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
Constants.UNITY_PACKETS = rd_unity.isSelected();
|
||||||
|
tgl_clientMode.selectedToggleProperty().addListener(observable -> {
|
||||||
|
if (parentController != null) parentController.connectionController.changeClientMode();
|
||||||
|
Constants.UNITY_PACKETS = rd_unity.isSelected();
|
||||||
|
});
|
||||||
|
|
||||||
url_troubleshooting.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting"));
|
url_troubleshooting.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting"));
|
||||||
InfoController.activateHyperlink(url_troubleshooting);
|
InfoController.activateHyperlink(url_troubleshooting);
|
||||||
@ -56,7 +81,16 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
JSONObject socksInitValue = Cacher.getCacheContents().getJSONObject(SOCKS_CACHE_KEY);
|
JSONObject socksInitValue = Cacher.getCacheContents().getJSONObject(SOCKS_CACHE_KEY);
|
||||||
txt_socksIp.setText(socksInitValue.getString(SOCKS_IP));
|
txt_socksIp.setText(socksInitValue.getString(SOCKS_IP));
|
||||||
txt_socksPort.setText(socksInitValue.getString(SOCKS_PORT));
|
txt_socksPort.setText(socksInitValue.getString(SOCKS_PORT));
|
||||||
cbx_socksUseIfNeeded.setSelected(socksInitValue.getBoolean(IGNORE_ONCE));
|
// cbx_socksUseIfNeeded.setSelected(socksInitValue.getBoolean(IGNORE_ONCE));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cacher.getCacheContents().has(GPYTHON_CACHE_KEY)) {
|
||||||
|
cbx_gpython.setSelected(Cacher.getCacheContents().getBoolean(GPYTHON_CACHE_KEY));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Cacher.getCacheContents().has(USE_UNITY_CLIENT_CACHE_KEY)) {
|
||||||
|
rd_unity.setSelected(Cacher.getCacheContents().getBoolean(USE_UNITY_CLIENT_CACHE_KEY));
|
||||||
|
rd_flash.setSelected(!Cacher.getCacheContents().getBoolean(USE_UNITY_CLIENT_CACHE_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
cbx_debug.selectedProperty().addListener(observable -> HConnection.DEBUG = cbx_debug.isSelected());
|
cbx_debug.selectedProperty().addListener(observable -> HConnection.DEBUG = cbx_debug.isSelected());
|
||||||
@ -85,6 +119,8 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
@Override
|
@Override
|
||||||
protected void onExit() {
|
protected void onExit() {
|
||||||
Cacher.put(NOTEPAD_CACHE_KEY, txtarea_notepad.getText());
|
Cacher.put(NOTEPAD_CACHE_KEY, txtarea_notepad.getText());
|
||||||
|
Cacher.put(GPYTHON_CACHE_KEY, cbx_gpython.isSelected());
|
||||||
|
Cacher.put(USE_UNITY_CLIENT_CACHE_KEY, rd_unity.isSelected());
|
||||||
saveSocksConfig();
|
saveSocksConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +128,13 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
JSONObject jsonObject = new JSONObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.put(SOCKS_IP, txt_socksIp.getText());
|
jsonObject.put(SOCKS_IP, txt_socksIp.getText());
|
||||||
jsonObject.put(SOCKS_PORT, txt_socksPort.getText());
|
jsonObject.put(SOCKS_PORT, txt_socksPort.getText());
|
||||||
jsonObject.put(IGNORE_ONCE, cbx_socksUseIfNeeded.isSelected());
|
// jsonObject.put(IGNORE_ONCE, cbx_socksUseIfNeeded.isSelected());
|
||||||
Cacher.put(SOCKS_CACHE_KEY, jsonObject);
|
Cacher.put(SOCKS_CACHE_KEY, jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAdvancedUI() {
|
private void updateAdvancedUI() {
|
||||||
|
grd_clientSelection.setDisable(getHConnection().getState() != HState.NOT_CONNECTED);
|
||||||
|
|
||||||
if (!cbx_advanced.isSelected()) {
|
if (!cbx_advanced.isSelected()) {
|
||||||
cbx_debug.setSelected(false);
|
cbx_debug.setSelected(false);
|
||||||
cbx_useSocks.setSelected(false);
|
cbx_useSocks.setSelected(false);
|
||||||
@ -127,6 +165,54 @@ public class ExtraController extends SubForm implements SocksConfiguration {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onlyUseIfNeeded() {
|
public boolean onlyUseIfNeeded() {
|
||||||
return cbx_socksUseIfNeeded.isSelected();
|
// return cbx_socksUseIfNeeded.isSelected();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean useGPython() {
|
||||||
|
return cbx_gpython.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void gpythonCbxClick(ActionEvent actionEvent) {
|
||||||
|
if (cbx_gpython.isSelected()) {
|
||||||
|
new Thread(() -> {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbx_gpython.setSelected(false);
|
||||||
|
cbx_gpython.setDisable(true);
|
||||||
|
});
|
||||||
|
if (!GPythonVersionUtils.validInstallation()) {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR, "G-Python installation", ButtonType.OK);
|
||||||
|
alert.setTitle("G-Python installation");
|
||||||
|
|
||||||
|
FlowPane fp = new FlowPane();
|
||||||
|
Label lbl = new Label("Before using G-Python, install the right packages using pip!" +
|
||||||
|
System.lineSeparator() + System.lineSeparator() + "More information here:");
|
||||||
|
Hyperlink link = new Hyperlink(INFO_URL_GPYTHON);
|
||||||
|
fp.getChildren().addAll( lbl, link);
|
||||||
|
link.setOnAction(event -> {
|
||||||
|
Main.main.getHostServices().showDocument(link.getText());
|
||||||
|
event.consume();
|
||||||
|
});
|
||||||
|
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.getDialogPane().setContent(fp);
|
||||||
|
alert.show();
|
||||||
|
|
||||||
|
cbx_gpython.setDisable(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
cbx_gpython.setSelected(true);
|
||||||
|
cbx_gpython.setDisable(false);
|
||||||
|
parentController.extensionsController.updateGPythonStatus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,27 +2,27 @@ package gearth.ui.info;
|
|||||||
|
|
||||||
import gearth.Main;
|
import gearth.Main;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.scene.control.Hyperlink;
|
import javafx.scene.control.*;
|
||||||
import gearth.ui.SubForm;
|
import gearth.ui.SubForm;
|
||||||
import javafx.scene.control.Label;
|
|
||||||
import javafx.scene.control.Tooltip;
|
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.FlowPane;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import javafx.scene.web.WebView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Jonas on 06/04/18.
|
* Created by Jonas on 06/04/18.
|
||||||
*/
|
*/
|
||||||
public class InfoController extends SubForm {
|
public class InfoController extends SubForm {
|
||||||
public ImageView img_logo;
|
public ImageView img_logo;
|
||||||
public Hyperlink link_sng;
|
public Hyperlink link_ase;
|
||||||
public Hyperlink link_darkbox;
|
public Hyperlink link_darkbox;
|
||||||
public Hyperlink link_d_harble;
|
public Hyperlink link_d_harble;
|
||||||
public Hyperlink link_g_gearth;
|
public Hyperlink link_g_gearth;
|
||||||
public Hyperlink link_g_tanji;
|
public Hyperlink link_g_tanji;
|
||||||
public Hyperlink link_d_bonnie;
|
public Hyperlink link_d_gearth;
|
||||||
public Label version;
|
|
||||||
|
|
||||||
// this is a TEMPORARY info tab
|
public Label version;
|
||||||
|
|
||||||
public static void activateHyperlink(Hyperlink link) {
|
public static void activateHyperlink(Hyperlink link) {
|
||||||
link.setOnAction((ActionEvent event) -> {
|
link.setOnAction((ActionEvent event) -> {
|
||||||
@ -38,16 +38,36 @@ public class InfoController extends SubForm {
|
|||||||
|
|
||||||
img_logo.setImage(new Image("/gearth/G-EarthLogo.png"));
|
img_logo.setImage(new Image("/gearth/G-EarthLogo.png"));
|
||||||
|
|
||||||
link_sng.setTooltip(new Tooltip("https://www.sngforum.info"));
|
link_ase.setTooltip(new Tooltip("https://allseeingeye.to"));
|
||||||
link_darkbox.setTooltip(new Tooltip("https://darkbox.nl"));
|
link_darkbox.setTooltip(new Tooltip("https://darkbox.nl"));
|
||||||
|
link_d_harble.setTooltip(new Tooltip("https://discord.gg/CzRuHvW"));
|
||||||
|
link_d_gearth.setTooltip(new Tooltip("https://discord.gg/AVkcF8y"));
|
||||||
link_g_gearth.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth"));
|
link_g_gearth.setTooltip(new Tooltip("https://github.com/sirjonasxx/G-Earth"));
|
||||||
link_g_tanji.setTooltip(new Tooltip("https://github.com/ArachisH/Tanji"));
|
link_g_tanji.setTooltip(new Tooltip("https://github.com/ArachisH/Tanji"));
|
||||||
link_d_harble.setTooltip(new Tooltip("https://discord.gg/CzRuHvW"));
|
|
||||||
|
|
||||||
|
activateHyperlink(link_ase);
|
||||||
|
activateHyperlink(link_darkbox);
|
||||||
activateHyperlink(link_d_harble);
|
activateHyperlink(link_d_harble);
|
||||||
|
activateHyperlink(link_d_gearth);
|
||||||
activateHyperlink(link_g_gearth);
|
activateHyperlink(link_g_gearth);
|
||||||
activateHyperlink(link_g_tanji);
|
activateHyperlink(link_g_tanji);
|
||||||
activateHyperlink(link_sng);
|
}
|
||||||
activateHyperlink(link_darkbox);
|
|
||||||
|
public void donate(ActionEvent actionEvent) {
|
||||||
|
String pubkey = "1GEarthEV9Ua3RcixsKTcuc1PPZd9hqri3";
|
||||||
|
|
||||||
|
Alert alert = new Alert(Alert.AlertType.INFORMATION, "Donate Bitcoins", ButtonType.OK);
|
||||||
|
alert.setHeaderText("Donate Bitcoins");
|
||||||
|
|
||||||
|
WebView webView = new WebView();
|
||||||
|
webView.getEngine().loadContent("<html>Bitcoin public address:<br><br>" +
|
||||||
|
"<textarea>" + pubkey +"</textarea>" +
|
||||||
|
"</html>");
|
||||||
|
webView.setPrefSize(200, 100);
|
||||||
|
|
||||||
|
alert.setResizable(false);
|
||||||
|
alert.getDialogPane().setMinHeight(Region.USE_PREF_SIZE);
|
||||||
|
alert.getDialogPane().setContent(webView);
|
||||||
|
alert.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,8 @@ public class InjectionController extends SubForm {
|
|||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
HPacket[] packets = parsePackets("{l}{u:3}{i:967585}{i:9589}{s:\"furni_inscriptionfuckfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\"}{s:\"sirjonasxx-II\"}{s:\"\"}{i:188}{i:0}{i:0}{b:false}");
|
HPacket[] packets = parsePackets("{l}{h:3}{i:967585}{i:9589}{s:\"furni_inscriptionfuckfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionfurni_inscriptionsssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss\"}{s:\"sirjonasxx-II\"}{s:\"\"}{i:188}{i:0}{i:0}{b:false}");
|
||||||
System.out.println(new HPacket("{l}{u:2550}{s:\"ClientPerf\"\"ormance\\\"}\"}{s:\"23\"}{s:\"fps\"}{s:\"Avatars: 1, Objects: 0\"}{i:76970180}").toExpression());
|
System.out.println(new HPacket("{l}{h:2550}{s:\"ClientPerf\"\"ormance\\\"}\"}{s:\"23\"}{s:\"fps\"}{s:\"Avatars: 1, Objects: 0\"}{i:76970180}").toExpression());
|
||||||
|
|
||||||
System.out.println("hi");
|
System.out.println("hi");
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public class UiLoggerController implements Initializable {
|
|||||||
|
|
||||||
String expr = packet.toExpression(isIncoming ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER);
|
String expr = packet.toExpression(isIncoming ? HMessage.Direction.TOCLIENT : HMessage.Direction.TOSERVER);
|
||||||
|
|
||||||
lblHarbleAPI.setText("HarbleAPI: " + (HarbleAPIFetcher.HARBLEAPI == null ? "False" : "True"));
|
lblHarbleAPI.setText("Messages: " + (HarbleAPIFetcher.HARBLEAPI == null ? "False" : "True"));
|
||||||
if ((viewMessageName || viewMessageHash) && HarbleAPIFetcher.HARBLEAPI != null) {
|
if ((viewMessageName || viewMessageHash) && HarbleAPIFetcher.HARBLEAPI != null) {
|
||||||
HarbleAPI api = HarbleAPIFetcher.HARBLEAPI;
|
HarbleAPI api = HarbleAPIFetcher.HARBLEAPI;
|
||||||
HarbleAPI.HarbleMessage message = api.getHarbleMessageFromHeaderId(
|
HarbleAPI.HarbleMessage message = api.getHarbleMessageFromHeaderId(
|
||||||
@ -124,7 +124,7 @@ public class UiLoggerController implements Initializable {
|
|||||||
.append(packet.headerId())
|
.append(packet.headerId())
|
||||||
.append(spanWithClass("]", isIncoming ? "incoming" : "outgoing"))
|
.append(spanWithClass("]", isIncoming ? "incoming" : "outgoing"))
|
||||||
.append(isIncoming ? " <- " : " -> ")
|
.append(isIncoming ? " <- " : " -> ")
|
||||||
.append(skiphugepackets && packet.length() > 8000 ?
|
.append(skiphugepackets && packet.length() > 4000 ?
|
||||||
divWithClass("<packet skipped>", "skipped") :
|
divWithClass("<packet skipped>", "skipped") :
|
||||||
divWithClass(packet.toString(), isIncoming ? "incoming" : "outgoing"));
|
divWithClass(packet.toString(), isIncoming ? "incoming" : "outgoing"));
|
||||||
|
|
||||||
|
1109
G-Earth/src/main/resources/build/messages.json
Normal file
1109
G-Earth/src/main/resources/build/messages.json
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -0,0 +1,42 @@
|
|||||||
|
from time import sleep
|
||||||
|
|
||||||
|
from g_python.gextension import Extension
|
||||||
|
from g_python.hmessage import Direction, HMessage
|
||||||
|
from g_python.hpacket import HPacket
|
||||||
|
from g_python import hparsers
|
||||||
|
from g_python import htools
|
||||||
|
|
||||||
|
extension_info = {"title": "$G_PYTHON_SHELL_TITLE$", "description": "G-Python scripting console", "version": "1.0", "author": ""}
|
||||||
|
|
||||||
|
ext = Extension(extension_info, ["--port", "$G_EARTH_PORT$", "--auth-token", "$COOKIE$"], {"can_leave": False})
|
||||||
|
ext.start()
|
||||||
|
|
||||||
|
|
||||||
|
def is_closed(): return ext.is_closed()
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_client(packet): return ext.send_to_client(packet)
|
||||||
|
|
||||||
|
|
||||||
|
def send_to_server(packet): return ext.send_to_server(packet)
|
||||||
|
|
||||||
|
|
||||||
|
def on_event(event_name: str, func): return ext.on_event(event_name, func)
|
||||||
|
|
||||||
|
|
||||||
|
def intercept(direction: Direction, callback, id=-1): return ext.intercept(direction, callback, id)
|
||||||
|
|
||||||
|
|
||||||
|
def start(): return ext.start()
|
||||||
|
|
||||||
|
|
||||||
|
def stop(): return ext.stop()
|
||||||
|
|
||||||
|
|
||||||
|
def write_to_console(text, color='black', mention_title=True): return ext.write_to_console(text, color, mention_title)
|
||||||
|
|
||||||
|
|
||||||
|
def request_flags(): return ext.request_flags()
|
||||||
|
|
||||||
|
|
||||||
|
HPacket.default_extension = ext
|
@ -0,0 +1,214 @@
|
|||||||
|
let gearth_isconnected = false;
|
||||||
|
|
||||||
|
let revision = "{{RevisionName}}";
|
||||||
|
let g_ws;
|
||||||
|
|
||||||
|
|
||||||
|
let chachas = [];
|
||||||
|
let chachaClass = -1;
|
||||||
|
|
||||||
|
let out_send_param1 = -1;
|
||||||
|
let out_send_param3 = -1;
|
||||||
|
let out_packet_objid = new Uint8Array(4);
|
||||||
|
|
||||||
|
let in_recv_param1 = -1;
|
||||||
|
let in_packet_prefix = new Uint8Array(16);
|
||||||
|
|
||||||
|
let _gearth_returnbyte_copy;
|
||||||
|
let _gearth_outgoing_copy;
|
||||||
|
let _gearth_incoming_copy;
|
||||||
|
|
||||||
|
let _malloc;
|
||||||
|
let _free;
|
||||||
|
|
||||||
|
|
||||||
|
var packetBuff = {"out": [], "in": []};
|
||||||
|
|
||||||
|
function readLittleEndian(arr) {
|
||||||
|
return arr[0] + arr[1] * 256 + arr[2] * 65536 + arr[3] * 16777216;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readBigEndian(arr) {
|
||||||
|
return arr[3] + arr[2] * 256 + arr[1] * 65536 + arr[0] * 16777216;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeLittleEndian(n) {
|
||||||
|
let arr = new Uint8Array(4);
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let rest = n % 256;
|
||||||
|
arr[i] = rest;
|
||||||
|
n -= rest;
|
||||||
|
n /= 256;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeBigEndian(n) {
|
||||||
|
let arr = new Uint8Array(4);
|
||||||
|
for (let i = 0; i < 4; i++) {
|
||||||
|
let rest = n % 256;
|
||||||
|
arr[3 - i] = rest;
|
||||||
|
n -= rest;
|
||||||
|
n /= 256;
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function packetToString(packet) {
|
||||||
|
let chars = [];
|
||||||
|
let textDecode = new TextDecoder('latin1');
|
||||||
|
for (let i = 0; i < packet.length; i++) {
|
||||||
|
let byte = packet[i];
|
||||||
|
if (byte < 32 || (byte > 127 && byte < 160) || byte === 93 || byte === 91 || byte === 125 || byte === 127) {
|
||||||
|
chars.push("["+byte+"]");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chars.push(textDecode.decode(packet.slice(i, i+1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chars.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function printPacket(type, packet) {
|
||||||
|
packet = new Uint8Array(packet);
|
||||||
|
if (packet.length > 2000) {
|
||||||
|
console.log("[" + type + " capture]" + " -> skipped");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("[" + type + " capture]" + " -> " + packetToString(packet));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let _g_packet_split = 600;
|
||||||
|
|
||||||
|
function inject_out(packet) {
|
||||||
|
|
||||||
|
if (chachas.length > 1) {
|
||||||
|
packet[5] = _gearth_returnbyte_copy(chachas[0], packet[5], chachaClass);
|
||||||
|
packet[4] = _gearth_returnbyte_copy(chachas[0], packet[4], chachaClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
while (i < packet.length) {
|
||||||
|
let inject_amount = Math.min(_g_packet_split, packet.length - i);
|
||||||
|
|
||||||
|
let packet_location = _malloc(inject_amount + 16);
|
||||||
|
unityInstance.Module.HEAPU8.set(out_packet_objid, packet_location);
|
||||||
|
unityInstance.Module.HEAPU8.fill(0, packet_location + 4, packet_location + 12);
|
||||||
|
unityInstance.Module.HEAPU8.set(writeLittleEndian(inject_amount), packet_location + 12);
|
||||||
|
unityInstance.Module.HEAPU8.set(packet.slice(i, i + inject_amount), packet_location + 16);
|
||||||
|
|
||||||
|
_gearth_outgoing_copy(out_send_param1, packet_location, out_send_param3);
|
||||||
|
_free(packet_location);
|
||||||
|
|
||||||
|
i += inject_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_out(packet) {
|
||||||
|
if (gearth_isconnected) {
|
||||||
|
let g_message = new Uint8Array(packet.length + 1);
|
||||||
|
g_message[0] = 1; // toserver
|
||||||
|
g_message.set(new Uint8Array(packet), 1);
|
||||||
|
g_ws.send(g_message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inject_out(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inject_in(packet) {
|
||||||
|
let i = 0;
|
||||||
|
while (i < packet.length) {
|
||||||
|
let inject_amount = Math.min(_g_packet_split, packet.length - i);
|
||||||
|
|
||||||
|
let packet_location = _malloc(inject_amount + 16);
|
||||||
|
unityInstance.Module.HEAPU8.set(in_packet_prefix, packet_location);
|
||||||
|
unityInstance.Module.HEAPU8.set(packet.slice(i, i + inject_amount), packet_location + 16);
|
||||||
|
|
||||||
|
_gearth_incoming_copy(in_recv_param1, packet_location, 0, inject_amount, 0);
|
||||||
|
_free(packet_location);
|
||||||
|
|
||||||
|
i += inject_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_in(packet) {
|
||||||
|
if (gearth_isconnected) {
|
||||||
|
let g_message = new Uint8Array(packet.length + 1);
|
||||||
|
g_message[0] = 0; // toclient
|
||||||
|
g_message.set(new Uint8Array(packet), 1);
|
||||||
|
g_ws.send(g_message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inject_in(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function collect_packets(type) {
|
||||||
|
let finishedPackets = [];
|
||||||
|
|
||||||
|
while (packetBuff[type].length >= 6 && readBigEndian(packetBuff[type].slice(0, 4)) + 4 <= packetBuff[type].length) {
|
||||||
|
let packetLength = readBigEndian(packetBuff[type].slice(0, 4)) + 4;
|
||||||
|
let packet = packetBuff[type].slice(0, packetLength);
|
||||||
|
finishedPackets.push(packet);
|
||||||
|
packetBuff[type] = packetBuff[type].slice(packetLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return finishedPackets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let onOpen = function() {
|
||||||
|
g_ws.send(new TextEncoder('latin1').encode(revision));
|
||||||
|
gearth_isconnected = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
let onClose = function() {
|
||||||
|
gearth_isconnected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let onMessage = function(message) {
|
||||||
|
let buffer = new Uint8Array(message.data);
|
||||||
|
|
||||||
|
if (buffer[0] === 0) {
|
||||||
|
inject_in([].slice.call(buffer.slice(1)));
|
||||||
|
}
|
||||||
|
else if (buffer[0] === 1) {
|
||||||
|
inject_out([].slice.call(buffer.slice(1)));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
gearth_isconnected = false;
|
||||||
|
g_ws.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let onError = function(event) {
|
||||||
|
gearth_isconnected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
let portRequester = new WebSocket("ws://localhost:9039/ws/portrequest");
|
||||||
|
portRequester.onmessage = function(message) {
|
||||||
|
let port = message.data.split(" ")[1];
|
||||||
|
|
||||||
|
let _g_packet_url = "ws://localhost:" + port + "/ws/packethandler";
|
||||||
|
g_ws = new WebSocket(_g_packet_url);
|
||||||
|
g_ws.binaryType = "arraybuffer";
|
||||||
|
|
||||||
|
g_ws.onopen = onOpen;
|
||||||
|
g_ws.onclose = onClose;
|
||||||
|
g_ws.onmessage = onMessage;
|
||||||
|
g_ws.onerror = onError;
|
||||||
|
|
||||||
|
portRequester.close();
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
_gearth_returnbyte_copy = Module["_gearth_returnbyte_copy"] = (function() {
|
||||||
|
return Module["asm"]["_gearth_returnbyte_copy"].apply(null, arguments)
|
||||||
|
});
|
||||||
|
|
||||||
|
_gearth_outgoing_copy = Module["_gearth_outgoing_copy"] = (function() {
|
||||||
|
return Module["asm"]["_gearth_outgoing_copy"].apply(null, arguments)
|
||||||
|
});
|
||||||
|
|
||||||
|
_gearth_incoming_copy = Module["_gearth_incoming_copy"] = (function() {
|
||||||
|
return Module["asm"]["_gearth_incoming_copy"].apply(null, arguments)
|
||||||
|
});
|
@ -0,0 +1,49 @@
|
|||||||
|
function g_outgoing_packet(param1, param2, param3) {
|
||||||
|
out_send_param1 = param1;
|
||||||
|
out_send_param3 = param3;
|
||||||
|
out_packet_objid = unityInstance.Module.HEAPU8.slice(param2, param2 + 4);
|
||||||
|
|
||||||
|
let length = readLittleEndian(unityInstance.Module.HEAPU8.subarray(param2 + 12, param2 + 12 + 4));
|
||||||
|
let array = [].slice.call(unityInstance.Module.HEAPU8.subarray(param2 + 12 + 4, param2 + 12 + 4 + length));
|
||||||
|
|
||||||
|
packetBuff["out"] = packetBuff["out"].concat(array);
|
||||||
|
|
||||||
|
for (let packet of collect_packets("out")) {
|
||||||
|
handle_out(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function g_incoming_packet(param1, param2, param3, param4, param5) {
|
||||||
|
in_recv_param1 = param1;
|
||||||
|
in_packet_prefix = unityInstance.Module.HEAPU8.slice(param2, param2 + 16);
|
||||||
|
|
||||||
|
let buffer = unityInstance.Module.HEAPU8.slice(param2 + 16, param2 + 16 + param4);
|
||||||
|
packetBuff["in"] = packetBuff["in"].concat([].slice.call(buffer));
|
||||||
|
|
||||||
|
let packets = collect_packets("in");
|
||||||
|
for (let packet of packets) {
|
||||||
|
if (chachas.length > 1) {
|
||||||
|
packet[5] = _gearth_returnbyte_copy(chachas[1], packet[5], chachaClass);
|
||||||
|
packet[4] = _gearth_returnbyte_copy(chachas[1], packet[4], chachaClass);
|
||||||
|
}
|
||||||
|
handle_in(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function g_chacha_setkey(param1, param2, param3, param4) {
|
||||||
|
if (chachas.length === 2) {
|
||||||
|
chachas = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
chachas.push(param1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function g_chacha_returnbyte(param1, param2, param3) {
|
||||||
|
chachaClass = param3;
|
||||||
|
return param2;
|
||||||
|
}
|
||||||
|
|
||||||
|
env["g_outgoing_packet"] = g_outgoing_packet;
|
||||||
|
env["g_incoming_packet"] = g_incoming_packet;
|
||||||
|
env["g_chacha_setkey"] = g_chacha_setkey;
|
||||||
|
env["g_chacha_returnbyte"] = g_chacha_returnbyte;
|
@ -11,7 +11,7 @@
|
|||||||
fx:controller="gearth.ui.GEarthController">
|
fx:controller="gearth.ui.GEarthController">
|
||||||
<Pane fx:id="mover" maxHeight="0.0" minHeight="0.0" prefWidth="200.0"/>
|
<Pane fx:id="mover" maxHeight="0.0" minHeight="0.0" prefWidth="200.0"/>
|
||||||
<TabPane fx:id="tabBar" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity"
|
<TabPane fx:id="tabBar" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity"
|
||||||
minWidth="-Infinity" prefHeight="295.0" prefWidth="565.0" tabClosingPolicy="UNAVAILABLE">
|
minWidth="-Infinity" prefHeight="295.0" prefWidth="650.0" tabClosingPolicy="UNAVAILABLE">
|
||||||
<Tab text="Connection">
|
<Tab text="Connection">
|
||||||
<fx:include fx:id="connection" source="connection/Connection.fxml"/>
|
<fx:include fx:id="connection" source="connection/Connection.fxml"/>
|
||||||
</Tab>
|
</Tab>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?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" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.connection.ConnectionController">
|
<GridPane alignment="CENTER" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.connection.ConnectionController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extensions.ExtensionsController">
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extensions.ExtensionsController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="277.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="277.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
@ -19,11 +19,11 @@
|
|||||||
<VBox fx:id="extensioncontainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
|
<VBox fx:id="extensioncontainer" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308">
|
||||||
<GridPane fx:id="header_ext" gridLinesVisible="true">
|
<GridPane fx:id="header_ext" gridLinesVisible="true">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="163.0" minWidth="10.0" percentWidth="22.0" prefWidth="57.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="22.0" prefWidth="132.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="190.0" minWidth="10.0" percentWidth="34.0" prefWidth="189.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="34.0" prefWidth="204.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="118.0" minWidth="10.0" percentWidth="18.0" prefWidth="66.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="18.0" prefWidth="108.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="100.0" minWidth="10.0" percentWidth="13.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="13.0" prefWidth="78.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="100.0" minWidth="10.0" percentWidth="11.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="11.0" prefWidth="66.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
@ -52,14 +52,16 @@
|
|||||||
<GridPane hgap="7.0">
|
<GridPane hgap="7.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="49.0" minWidth="49.0" prefWidth="49.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="49.0" minWidth="49.0" prefWidth="49.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="101.0" minWidth="101.0" prefWidth="101.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="90.0" minWidth="90.0" prefWidth="90.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="0.0" prefWidth="247.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="0.0" prefWidth="247.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="140.0" minWidth="140.0" prefWidth="140.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="130.0" prefWidth="130.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="140.0" minWidth="140.0" prefWidth="140.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="130.0" prefWidth="130.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="130.0" minWidth="130.0" prefWidth="130.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
|
<Button fx:id="btn_gpython" disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#gpythonBtnClicked" text="G-Python shell" GridPane.columnIndex="3" />
|
||||||
<TextField fx:id="ext_port" editable="false" prefHeight="26.0" prefWidth="157.0" GridPane.columnIndex="1">
|
<TextField fx:id="ext_port" editable="false" prefHeight="26.0" prefWidth="157.0" GridPane.columnIndex="1">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="-7.0" />
|
<Insets left="-7.0" />
|
||||||
@ -70,8 +72,8 @@
|
|||||||
<Insets left="3.0" />
|
<Insets left="3.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<Button fx:id="btn_install" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#installBtnClicked" text="Install" GridPane.columnIndex="4" />
|
<Button fx:id="btn_install" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#installBtnClicked" text="Install" GridPane.columnIndex="5" />
|
||||||
<Button fx:id="btn_viewExtensionConsole" layoutX="401.0" layoutY="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#extConsoleBtnClicked" text="View logs" GridPane.columnIndex="3" />
|
<Button fx:id="btn_viewExtensionConsole" layoutX="401.0" layoutY="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#extConsoleBtnClicked" text="View logs" GridPane.columnIndex="4" />
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<?import javafx.geometry.*?>
|
<?import javafx.geometry.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<BorderPane fx:id="borderPane" prefHeight="230.0" prefWidth="394.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extensions.logger.ExtensionLoggerController">
|
<BorderPane fx:id="borderPane" prefHeight="230.0" prefWidth="394.0" style="-fx-background-color: white;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extensions.logger.ExtensionLoggerController">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="1.0" left="5.0" right="1.0" top="5.0" />
|
<Insets bottom="1.0" left="5.0" right="1.0" top="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extra.ExtraController">
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.extra.ExtraController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="331.0" minWidth="10.0" prefWidth="318.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="331.0" minWidth="10.0" prefWidth="318.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="10.0" prefWidth="247.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="390.0" minWidth="10.0" prefWidth="247.0" />
|
||||||
@ -26,38 +26,39 @@
|
|||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="125.0" minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="7.0" minHeight="7.0" prefHeight="7.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="235.0" minHeight="10.0" prefHeight="232.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="34.0" minHeight="34.0" prefHeight="34.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="28.0" minHeight="28.0" prefHeight="28.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints maxHeight="1.7976931348623157E308" minHeight="10.0" prefHeight="232.0" vgrow="SOMETIMES" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<GridPane fx:id="grd_advanced" disable="true" style="-fx-border-color: #888888; -fx-border-radius: 5px;" GridPane.rowIndex="1">
|
<GridPane fx:id="grd_advanced" disable="true" prefHeight="161.0" prefWidth="299.0" style="-fx-border-color: #888888; -fx-border-radius: 5px;" GridPane.rowIndex="4">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="28.0" minHeight="28.0" prefHeight="28.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="119.0" minHeight="58.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="119.0" minHeight="6.0" prefHeight="15.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="28.0" minHeight="28.0" prefHeight="28.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="28.0" minHeight="28.0" prefHeight="28.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets bottom="12.0" left="10.0" right="10.0" />
|
<Insets bottom="5.0" left="10.0" right="10.0" top="6.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="4.0" left="7.0" top="7.0" />
|
<Insets left="7.0" top="3.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<children>
|
<children>
|
||||||
<CheckBox fx:id="cbx_useSocks" mnemonicParsing="false" text="Use SOCKS proxy" />
|
<CheckBox fx:id="cbx_useSocks" mnemonicParsing="false" text="Use SOCKS proxy" />
|
||||||
<CheckBox fx:id="cbx_disableDecryption" mnemonicParsing="false" text="Disable decryption" GridPane.rowIndex="3" />
|
<CheckBox fx:id="cbx_disableDecryption" mnemonicParsing="false" text="Disable decryption" GridPane.rowIndex="2" />
|
||||||
<CheckBox fx:id="cbx_debug" mnemonicParsing="false" text="Debug to stdout" GridPane.rowIndex="4" />
|
<CheckBox fx:id="cbx_debug" mnemonicParsing="false" text="Debug to stdout" GridPane.rowIndex="3" />
|
||||||
<GridPane fx:id="grd_socksInfo" disable="true" prefHeight="54.0" prefWidth="81.0" GridPane.rowIndex="1">
|
<GridPane fx:id="grd_socksInfo" disable="true" prefHeight="54.0" prefWidth="81.0" GridPane.rowIndex="1">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
|
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="60.0" vgrow="SOMETIMES" />
|
||||||
<RowConstraints maxHeight="30.0" minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets />
|
<Insets />
|
||||||
@ -66,7 +67,6 @@
|
|||||||
<Insets left="5.0" />
|
<Insets left="5.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<children>
|
<children>
|
||||||
<CheckBox fx:id="cbx_socksUseIfNeeded" mnemonicParsing="false" selected="true" text="Only use if needed" GridPane.rowIndex="1" />
|
|
||||||
<GridPane prefHeight="119.0" prefWidth="259.0">
|
<GridPane prefHeight="119.0" prefWidth="259.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="159.0" minWidth="10.0" prefWidth="68.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="159.0" minWidth="10.0" prefWidth="68.0" />
|
||||||
@ -104,12 +104,50 @@
|
|||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
<CheckBox fx:id="cbx_advanced" mnemonicParsing="false" text="Advanced" textFill="#000000ba">
|
<CheckBox fx:id="cbx_advanced" mnemonicParsing="false" text="Advanced" textFill="#000000ba" GridPane.rowIndex="3">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="10.0" top="2.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets top="2.0" />
|
||||||
|
</padding>
|
||||||
|
</CheckBox>
|
||||||
|
<CheckBox fx:id="cbx_gpython" mnemonicParsing="false" onAction="#gpythonCbxClick" text="Enable G-Python scripting" textFill="#000000ba" GridPane.rowIndex="2">
|
||||||
<GridPane.margin>
|
<GridPane.margin>
|
||||||
<Insets left="10.0" top="2.0" />
|
<Insets left="10.0" top="2.0" />
|
||||||
</GridPane.margin>
|
</GridPane.margin>
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
<GridPane fx:id="grd_clientSelection" prefHeight="26.0" prefWidth="286.0" style="-fx-border-color: #888888; -fx-border-radius: 5px;" GridPane.rowIndex="1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="149.0" minWidth="10.0" prefWidth="38.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="81.0" minWidth="69.0" prefWidth="75.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="83.0" minWidth="66.0" prefWidth="72.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="82.0" minWidth="61.0" prefWidth="65.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="242.0" minWidth="10.0" prefWidth="47.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="20.0" prefHeight="34.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<RadioButton fx:id="rd_unity" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" selected="true" text="Unity" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS">
|
||||||
|
<toggleGroup>
|
||||||
|
<ToggleGroup fx:id="tgl_clientMode" />
|
||||||
|
</toggleGroup>
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton fx:id="rd_flash" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Flash" toggleGroup="$tgl_clientMode" GridPane.columnIndex="2" />
|
||||||
|
<RadioButton disable="true" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Anime" GridPane.columnIndex="3" />
|
||||||
|
</children>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="10.0" right="10.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="8.0" top="8.0" />
|
||||||
|
</padding>
|
||||||
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</GridPane.margin>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
<?import javafx.scene.text.*?>
|
<?import javafx.scene.text.*?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="595.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.info.InfoController">
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.info.InfoController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="332.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="332.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
@ -20,61 +20,63 @@
|
|||||||
<Font size="18.0" />
|
<Font size="18.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="260.0" layoutY="50.0" text="Habbo packet manipulator for Linux, Windows & Mac" textFill="#000000b2">
|
<Label layoutX="260.0" layoutY="57.0" text="Habbo packet manipulator for Linux, Windows & Mac" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="260.0" layoutY="87.0" text="Made by:" textFill="#000000b2">
|
<Label layoutX="260.0" layoutY="94.0" text="Made by:" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="14.0" />
|
<Font name="System Bold" size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="260.0" layoutY="107.0" text="sirjonasxx" textFill="#000000b2">
|
<Label layoutX="260.0" layoutY="114.0" text="sirjonasxx" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="87.0" text="Contributors:" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="94.0" text="Contributors:" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="14.0" />
|
<Font name="System Bold" size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="107.0" text="XePeleato" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="114.0" text="XePeleato" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="127.0" text="Scott Stamp" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="134.0" text="Scott Stamp" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="147.0" text="LittleJ" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="154.0" text="LittleJ" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="167.0" text="ArachisH" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="174.0" text="ArachisH" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="363.0" layoutY="187.0" text="BurakDev" textFill="#000000b2">
|
<Label layoutX="363.0" layoutY="194.0" text="BurakDev" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font size="14.0" />
|
<Font size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label layoutX="487.0" layoutY="87.0" text="Links:" textFill="#000000b2">
|
<Label layoutX="491.0" layoutY="94.0" text="Links:" textFill="#000000b2">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="14.0" />
|
<Font name="System Bold" size="14.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Hyperlink fx:id="link_sng" layoutX="487.0" layoutY="107.0" text="SNG Forum" />
|
<Hyperlink fx:id="link_ase" layoutX="487.0" layoutY="114.0" text="AllSeeingEye" />
|
||||||
<Hyperlink fx:id="link_darkbox" layoutX="487.0" layoutY="127.0" text="Darkbox" />
|
<Hyperlink fx:id="link_darkbox" layoutX="487.0" layoutY="134.0" text="Darkbox" />
|
||||||
<Hyperlink fx:id="link_d_harble" layoutX="487.0" layoutY="187.0" text="Discord - Harble" />
|
<Hyperlink fx:id="link_d_gearth" layoutX="487.0" layoutY="194.0" text="Discord - G-Earth" />
|
||||||
<Hyperlink fx:id="link_g_gearth" layoutX="487.0" layoutY="147.0" text="Github - G-Earth" />
|
<Hyperlink fx:id="link_d_harble" layoutX="487.0" layoutY="214.0" text="Discord - Harble" />
|
||||||
<Hyperlink fx:id="link_g_tanji" layoutX="487.0" layoutY="167.0" text="Github - Tanji" />
|
<Hyperlink fx:id="link_g_gearth" layoutX="487.0" layoutY="154.0" text="Github - G-Earth" />
|
||||||
|
<Hyperlink fx:id="link_g_tanji" layoutX="487.0" layoutY="174.0" text="Github - Tanji" />
|
||||||
|
<Button layoutX="537.0" layoutY="14.0" mnemonicParsing="false" onAction="#donate" prefHeight="20.0" prefWidth="100.0" text="Donate BTC" />
|
||||||
<!--<Hyperlink fx:id="link_d_bonnie" layoutX="400.0" layoutY="221.0" text="Discord - BonnieScripting (pt/br)" />-->
|
<!--<Hyperlink fx:id="link_d_bonnie" layoutX="400.0" layoutY="221.0" text="Discord - BonnieScripting (pt/br)" />-->
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<?import javafx.scene.text.Text?>
|
<?import javafx.scene.text.Text?>
|
||||||
|
|
||||||
<?import javafx.scene.text.TextFlow?>
|
<?import javafx.scene.text.TextFlow?>
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0"
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0"
|
||||||
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="gearth.ui.injection.InjectionController">
|
fx:controller="gearth.ui.injection.InjectionController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.TextFlow?>
|
<?import javafx.scene.text.TextFlow?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0"
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0"
|
||||||
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="gearth.ui.logger.LoggerController">
|
fx:controller="gearth.ui.logger.LoggerController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
<Insets right="10.0" />
|
<Insets right="10.0" />
|
||||||
</FlowPane.margin>
|
</FlowPane.margin>
|
||||||
</Label>
|
</Label>
|
||||||
<Label fx:id="lblHarbleAPI" layoutX="283.0" layoutY="11.0" style="-fx-text-fill: black !important" text="HarbleAPI: False">
|
<Label fx:id="lblHarbleAPI" layoutX="283.0" layoutY="11.0" style="-fx-text-fill: black !important" text="Messages: False">
|
||||||
<FlowPane.margin>
|
<FlowPane.margin>
|
||||||
<Insets right="10.0" />
|
<Insets right="10.0" />
|
||||||
</FlowPane.margin>
|
</FlowPane.margin>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="595.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.scheduler.SchedulerController">
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1" fx:controller="gearth.ui.scheduler.SchedulerController">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="277.0" />
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" prefWidth="277.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<?import javafx.scene.layout.RowConstraints?>
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="262.0" prefWidth="565.0"
|
<GridPane maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" prefHeight="258.0" prefWidth="650.0"
|
||||||
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="gearth.ui.tools.ToolsController">
|
fx:controller="gearth.ui.tools.ToolsController">
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
|
19
README.md
19
README.md
@ -3,25 +3,25 @@ Habbo packet logger & manipulator for Windows, Linux and Mac.
|
|||||||
|
|
||||||
- Requires Java 8
|
- Requires Java 8
|
||||||
|
|
||||||
FOR TROUBLESHOOTING, GO TO https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting
|
[CLICK HERE FOR TROUBLESHOOTING](https://github.com/sirjonasxx/G-Earth/wiki/Troubleshooting)
|
||||||
|
|
||||||
Join the G-Earth Discord server: https://discord.gg/AVkcF8y
|
Join the G-Earth [Discord server](https://discord.gg/AVkcF8y)
|
||||||
|
|
||||||
# Windows execution
|
# Windows execution
|
||||||
Double click G-Earth.exe, which will be delivered in the release. Note that executing G-Earth requires admin privileges.
|
Double click G-Earth.exe, which will be delivered in the release. Note that executing G-Earth requires admin privileges.
|
||||||
|
|
||||||
# Linux execution
|
# Linux execution
|
||||||
Execution command (temporary, verified in Ubuntu):
|
Execution command:
|
||||||
> $ sudo java -jar G-Earth.jar
|
> $ sudo java -jar G-Earth.jar
|
||||||
|
|
||||||
Additionally, you can add the -t flag to log the packets in your terminal instead of opening a new window for it.
|
Additionally, you can add the -t flag to log the packets in your terminal instead of opening a new window for it.
|
||||||
|
|
||||||
# Mac execution
|
# Mac execution
|
||||||
https://github.com/sirjonasxx/G-Earth/wiki/macOs-Installation-guide
|
[MacOs Installation guide](https://github.com/sirjonasxx/G-Earth/wiki/macOs-Installation-guide)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
* Log outgoing and incoming packets
|
* Log outgoing and incoming packets
|
||||||
* Injection, both sides
|
* Injection, both directions
|
||||||
* Blocking & replacing packets functionality
|
* Blocking & replacing packets functionality
|
||||||
* Packet expressions
|
* Packet expressions
|
||||||
* Encoding/decoding
|
* Encoding/decoding
|
||||||
@ -29,10 +29,13 @@ https://github.com/sirjonasxx/G-Earth/wiki/macOs-Installation-guide
|
|||||||
* Retro support - enter game host & port manually (only the first time)
|
* Retro support - enter game host & port manually (only the first time)
|
||||||
* Advanced scheduler
|
* Advanced scheduler
|
||||||
* Advanced extension support
|
* Advanced extension support
|
||||||
|
* Python scripting on the fly
|
||||||
|
* SOCKS proxy
|
||||||
* 2 included extensions on-release
|
* 2 included extensions on-release
|
||||||
|
|
||||||
Interested in creating an extension?
|
Interested in creating an extension?
|
||||||
* If you're not experienced with Java but have written extensions before in C#, you could have a look at https://github.com/ArachisH/Geode
|
* If you're not experienced with Java but have written extensions before in C#, you could have a look at [Geode](https://github.com/ArachisH/Geode).
|
||||||
* If you are experienced with Java, read this wiki page carefully: https://github.com/sirjonasxx/G-Earth/wiki/Extensions
|
* If you are experienced with Java, read this [wiki page](https://github.com/sirjonasxx/G-Earth/wiki/Extensions) carefully.
|
||||||
|
* The easiest way to create extensions is using [G-Python](https://github.com/sirjonasxx/G-Python). (can also be done inside G-Earth with a [live scripting console](https://github.com/sirjonasxx/G-Earth/wiki/G-Python-qtConsole))
|
||||||
|
|
||||||
For the memorysearcher that extracts the RC4 table, go to https://github.com/sirjonasxx/G-Mem
|
For the memorysearcher that extracts the RC4 table, go to [G-Mem](https://github.com/sirjonasxx/G-Mem).
|
||||||
|
2
pom.xml
2
pom.xml
@ -7,7 +7,7 @@
|
|||||||
<groupId>G-Earth</groupId>
|
<groupId>G-Earth</groupId>
|
||||||
<artifactId>G-Earth-Parent</artifactId>
|
<artifactId>G-Earth-Parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>1.1</version>
|
<version>1.3</version>
|
||||||
|
|
||||||
<name>G-Earth-Parent</name>
|
<name>G-Earth-Parent</name>
|
||||||
<url>https://github.com/sirjonasxx/G-Earth</url>
|
<url>https://github.com/sirjonasxx/G-Earth</url>
|
||||||
|
Loading…
Reference in New Issue
Block a user