mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 04:11:13 +00:00
Open loaded SWFs during playback feature
This commit is contained in:
@@ -24,5 +24,9 @@ public interface DebugListener {
|
||||
|
||||
public void onMessage(String clientId, String msg);
|
||||
|
||||
public void onLoaderURL(String clientId, String url);
|
||||
|
||||
public void onLoaderBytes(String clientId, byte data[]);
|
||||
|
||||
public void onFinish(String clientId);
|
||||
}
|
||||
|
||||
@@ -25,10 +25,12 @@ import java.io.OutputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -57,6 +59,30 @@ public class Debugger {
|
||||
private final int id;
|
||||
|
||||
public boolean finished = false;
|
||||
private final Map<String, String> parameters = new HashMap<>();
|
||||
|
||||
public static final int MSG_STRING = 0;
|
||||
public static final int MSG_LOADER_URL = 1;
|
||||
public static final int MSG_LOADER_BYTES = 2;
|
||||
|
||||
public String getParameter(String name, String defValue) {
|
||||
if (parameters.containsKey(name)) {
|
||||
return parameters.get(name);
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
public int getVersionMajor() {
|
||||
return Integer.parseInt(getParameter("debug.version.major", "1"));
|
||||
}
|
||||
|
||||
public int getVersionMinor() {
|
||||
return Integer.parseInt(getParameter("debug.version.major", "0"));
|
||||
}
|
||||
|
||||
public boolean hasMsgType() {
|
||||
return getVersionMajor() > 1 || getVersionMinor() > 0;
|
||||
}
|
||||
|
||||
public DebugHandler(int serverPort, Socket s) {
|
||||
this.s = s;
|
||||
@@ -72,6 +98,42 @@ public class Debugger {
|
||||
}
|
||||
}
|
||||
|
||||
private int readType(InputStream is) throws IOException {
|
||||
int type = is.read();
|
||||
if (type == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private byte[] readBytes(InputStream is) throws IOException {
|
||||
int len = is.read();
|
||||
if (len == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
int len2 = is.read();
|
||||
if (len2 == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
int len3 = is.read();
|
||||
if (len3 == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
int len4 = is.read();
|
||||
if (len4 == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
len = (len << 24) + (len2 << 16) + (len3 << 8) + len4;
|
||||
byte data[] = new byte[len];
|
||||
int cnt;
|
||||
int off = 0;
|
||||
while (len > 0 && (cnt = is.read(data, off, len)) > 0) {
|
||||
len -= cnt;
|
||||
off += cnt;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private String readString(InputStream is) throws IOException {
|
||||
int len = is.read();
|
||||
if (len == -1) {
|
||||
@@ -115,14 +177,47 @@ public class Debugger {
|
||||
os.write(("<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"" + serverPort + "\" /></cross-domain-policy>").getBytes("UTF-8"));
|
||||
}
|
||||
} else {
|
||||
if (!ret.isEmpty()) {
|
||||
String param[] = (ret.contains(";") ? ret.split(";") : new String[]{ret});
|
||||
for (String p : param) {
|
||||
if (p.contains("=")) {
|
||||
String key = p.substring(0, p.indexOf("="));
|
||||
String val = p.substring(p.indexOf("=") + 1);
|
||||
parameters.put(key, val);
|
||||
} else {
|
||||
parameters.put(p, "true");
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean hasType = hasMsgType();
|
||||
String name = readString(is);
|
||||
if (!name.isEmpty()) {
|
||||
clientName = name;
|
||||
}
|
||||
while (true) {
|
||||
ret = readString(is);
|
||||
for (DebugListener l : listeners) {
|
||||
l.onMessage(clientName, ret);
|
||||
int type = 0;
|
||||
if (hasType) {
|
||||
type = readType(is);
|
||||
}
|
||||
switch (type) {
|
||||
case MSG_STRING:
|
||||
ret = readString(is);
|
||||
for (DebugListener l : listeners) {
|
||||
l.onMessage(clientName, ret);
|
||||
}
|
||||
break;
|
||||
case MSG_LOADER_URL:
|
||||
ret = readString(is);
|
||||
for (DebugListener l : listeners) {
|
||||
l.onLoaderURL(clientName, ret);
|
||||
}
|
||||
break;
|
||||
case MSG_LOADER_BYTES:
|
||||
byte retB[] = readBytes(is);
|
||||
for (DebugListener l : listeners) {
|
||||
l.onLoaderBytes(clientName, retB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,27 @@ public class DebuggerTools {
|
||||
return tested.matches(Pattern.quote(DEBUGGER_PACKAGE) + "(\\.pkg[a-f0-9]+)?" + cls);
|
||||
}
|
||||
|
||||
public static void injectDebugLoader(SWF swf) {
|
||||
if (hasDebugger(swf)) {
|
||||
ScriptPack dsp = getDebuggerScriptPack(swf);
|
||||
String debuggerPkg = dsp.getClassPath().packageStr.toRawString();
|
||||
for (ABCContainerTag ct : swf.getAbcList()) {
|
||||
ABC a = ct.getABC();
|
||||
if (dsp.abc == a) { //do not replace Loader in debugger itself
|
||||
continue;
|
||||
}
|
||||
for (int i = 1; i < a.constants.constant_multiname.size(); i++) {
|
||||
Multiname m = a.constants.constant_multiname.get(i);
|
||||
if ("flash.display.Loader".equals(m.getNameWithNamespace(a.constants).toRawString())) {
|
||||
m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId(debuggerPkg, true)), 0, true);
|
||||
m.name_index = a.constants.getStringId("DebugLoader", true);
|
||||
((Tag) ct).setModified(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void replaceTraceCalls(SWF swf, String fname) {
|
||||
if (hasDebugger(swf)) {
|
||||
String debuggerPkg = getDebuggerScriptPack(swf).getClassPath().packageStr.toRawString();
|
||||
@@ -111,7 +132,7 @@ public class DebuggerTools {
|
||||
swf.tags.remove((Tag) tag);
|
||||
swf.getAbcList().remove(tag);
|
||||
|
||||
//Change all debugger calls to normal trace
|
||||
//Change all debugger calls to normal trace / Loader
|
||||
for (ABCContainerTag ct : swf.getAbcList()) {
|
||||
ABC a = ct.getABC();
|
||||
for (int i = 1; i < a.constants.constant_multiname.size(); i++) {
|
||||
@@ -124,6 +145,9 @@ public class DebuggerTools {
|
||||
m.name_index = a.constants.getStringId("trace", true);
|
||||
m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId("", true)), 0, true);
|
||||
((Tag) ct).setModified(true);
|
||||
} else if (isDebuggerClass(packageStr, "DebugLoader")) {
|
||||
m.name_index = a.constants.getStringId("Loader", true);
|
||||
m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId("flash.display", true)), 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,7 +160,11 @@ public class DebuggerTools {
|
||||
//load debug swf
|
||||
SWF debugSWF = new SWF(Main.class.getClassLoader().getResourceAsStream("com/jpexs/decompiler/flash/gui/debugger/debug.swf"), false);
|
||||
|
||||
ABCContainerTag firstAbc = swf.getAbcList().get(0);
|
||||
List<ABCContainerTag> al = swf.getAbcList();
|
||||
ABCContainerTag firstAbc = al.isEmpty() ? null : al.get(0);
|
||||
if (firstAbc == null) { //nothing to instrument?
|
||||
return;
|
||||
}
|
||||
String newdebuggerpkg = DEBUGGER_PACKAGE;
|
||||
|
||||
if (Configuration.randomDebuggerPackage.get()) {
|
||||
@@ -174,7 +202,7 @@ public class DebuggerTools {
|
||||
initDebugger();
|
||||
}
|
||||
|
||||
private static void initDebugger() {
|
||||
public static Debugger initDebugger() {
|
||||
if (debugger == null) {
|
||||
synchronized (Main.class) {
|
||||
if (debugger == null) {
|
||||
@@ -184,6 +212,7 @@ public class DebuggerTools {
|
||||
}
|
||||
}
|
||||
}
|
||||
return debugger;
|
||||
}
|
||||
|
||||
public static void debuggerShowLog() {
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user