unity local fileserver

This commit is contained in:
sirjonasxx 2020-12-27 21:32:40 +01:00
parent 1ad3a52c33
commit a29b620579
4 changed files with 327 additions and 8 deletions

View File

@ -1,4 +0,0 @@
package gearth.services.g_chrome_tools;
public class UnityFileServer {
}

View File

@ -1,4 +0,0 @@
package gearth.services.g_chrome_tools;
public class UnitywebModifyer {
}

View File

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

View File

@ -0,0 +1,177 @@
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);
WasmCodePatcher patcher = new WasmCodePatcher(codeFile.getAbsolutePath());
patcher.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();
}
}