diff --git a/build_common.xml b/build_common.xml
index e97fccec0..a6ea1a799 100644
--- a/build_common.xml
+++ b/build_common.xml
@@ -17,6 +17,7 @@
+
diff --git a/lib/JavactiveX.jar b/lib/JavactiveX.jar
index 9e4a6b28a..d3143e889 100644
Binary files a/lib/JavactiveX.jar and b/lib/JavactiveX.jar differ
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as
new file mode 100644
index 000000000..4d0008532
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as
@@ -0,0 +1,67 @@
+package com.jpexs.decompiler.flash.debugger {
+
+ import flash.net.Socket;
+ import flash.utils.ByteArray;
+ import flash.events.Event;
+ import flash.display.Sprite;
+
+ public class DebugConnection {
+
+ private static var s:Socket;
+ private static var q = [];
+ private static var first:Boolean = true;
+ private static var inited:Boolean = false;
+ private static var name:String;
+
+
+
+ private static function sendQueue(){
+ var qo = q;
+ q = [];
+ for each(var m in qo){
+ writeMsg(m);
+ }
+ }
+
+ private static function writeString(msg){
+ var b:ByteArray = new ByteArray();
+ b.writeUTFBytes(msg);
+ s.writeByte(b.length);
+ s.writeBytes(b,0,b.length);
+ }
+
+ public static function initClient(sname){
+ if(inited){
+ return;
+ }
+ name = sname;
+ inited = true;
+ s = new Socket();
+ s.addEventListener(Event.CONNECT, function(){
+ sendQueue();
+ });
+ var port:int = 0;
+ port = 123456;
+ s.connect("localhost",port);
+ inited = true;
+ }
+
+ public static function writeMsg(msg){
+ if(!inited){
+ initClient("");
+ }
+ if(s.connected){
+ if(first){
+ s.writeByte(0);
+ writeString(name);
+ first = false;
+ }
+ writeString(msg);
+ }else{
+ q.push(msg);
+ }
+ }
+
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugMain.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugMain.as
new file mode 100644
index 000000000..0ac6bac75
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugMain.as
@@ -0,0 +1,17 @@
+package com.jpexs.decompiler.flash.debugger {
+
+ import flash.display.MovieClip;
+
+
+ public class DebugMain extends MovieClip {
+
+
+ public function DebugMain() {
+ debugAlert("test alert");
+ debugConsole("test console");
+ debugSocket("test proxy");
+ debugTrace("test trace");
+ }
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugAlert.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugAlert.as
new file mode 100644
index 000000000..7a35251ec
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugAlert.as
@@ -0,0 +1,11 @@
+package com.jpexs.decompiler.flash.debugger {
+
+ import flash.external.ExternalInterface;
+
+ public function debugAlert(msg):*{
+ if(ExternalInterface.available)
+ ExternalInterface.call("alert",""+msg);
+ return msg;
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugConsole.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugConsole.as
new file mode 100644
index 000000000..121ab0867
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugConsole.as
@@ -0,0 +1,11 @@
+package com.jpexs.decompiler.flash.debugger {
+
+ import flash.external.ExternalInterface;
+
+ public function debugConsole(msg):*{
+ if(ExternalInterface.available)
+ ExternalInterface.call("console.log",""+msg);
+ return msg;
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugInit.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugInit.as
new file mode 100644
index 000000000..699f8e7c9
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugInit.as
@@ -0,0 +1,8 @@
+package com.jpexs.decompiler.flash.debugger {
+
+
+ public function debugInit(name){
+ DebugConnection.iniClient(name);
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugSocket.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugSocket.as
new file mode 100644
index 000000000..0f93d6137
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugSocket.as
@@ -0,0 +1,13 @@
+package com.jpexs.decompiler.flash.debugger {
+ import flash.system.Capabilities;
+
+ public function debugSocket(msg):*{
+ //only on webpages or activex
+ if(Capabilities.playerType == 'PlugIn'
+ || Capabilities.playerType == 'ActiveX'){
+ DebugConnection.writeMsg(msg);
+ }
+ return msg;
+ }
+
+}
diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugTrace.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugTrace.as
new file mode 100644
index 000000000..58ee09b11
--- /dev/null
+++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/debugTrace.as
@@ -0,0 +1,9 @@
+package com.jpexs.decompiler.flash.debugger {
+
+
+ public function debugTrace(name){
+ debugConsole(name);
+ debugSocket(name);
+ }
+
+}
diff --git a/libsrc/debugswf/debug/DOMDocument.xml b/libsrc/debugswf/debug/DOMDocument.xml
new file mode 100644
index 000000000..607f86475
--- /dev/null
+++ b/libsrc/debugswf/debug/DOMDocument.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libsrc/debugswf/debug/META-INF/metadata.xml b/libsrc/debugswf/debug/META-INF/metadata.xml
new file mode 100644
index 000000000..1bd11073f
--- /dev/null
+++ b/libsrc/debugswf/debug/META-INF/metadata.xml
@@ -0,0 +1,73 @@
+
+
+
+
+ Adobe Flash Professional CS6 - build 537
+ 2014-10-26T15:59:21+01:00
+ 2014-10-27T08:16:09+01:00
+ 2014-10-27T08:16:09+01:00
+
+
+ application/vnd.adobe.fla
+
+
+ xmp.iid:A3850720A95DE411873EA2B016962F64
+ xmp.did:1476A545885CE411B13FACEEFCD7D43C
+ xmp.did:1476A545885CE411B13FACEEFCD7D43C
+
+
+
+ created
+ xmp.iid:1476A545885CE411B13FACEEFCD7D43C
+ 2014-10-26T15:59:21+01:00
+ Adobe Flash Professional CS6 - build 537
+
+
+ created
+ xmp.iid:8C96C4B4325DE411B13FACEEFCD7D43C
+ 2014-10-26T15:59:21+01:00
+ Adobe Flash Professional CS6 - build 537
+
+
+ created
+ xmp.iid:8E96C4B4325DE411B13FACEEFCD7D43C
+ 2014-10-26T15:59:21+01:00
+ Adobe Flash Professional CS6 - build 537
+
+
+ created
+ xmp.iid:A3850720A95DE411873EA2B016962F64
+ 2014-10-26T15:59:21+01:00
+ Adobe Flash Professional CS6 - build 537
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libsrc/debugswf/debug/MobileSettings.xml b/libsrc/debugswf/debug/MobileSettings.xml
new file mode 100644
index 000000000..e69de29bb
diff --git a/libsrc/debugswf/debug/PublishSettings.xml b/libsrc/debugswf/debug/PublishSettings.xml
new file mode 100644
index 000000000..dce804882
--- /dev/null
+++ b/libsrc/debugswf/debug/PublishSettings.xml
@@ -0,0 +1,206 @@
+
+
+
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ ../../src/com/jpexs/decompiler/flash/gui/debugger/debug.swf
+ debug.exe
+ debug.app
+ debug.html
+ debug.gif
+ debug.jpg
+ debug.png
+ debug.mov
+ debug.smil
+ debug.swc
+
+
+ 0
+ 11,4,0,0;11,3,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1;
+ 1
+ 1
+ debug_content.html
+ debug_alternate.html
+ 0
+
+ 550
+ 400
+ 0
+ 0
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4
+ 0
+ 0
+ 1
+ 0
+ C:\Users\Jindra\AppData\Local\Adobe\Flash CS6\en_US\Configuration\HTML\Default.html
+ 1
+
+
+
+
+ 0
+ 0
+ 0
+ 80
+ 0
+ 0
+ 7
+ 0
+ 7
+ 0
+ 17
+ FlashPlayer11.4
+ 3
+ 1
+
+ .
+ CONFIG::FLASH_AUTHORING="true";
+ 0
+
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ com.jpexs.decompiler.flash.debugger.DebugMain
+ 2
+ 4
+ 4096
+ AS3
+ 1
+ 1
+ 0
+ 15
+ 1
+ 0
+ 4102
+ rsl
+ wrap
+ $(AppConfig)/ActionScript 3.0/rsls/loader_animation.swf
+
+
+ $(AppConfig)/ActionScript 3.0/libs
+ merge
+
+
+ $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc
+ rsl
+ http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz
+ http://fpdownload.adobe.com/pub/swz/crossdomain.xml
+ textLayout_2.0.0.232.swz
+
+
+
+
+ $(AppConfig)/ActionScript 3.0/libs/11.0/textLayout.swc
+
+ http://fpdownload.adobe.com/pub/swz/tlf/2.0.0.232/textLayout_2.0.0.232.swz
+ http://fpdownload.adobe.com/pub/swz/crossdomain.xml
+ textLayout_2.0.0.232.swz
+
+
+
+
+ 550
+ 400
+ 0
+ 4718592
+ 0
+ 80
+ 1
+
+
+ 1
+ 0
+ 1
+ 0
+ 0
+ 100000
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+
+
+ 550
+ 400
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 1
+ 0
+ 0
+
+ 128
+
+
+ 255
+
+
+
+ 550
+ 400
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 1
+
+
+
+ 24-bit with Alpha
+ 255
+
+
+
+ 550
+ 400
+ 1
+ 0
+
+
+ 00000000
+ 0
+ 0
+ 0
+ 0
+ 1
+
+
+
\ No newline at end of file
diff --git a/libsrc/debugswf/debug/bin/SymDepend.cache b/libsrc/debugswf/debug/bin/SymDepend.cache
new file mode 100644
index 000000000..fa0e29a10
Binary files /dev/null and b/libsrc/debugswf/debug/bin/SymDepend.cache differ
diff --git a/libsrc/debugswf/debug/debug.xfl b/libsrc/debugswf/debug/debug.xfl
new file mode 100644
index 000000000..860a820ec
--- /dev/null
+++ b/libsrc/debugswf/debug/debug.xfl
@@ -0,0 +1 @@
+PROXY-CS5
\ No newline at end of file
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java
index 4f48a317a..be86d89ca 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java
@@ -34,6 +34,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -197,4 +198,35 @@ public class ScriptPack implements TreeElementItem {
}
return file;
}
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+ hash = 79 * hash + Objects.hashCode(this.abc);
+ hash = 79 * hash + this.scriptIndex;
+ hash = 79 * hash + Objects.hashCode(this.path);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ScriptPack other = (ScriptPack) obj;
+ if (!Objects.equals(this.abc, other.abc)) {
+ return false;
+ }
+ if (this.scriptIndex != other.scriptIndex) {
+ return false;
+ }
+ if (!Objects.equals(this.path, other.path)) {
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
index ab2edc50b..9580c3200 100644
--- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
+++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java
@@ -340,6 +340,14 @@ public class Configuration {
public static final ConfigurationItem pluginPath = null;
+
+ @ConfigurationDefaultInt(55556)
+ @ConfigurationCategory("script")
+ public static final ConfigurationItem debuggerPort = null;
+
+ @ConfigurationDefaultBoolean(true)
+ public static final ConfigurationItem displayDebuggerInfo = null;
+
private enum OSId {
WINDOWS, OSX, UNIX
diff --git a/src/com/jpexs/decompiler/flash/gui/DebugLogDialog.java b/src/com/jpexs/decompiler/flash/gui/DebugLogDialog.java
new file mode 100644
index 000000000..789ae59c6
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/DebugLogDialog.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2014 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.jpexs.decompiler.flash.gui;
+
+import com.jpexs.decompiler.flash.gui.debugger.DebugListener;
+import com.jpexs.decompiler.flash.gui.debugger.Debugger;
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ListModel;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class DebugLogDialog extends AppDialog implements ActionListener {
+
+ private JTextArea logTextArea = new JTextArea();
+ private final String ACTION_CLOSE = "CLOSE";
+ private final String ACTION_CLEAR = "CLEAR";
+ private Debugger debug;
+
+ public DebugLogDialog(Debugger debug) {
+ setSize(800, 600);
+ this.debug = debug;
+ setTitle(translate("dialog.title"));
+ logTextArea.setBackground(Color.white);
+ logTextArea.setEditable(false);
+ JScrollPane spane = new JScrollPane(logTextArea);
+ spane.setPreferredSize(new Dimension(800,500));
+
+ debug.addMessageListener(new DebugListener() {
+
+ @Override
+ public void onMessage(String clientId, String msg) {
+ log(translate("msg.header").replace("%clientid%", clientId)+msg);
+ }
+
+ @Override
+ public void onFinish(String clientId) {
+
+ }
+ });
+ Container cnt = getContentPane();
+ cnt.setLayout(new BorderLayout());
+ cnt.add(spane,BorderLayout.CENTER);
+
+ JPanel buttonsPanel = new JPanel(new FlowLayout());
+ JButton clearButton = new JButton(translate("button.clear"));
+ clearButton.setActionCommand(ACTION_CLEAR);
+ clearButton.addActionListener(this);
+
+ JButton closeButton = new JButton(translate("button.close"));
+ closeButton.setActionCommand(ACTION_CLOSE);
+ closeButton.addActionListener(this);
+
+ buttonsPanel.add(clearButton);
+ buttonsPanel.add(closeButton);
+ cnt.add(buttonsPanel,BorderLayout.SOUTH);
+ View.setWindowIcon(this);
+ View.centerScreen(this);
+ }
+
+ public void log(String msg){
+ Document d = logTextArea.getDocument();
+ try {
+ d.insertString(d.getLength(), msg+"\r\n", null);
+ } catch (BadLocationException ex) {
+ //ignore
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ switch(e.getActionCommand()){
+ case ACTION_CLEAR:
+ logTextArea.setText("");
+ break;
+ case ACTION_CLOSE:
+ setVisible(false);
+ break;
+ }
+ }
+
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java
index 6788d89d2..13b4b0888 100644
--- a/src/com/jpexs/decompiler/flash/gui/Main.java
+++ b/src/com/jpexs/decompiler/flash/gui/Main.java
@@ -23,12 +23,22 @@ import com.jpexs.decompiler.flash.SWFBundle;
import com.jpexs.decompiler.flash.SWFSourceInfo;
import com.jpexs.decompiler.flash.SearchMode;
import com.jpexs.decompiler.flash.Version;
+import com.jpexs.decompiler.flash.abc.ABC;
+import com.jpexs.decompiler.flash.abc.ClassPath;
+import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
+import com.jpexs.decompiler.flash.abc.types.Multiname;
+import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.console.CommandLineArgumentParser;
import com.jpexs.decompiler.flash.console.ContextMenuTools;
+import com.jpexs.decompiler.flash.gui.debugger.DebugListener;
+import com.jpexs.decompiler.flash.gui.debugger.Debugger;
import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
+import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
+import com.jpexs.decompiler.flash.tags.ABCContainerTag;
+import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.treeitems.SWFList;
import com.jpexs.helpers.Cache;
@@ -70,6 +80,7 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
+import java.util.Random;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
@@ -106,6 +117,39 @@ public class Main {
public static LoadFromMemoryFrame loadFromMemoryFrame;
public static LoadFromCacheFrame loadFromCacheFrame;
private static final Logger logger = Logger.getLogger(Main.class.getName());
+ private static Debugger debugger;
+ public static DebugLogDialog debugDialog;
+ public static final String DEBUGGER_PACKAGE = "com.jpexs.decompiler.flash.debugger";
+
+ private static ABCContainerTag getDebuggerABCTag(SWF swf) {
+ for (ABCContainerTag ac : swf.abcList) {
+ ABC a = ac.getABC();
+ for (MyEntry m : a.getScriptPacks()) {
+ if (isDebuggerClass(m.getKey().packageStr, null)) {
+ return ac;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String getDebuggerPackage(SWF swf) {
+ ABCContainerTag ac = getDebuggerABCTag(swf);
+ if (ac == null) {
+ return null;
+ }
+ ABC a = ac.getABC();
+ for (MyEntry m : a.getScriptPacks()) {
+ if (isDebuggerClass(m.getKey().packageStr, null)) {
+ return m.getKey().packageStr;
+ }
+ }
+ return null;
+ }
+
+ public static boolean hasDebugger(SWF swf) {
+ return getDebuggerABCTag(swf) != null;
+ }
public static void ensureMainFrame() {
if (mainFrame == null) {
@@ -448,6 +492,10 @@ public class Main {
}
public static void reloadApp() {
+ if (debugDialog != null) {
+ debugDialog.setVisible(false);
+ debugDialog = null;
+ }
if (loadingDialog != null) {
loadingDialog.setVisible(false);
loadingDialog = null;
@@ -878,7 +926,7 @@ public class Main {
* @throws IOException
*/
public static void main(String[] args) throws IOException {
-
+
String pluginPath = Configuration.pluginPath.get();
if (pluginPath != null && !pluginPath.isEmpty()) {
try {
@@ -1030,6 +1078,124 @@ public class Main {
(new AdvancedSettingsDialog()).setVisible(true);
}
+ private static boolean isDebuggerClass(String tested, String cls) {
+ if (tested == null) {
+ return false;
+ }
+ if (cls == null) {
+ cls = "";
+ } else {
+ cls = "\\." + Pattern.quote(cls);
+ }
+ return tested.matches(Pattern.quote(DEBUGGER_PACKAGE) + "\\.pkg[a-f0-9]+" + cls);
+ }
+
+ private static String byteArrayToHex(byte[] a) {
+ StringBuilder sb = new StringBuilder(a.length * 2);
+ for (byte b : a) {
+ sb.append(String.format("%02x", b & 0xff));
+ }
+ return sb.toString();
+ }
+
+ public static void replaceTraceCalls(String fname) {
+ SWF swf = getMainFrame().getPanel().getCurrentSwf();
+ if (hasDebugger(swf)) {
+ String debuggerPkg = getDebuggerPackage(swf);
+ //change trace to fname
+ for (ABCContainerTag ct : swf.abcList) {
+ ABC a = ct.getABC();
+ for (int i = 1; i < a.constants.constant_multiname.size(); i++) {
+ Multiname m = a.constants.constant_multiname.get(i);
+ if ("trace".equals(m.getNameWithNamespace(a.constants, true))) {
+ m.namespace_index = a.constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, a.constants.getStringId(debuggerPkg, true)), 0, true);
+ m.name_index = a.constants.getStringId(fname, true);
+ ((Tag) ct).setModified(true);
+ }
+ }
+ }
+ }
+ }
+
+ public static void switchDebugger() {
+ int port = Configuration.debuggerPort.get();
+ SWF swf = getMainFrame().getPanel().getCurrentSwf();
+ ABCContainerTag found = getDebuggerABCTag(swf);
+ if (found != null) {
+ swf.tags.remove((Tag) found);
+ swf.abcList.remove(found);
+
+ //Change all debugger calls to normal trace
+ for (ABCContainerTag ct : swf.abcList) {
+ ABC a = ct.getABC();
+ for (int i = 1; i < a.constants.constant_multiname.size(); i++) {
+ Multiname m = a.constants.constant_multiname.get(i);
+ if (isDebuggerClass(m.getNameWithNamespace(a.constants, true), "debugTrace")
+ || isDebuggerClass(m.getNameWithNamespace(a.constants, true), "debugAlert")
+ || isDebuggerClass(m.getNameWithNamespace(a.constants, true), "debugSocket")
+ || isDebuggerClass(m.getNameWithNamespace(a.constants, true), "debugConsole")) {
+ 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 {
+ Random rnd = new Random();
+ byte rb[] = new byte[16];
+ rnd.nextBytes(rb);
+ String rhex = byteArrayToHex(rb);
+ try {
+ //load debug swf
+ SWF debugSWF = new SWF(Main.class.getClassLoader().getResourceAsStream("com/jpexs/decompiler/flash/gui/debugger/debug.swf"), false);
+
+ ABCContainerTag firstAbc = swf.abcList.get(0);
+ String newdebuggerpkg = DEBUGGER_PACKAGE + ".pkg" + rhex;
+ //add debug ABC tags to main SWF
+ for (ABCContainerTag ds : debugSWF.abcList) {
+ ABC a = ds.getABC();
+ //Append random hex to Debugger package name
+ for (int i = 1; i < a.constants.constant_namespace.size(); i++) {
+ if (a.constants.constant_namespace.get(i).hasName(DEBUGGER_PACKAGE, a.constants)) {
+ a.constants.constant_namespace.get(i).name_index = a.constants.getStringId(newdebuggerpkg, true);
+ }
+ }
+ //Set debugger port to actually set port
+ for (int i = 0; i < a.constants.constant_int.size(); i++) {
+ if (a.constants.constant_int.get(i) == 123456L) {
+ a.constants.constant_int.set(i, (long) port);
+ }
+ }
+ //Add to target SWF
+ ((Tag) ds).setSwf(swf);
+ swf.tags.add(swf.tags.indexOf(firstAbc), (Tag) ds);
+ swf.abcList.add(swf.abcList.indexOf(firstAbc), ds);
+ ((Tag) ds).setModified(true);
+ }
+
+ } catch (Exception ex) {
+ //ignore
+ }
+
+ }
+ initDebugger();
+ }
+
+ private static void initDebugger() {
+ if (debugger == null) {
+ debugger = new Debugger(Configuration.debuggerPort.get());
+ debugger.start();
+ }
+ }
+
+ public static void debuggerShowLog() {
+ initDebugger();
+ if (debugDialog == null) {
+ debugDialog = new DebugLogDialog(debugger);
+ }
+ debugDialog.setVisible(true);
+ }
+
public static void autoCheckForUpdates() {
if (Configuration.checkForUpdatesAuto.get()) {
Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get();
diff --git a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
index 72eefe499..6b0a4e7fe 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainFrameRibbonMenu.java
@@ -93,6 +93,9 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
static final String ACTION_TIMELINE = "TIMELINE";
static final String ACTION_AUTO_DEOBFUSCATE = "AUTODEOBFUSCATE";
static final String ACTION_EXIT = "EXIT";
+ static final String ACTION_DEBUGGER_SWITCH = "DEBUGGER_SWITCH";
+ static final String ACTION_DEBUGGER_REPLACE_TRACE = "DEBUGGER_REPLACE_TRACE";
+ static final String ACTION_DEBUGGER_LOG = "DEBUGGER_LOG";
static final String ACTION_RENAME_ONE_IDENTIFIER = "RENAMEONEIDENTIFIER";
static final String ACTION_ABOUT = "ABOUT";
@@ -158,6 +161,10 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
private CommandToggleButtonGroup timeLineToggleGroup;
private JCommandButton gotoDocumentClassCommandButton;
private JCommandButton clearRecentFilesCommandButton;
+ private JCommandToggleButton debuggerSwitchCommandButton;
+ private CommandToggleButtonGroup debuggerSwitchGroup;
+ private JCommandButton debuggerReplaceTraceCommandButton;
+ private JCommandButton debuggerLogCommandButton;
private CommandToggleButtonGroup viewModeToggleGroup;
@@ -385,13 +392,43 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
}
private RibbonTask createToolsRibbonTask() {
+
+
+ JRibbonBand debuggerBand = new JRibbonBand(translate("menu.debugger"), null);
+ debuggerBand.setResizePolicies(getResizePolicies(debuggerBand));
+
+ debuggerSwitchCommandButton = new JCommandToggleButton(translate("menu.debugger.switch"),View.getResizableIcon("debugger32"));
+ assignListener(debuggerSwitchCommandButton, ACTION_DEBUGGER_SWITCH);
+
+ //debuggerDetachCommandButton = new JCommandButton("Detach debugger",View.getResizableIcon("debuggerremove16"));
+ //assignListener(debuggerDetachCommandButton, ACTION_DEBUGGER_DETACH);
+
+ debuggerReplaceTraceCommandButton = new JCommandButton(translate("menu.debugger.replacetrace"), View.getResizableIcon("debuggerreplace16"));
+ assignListener(debuggerReplaceTraceCommandButton, ACTION_DEBUGGER_REPLACE_TRACE);
+
+ debuggerLogCommandButton = new JCommandButton(translate("menu.debugger.showlog"), View.getResizableIcon("debuggerlog16"));
+ assignListener(debuggerLogCommandButton, ACTION_DEBUGGER_LOG);
+
+ debuggerSwitchGroup = new CommandToggleButtonGroup();
+ debuggerSwitchGroup.add(debuggerSwitchCommandButton);
+
+ debuggerSwitchCommandButton.setEnabled(false);
+
+ debuggerReplaceTraceCommandButton.setEnabled(false);
+
+ debuggerBand.addCommandButton(debuggerSwitchCommandButton, RibbonElementPriority.TOP);
+ debuggerBand.addCommandButton(debuggerReplaceTraceCommandButton, RibbonElementPriority.MEDIUM);
+ debuggerBand.addCommandButton(debuggerLogCommandButton, RibbonElementPriority.MEDIUM);
+
+
+
//----------------------------------------- TOOLS -----------------------------------
JRibbonBand toolsBand = new JRibbonBand(translate("menu.tools"), null);
toolsBand.setResizePolicies(getResizePolicies(toolsBand));
searchCommandButton = new JCommandButton(fixCommandTitle(translate("menu.tools.search")), View.getResizableIcon("search32"));
- assignListener(searchCommandButton, ACTION_SEARCH);
+ assignListener(searchCommandButton, ACTION_SEARCH);
timeLineToggleButton = new JCommandToggleButton(fixCommandTitle(translate("menu.tools.timeline")), View.getResizableIcon("timeline32"));
assignListener(timeLineToggleButton, ACTION_TIMELINE);
@@ -436,7 +473,7 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
//JRibbonBand otherToolsBand = new JRibbonBand(translate("menu.tools.otherTools"), null);
//otherToolsBand.setResizePolicies(getResizePolicies(otherToolsBand));
- return new RibbonTask(translate("menu.tools"), toolsBand, deobfuscationBand/*, otherToolsBand*/);
+ return new RibbonTask(translate("menu.tools"), toolsBand, deobfuscationBand, debuggerBand /*, otherToolsBand*/);
}
private RibbonTask createSettingsRibbonTask(boolean externalFlashPlayerUnavailable) {
@@ -598,7 +635,8 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
public void updateComponents(SWF swf, List abcList) {
boolean swfLoaded = swf != null;
boolean hasAbc = swfLoaded && abcList != null && !abcList.isEmpty();
-
+ boolean hasDebugger = hasAbc && Main.hasDebugger(swf);
+
exportAllMenu.setEnabled(swfLoaded);
exportFlaMenu.setEnabled(swfLoaded);
exportSelMenu.setEnabled(swfLoaded);
@@ -625,6 +663,12 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
gotoDocumentClassCommandButton.setEnabled(hasAbc);
deobfuscationCommandButton.setEnabled(hasAbc);
+ debuggerSwitchCommandButton.setEnabled(hasAbc);
+ debuggerSwitchGroup.setSelected(debuggerSwitchCommandButton, hasDebugger);
+ //debuggerSwitchCommandButton.
+ //debuggerDetachCommandButton.setEnabled(hasDebugger);
+ debuggerReplaceTraceCommandButton.setEnabled(hasAbc && hasDebugger);
+
}
private boolean saveAs(SWF swf, SaveFileMode mode) {
@@ -640,6 +684,28 @@ public class MainFrameRibbonMenu implements MainFrameMenu, ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
+ case ACTION_DEBUGGER_SWITCH:
+ if(debuggerSwitchGroup.getSelected()==null || View.showConfirmDialog(mainFrame, translate("message.debugger"), translate("dialog.message.title"),JOptionPane.OK_CANCEL_OPTION,JOptionPane.INFORMATION_MESSAGE, Configuration.displayDebuggerInfo,JOptionPane.OK_OPTION)==JOptionPane.OK_OPTION){
+ Main.switchDebugger();
+ mainFrame.panel.refreshDecompiled();
+ }else{
+ if(debuggerSwitchGroup.getSelected()==debuggerSwitchCommandButton){
+ debuggerSwitchGroup.setSelected(debuggerSwitchCommandButton, false);
+ }
+ }
+ debuggerReplaceTraceCommandButton.setEnabled(debuggerSwitchGroup.getSelected()==debuggerSwitchCommandButton);
+ break;
+ case ACTION_DEBUGGER_LOG:
+ Main.debuggerShowLog();
+ break;
+ case ACTION_DEBUGGER_REPLACE_TRACE:
+ ReplaceTraceDialog rtd = new ReplaceTraceDialog(mainFrame);
+ rtd.setVisible(true);
+ if(rtd.getResult()!=null){
+ Main.replaceTraceCalls(rtd.getResult());
+ mainFrame.panel.refreshDecompiled();
+ }
+ break;
case ACTION_RELOAD:
if (View.showConfirmDialog(null, translate("message.confirm.reload"), translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
Main.reloadApp();
diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
index 069fb6993..cb85f49fd 100644
--- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java
@@ -1892,12 +1892,12 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec
}
}
- public void refreshDecompiled() {
+ public void refreshDecompiled() {
clearCache();
if (abcPanel != null) {
abcPanel.reload();
}
- reload(true);
+ reload(true);
updateClassesList();
}
diff --git a/src/com/jpexs/decompiler/flash/gui/ReplaceTraceDialog.java b/src/com/jpexs/decompiler/flash/gui/ReplaceTraceDialog.java
new file mode 100644
index 000000000..2de8e0471
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/ReplaceTraceDialog.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 JPEXS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package com.jpexs.decompiler.flash.gui;
+
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class ReplaceTraceDialog extends AppDialog {
+
+ private JRadioButton debugAlertRadio;
+ private JRadioButton debugConsoleRadio;
+ private JRadioButton debugProxyRadio;
+
+ private String result = null;
+
+ public String getResult() {
+ return result;
+ }
+
+ public ReplaceTraceDialog(Window owner) {
+ super(owner);
+ setTitle(translate("dialog.title"));
+ Container cnt=getContentPane();
+ cnt.setLayout(new BoxLayout(cnt, BoxLayout.Y_AXIS));
+ debugAlertRadio = new JRadioButton(translate("function.debugAlert"));
+ debugAlertRadio.setAlignmentX(0);
+ debugConsoleRadio = new JRadioButton(translate("function.debugConsole"));
+ debugConsoleRadio.setAlignmentX(0);
+ debugProxyRadio = new JRadioButton(translate("function.debugSocket"));
+ debugProxyRadio.setAlignmentX(0);
+
+ debugAlertRadio.setSelected(true);
+
+ ButtonGroup bg = new ButtonGroup();
+ bg.add(debugAlertRadio);
+ bg.add(debugConsoleRadio);
+ bg.add(debugProxyRadio);
+
+
+
+ cnt.add(debugAlertRadio);
+ cnt.add(debugConsoleRadio);
+ cnt.add(debugProxyRadio);
+
+ JPanel buttonsPanel = new JPanel(new FlowLayout());
+ JButton okButton=new JButton(AppStrings.translate("button.ok"));
+ okButton.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if(debugAlertRadio.isSelected()){
+ result = "debugAlert";
+ }
+ if(debugConsoleRadio.isSelected()){
+ result = "debugConsole";
+ }
+ if(debugProxyRadio.isSelected()){
+ result = "debugSocket";
+ }
+ setVisible(false);
+ }
+ });
+ JButton cancelButton=new JButton(AppStrings.translate("button.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ result = null;
+ setVisible(false);
+ }
+ });
+ buttonsPanel.add(okButton);
+ buttonsPanel.add(cancelButton);
+ buttonsPanel.setAlignmentX(0);
+ add(buttonsPanel);
+ setModalityType(DEFAULT_MODALITY_TYPE);
+ pack();
+ View.setWindowIcon(this);
+ View.centerScreen(this);
+ }
+
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java b/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java
index 482dab457..425a083c5 100644
--- a/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java
+++ b/src/com/jpexs/decompiler/flash/gui/TagTreeModel.java
@@ -333,7 +333,7 @@ public class TagTreeModel implements TreeModel {
if (n instanceof TreeElement) {
TreeElement te = (TreeElement) n;
TreeElementItem it = te.getItem();
- if (obj == it) {
+ if (obj.equals(it)) {
return newPath;
}
}
@@ -346,7 +346,7 @@ public class TagTreeModel implements TreeModel {
return newPath;
}
} else {
- if (n.getItem() == obj) {
+ if (obj.equals(n.getItem())) {
return newPath;
}
}
diff --git a/src/com/jpexs/decompiler/flash/gui/View.java b/src/com/jpexs/decompiler/flash/gui/View.java
index 1b921ac91..13ec09128 100644
--- a/src/com/jpexs/decompiler/flash/gui/View.java
+++ b/src/com/jpexs/decompiler/flash/gui/View.java
@@ -376,7 +376,7 @@ public class View {
public static int showConfirmDialog(final Component parentComponent, String message, final String title, final int optionType, final int messageTyp, ConfigurationItem showAgainConfig, int defaultOption) {
- JLabel warLabel = new JLabel(message);
+ JLabel warLabel = new JLabel(""+message.replace("\r\n", "
")+"");
final JPanel warPanel = new JPanel(new BorderLayout());
warPanel.add(warLabel, BorderLayout.CENTER);
JCheckBox donotShowAgainCheckBox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain"));
@@ -398,13 +398,37 @@ public class View {
return ret[0];
}
- public static void showMessageDialog(final Component parentComponent, final Object message, final String title, final int messageType) {
+ public static void showMessageDialog(final Component parentComponent, final String message, final String title, final int messageType) {
+ showMessageDialog(parentComponent, message, title, messageType, null);
+ }
+
+ public static void showMessageDialog(final Component parentComponent, final String message, final String title, final int messageType, ConfigurationItem showAgainConfig) {
+
+ Object msg = message;
+ JCheckBox donotShowAgainCheckBox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain"));
+
+ if (showAgainConfig != null) {
+ JLabel warLabel = new JLabel(""+message.replace("\r\n", "
")+"");
+ final JPanel warPanel = new JPanel(new BorderLayout());
+ warPanel.add(warLabel, BorderLayout.CENTER);
+ donotShowAgainCheckBox.setSelected(!showAgainConfig.get());
+ warPanel.add(donotShowAgainCheckBox, BorderLayout.SOUTH);
+ msg = warPanel;
+ if (donotShowAgainCheckBox.isSelected()) {
+ return;
+ }
+ }
+ final Object fmsg=msg;
+
execInEventDispatch(new Runnable() {
@Override
public void run() {
- JOptionPane.showMessageDialog(parentComponent, message, title, messageType);
+ JOptionPane.showMessageDialog(parentComponent, fmsg, title, messageType);
}
});
+ if (showAgainConfig != null) {
+ showAgainConfig.set(!donotShowAgainCheckBox.isSelected());
+ }
}
public static void showMessageDialog(final Component parentComponent, final Object message) {
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
index 8cea28f0a..a0ea3503a 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java
@@ -119,7 +119,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
public ABC abc;
public SWF swf;
public JComboBox abcComboBox;
- public int listIndex = -1;
+ public ABCContainerTag listIndex = null;
public DecompiledEditorPane decompiledTextArea;
public JScrollPane decompiledScrollPane;
public JSplitPane splitPane;
@@ -318,8 +318,8 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
public void setSwf(SWF swf) {
if (this.swf != swf) {
this.swf = swf;
- listIndex = -1;
- switchAbc(0); // todo honika: do we need this?
+ listIndex = null;
+ switchAbc(swf.abcList.get(0)); // todo honika: do we need this?
abcComboBox.setModel(new ABCComboBoxModel(swf.abcList));
if (swf.abcList.size() > 0) {
this.abc = swf.abcList.get(0).getABC();
@@ -329,11 +329,11 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
}
}
- public void switchAbc(int index) {
+ public void switchAbc(ABCContainerTag index) {
listIndex = index;
- if (index != -1) {
- this.abc = swf.abcList.get(index).getABC();
+ if (index != null) {
+ this.abc = index.getABC();
}
updateConstList();
}
@@ -643,7 +643,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
if (index == -1) {
return;
}
- switchAbc(index - 1);
+ switchAbc(swf.abcList.get(index - 1));
}
if (e.getSource() == constantTypeList) {
int index = ((JComboBox) e.getSource()).getSelectedIndex();
@@ -775,15 +775,23 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se
case ACTION_SAVE_DECOMPILED:
ScriptPack pack = decompiledTextArea.getScriptLeaf();
int oldIndex = pack.scriptIndex;
-
+ decompiledTextArea.uncache(pack);
+
+
try {
+ String oldSp = null;
+ List> packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex);
+ if (!packs.isEmpty()) {
+ oldSp = packs.get(0).getKey().toString();
+ }
+
String as = decompiledTextArea.getText();
abc.replaceSciptPack(pack, as);
lastDecompiled = as;
mainPanel.updateClassesList();
- List> packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex);
- if (!packs.isEmpty()) {
- hilightScript(swf, packs.get(0).getKey().toString());
+
+ if(oldSp!=null){
+ hilightScript(swf, oldSp);
}
//decompiledTextArea.setClassIndex(-1);
//navigator.setClassIndex(-1, oldIndex);
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java
index d536889e8..ef8579f3c 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java
@@ -385,7 +385,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
}
}
- private void uncache(ScriptPack pack) {
+ public void uncache(ScriptPack pack) {
cache.remove(pack);
}
diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java
index 01939b0a7..77d566c3a 100644
--- a/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java
@@ -169,7 +169,9 @@ public class DetailPanel extends JPanel implements ActionListener {
if (trait == null) {
traitNameLabel.setText("-");
} else {
- traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList(), false));
+ if(abcPanel!=null && trait.getName(abcPanel.abc)!=null && abcPanel.abc != null){
+ traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList(), false));
+ }
}
}
});
diff --git a/src/com/jpexs/decompiler/flash/gui/debugger/DebugListener.java b/src/com/jpexs/decompiler/flash/gui/debugger/DebugListener.java
new file mode 100644
index 000000000..0627a7b58
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/debugger/DebugListener.java
@@ -0,0 +1,10 @@
+package com.jpexs.decompiler.flash.gui.debugger;
+
+/**
+ *
+ * @author JPEXS
+ */
+public interface DebugListener {
+ public void onMessage(String clientId,String msg);
+ public void onFinish(String clientId);
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/debugger/Debugger.java b/src/com/jpexs/decompiler/flash/gui/debugger/Debugger.java
new file mode 100644
index 000000000..752b40dc1
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/debugger/Debugger.java
@@ -0,0 +1,181 @@
+package com.jpexs.decompiler.flash.gui.debugger;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class Debugger {
+
+ private static Set listeners = new HashSet<>();
+
+ public synchronized void addMessageListener(DebugListener l) {
+ listeners.add(l);
+ }
+
+ public synchronized void removeMessageListener(DebugListener l) {
+ listeners.remove(l);
+ }
+
+ private static class DebugHandler extends Thread {
+
+ Socket s;
+ int serverPort;
+ static int maxid = 0;
+ int id;
+ public boolean finished = false;
+
+ public DebugHandler(int serverPort, Socket s) {
+ this.s = s;
+ id = maxid++;
+ this.serverPort = serverPort;
+ }
+
+ public void cancel() {
+ try {
+ s.close();
+ } catch (IOException ex) {
+ //ignore
+ }
+ }
+
+ private String readString(InputStream is) throws IOException
+ {
+ int len = is.read();
+ if (len == -1) {
+ return "";
+ }
+ byte buf[] = new byte[len];
+ is.read(buf);
+ return new String(buf, "UTF-8");
+
+ }
+ @Override
+ public void run() {
+ String clientName = ""+id;
+ try (InputStream is = s.getInputStream()) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ int c;
+ do {
+ c = is.read();
+ if (c != 0) {
+ baos.write(c);
+ }
+
+ } while (c > 0);
+ String ret = baos.toString("UTF-8");
+
+ if (ret.equals("")) {
+ try (OutputStream os = s.getOutputStream()) {
+ os.write(("").getBytes("UTF-8"));
+ }
+ } else {
+ String name = readString(is);
+ if(!name.equals("")){
+ clientName = name;
+ }
+ while (true) {
+ ret = readString(is);
+ for (DebugListener l : listeners) {
+ l.onMessage(clientName, ret);
+ }
+ }
+ }
+
+ } catch (IOException ex) {
+ //ignore
+ }
+ try {
+ s.close();
+ } catch (IOException ex) {
+ //ignore
+ }
+ finished = true;
+ for (DebugListener l : listeners) {
+ l.onFinish(clientName);
+ }
+ }
+
+ }
+
+ private static class DebugServerThread extends Thread {
+
+ private final int port;
+ private ServerSocket ss;
+ private final Map handlers = new WeakHashMap<>();
+
+ public DebugServerThread(int port) {
+ this.port = port;
+ }
+
+ @Override
+ public void run() {
+ try {
+ ss = new ServerSocket(port,50,InetAddress.getByName("localhost"));
+ ss.setReuseAddress(true);
+ while (true) {
+ Socket s = ss.accept();
+ if (s != null) {
+ DebugHandler h = new DebugHandler(port, s);
+ handlers.put(h.id, h);
+ h.start();
+ }
+ }
+ } catch (IOException ex) {
+ //ignore
+ }
+ }
+
+ }
+
+ private int port;
+
+ public Debugger(int port) {
+ this.port = port;
+ }
+
+ private DebugServerThread server = null;
+
+ public synchronized void start() {
+ if (server == null) {
+ server = new DebugServerThread(port);
+ server.start();
+ }
+ }
+
+ public synchronized boolean isRunning() {
+ return server != null;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public synchronized void stop() {
+ if (server != null) {
+ try {
+ server.ss.close();
+ } catch (IOException ex) {
+ //ignore
+ }
+ for (DebugHandler h : server.handlers.values()) {
+ h.cancel();
+ }
+ server.handlers.clear();
+ server = null;
+ }
+ }
+
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/debugger/debug.swf b/src/com/jpexs/decompiler/flash/gui/debugger/debug.swf
new file mode 100644
index 000000000..f6851e435
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/debugger/debug.swf differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debugger16.png b/src/com/jpexs/decompiler/flash/gui/graphics/debugger16.png
new file mode 100644
index 000000000..c7299fd7d
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debugger16.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debugger32.png b/src/com/jpexs/decompiler/flash/gui/graphics/debugger32.png
new file mode 100644
index 000000000..563c364c7
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debugger32.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach16.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach16.png
new file mode 100644
index 000000000..e8d9959f9
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach16.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach32.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach32.png
new file mode 100644
index 000000000..8bfe4a44e
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerattach32.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerlog16.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerlog16.png
new file mode 100644
index 000000000..8a08b5224
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerlog16.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove16.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove16.png
new file mode 100644
index 000000000..06a9049e5
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove16.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove32.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove32.png
new file mode 100644
index 000000000..5e1faac49
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerremove32.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace16.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace16.png
new file mode 100644
index 000000000..808773ece
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace16.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace32.png b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace32.png
new file mode 100644
index 000000000..285c58279
Binary files /dev/null and b/src/com/jpexs/decompiler/flash/gui/graphics/debuggerreplace32.png differ
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
index e3132bb2c..e9026d582 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties
@@ -272,3 +272,9 @@ config.description.showMethodBodyId = Shows the id of the methodbody for command
config.name.export.zoom = (Internal) Export zoom
config.description.export.zoom = Last used export zoom
+
+config.name.debuggerPort = Debugger port
+config.description.debuggerPort = Port used for socket debugging
+
+config.name.displayDebuggerInfo = (Internal) Display debugger info
+config.description.displayDebuggerInfo = Display info about debugger before switching it
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties
index 53031c72d..4889952a6 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties
@@ -253,5 +253,21 @@ config.description.packJavaScripts = Spou\u0161t\u011bt komprim\u00e1tor JavaScr
config.name.textExportExportFontFace = Pou\u017e\u00edvat font-face v SVG exportu
config.description.textExportExportFontFace = Vkl\u00e1dat soubory p\u00edsem do SVG pou\u017eit\u00edm font-face m\u00edsto tvar\u016f
-config.name.dumpView = Dump zobrazen\u00ed
-config.description.dumpView = Zobrazit dump raw dat
+config.name.lzmaFastBytes = LZMA fast bytes (platn\u00e9 hodnoty: 5-255)
+config.description.lzmaFastBytes = Parametr fast bytes LZMA enkoderu
+
+#temporary setting, do not translate it
+config.name.pluginPath = Plugin Path
+config.description.pluginPath = -
+
+config.name.deobfuscationMode = M\u00f3d deobfuskace
+config.description.deobfuscationMode = Typ deobfuskace
+
+config.name.showMethodBodyId = Zobrazovat id body metod
+config.description.showMethodBodyId = Zobrazuje id body metody pro import p\u0159es p\u0159\u00edkazovou \u0159\u00e1dku
+
+config.name.export.zoom = (Internal) P\u0159ibl\u00ed\u017een\u00ed exportu
+config.description.export.zoom = Naposledy pou\u017eit\u00e9 nastaven\u00ed p\u0159ibl\u00ed\u017een\u00ed
+
+config.name.debuggerPort = Port Debuggeru
+config.description.debuggerPort = Port pou\u017e\u00edvan\u00fd pro lad\u011bn\u00ed p\u0159es sockety
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog.properties
new file mode 100644
index 000000000..db2c4c63d
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog.properties
@@ -0,0 +1,19 @@
+# Copyright (C) 2014 JPEXS
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+dialog.title = Debugger Log
+button.clear = Clear
+button.close = Close
+msg.header = connection %clientid%:
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog_cs.properties
new file mode 100644
index 000000000..7cbef99b8
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/DebugLogDialog_cs.properties
@@ -0,0 +1,19 @@
+# Copyright (C) 2014 JPEXS
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+dialog.title = Log Debuggeru
+button.clear = Vypr\u00e1zdnit
+button.close = Zav\u0159\u00edt
+msg.header = spojen\u00ed %clientid%:
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties
index 4781e9f57..3d7753e0c 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/ExportDialog_cs.properties
@@ -66,3 +66,7 @@ frames.pdf = PDF
fonts = P\u00edsma
fonts.ttf = TTF
fonts.woff = WOFF
+
+zoom = P\u0159ibl\u00ed\u017een\u00ed
+zoom.percent = %
+zoom.invalid = Neplatn\u00e1 hodnota velikost.
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
index 0f075d0dc..2c9435d43 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties
@@ -514,4 +514,11 @@ button.snapshot.hint = Take snapshot into clipboard
editorTruncateWarning = Text truncated at position %chars% in debug mode.
-font.name.intag = Font name in tag:
\ No newline at end of file
+font.name.intag = Font name in tag:
+
+menu.debugger = Debugger
+menu.debugger.switch = Debugger
+menu.debugger.replacetrace = Replace trace calls
+menu.debugger.showlog = Show Log
+
+message.debugger = This SWF Debugger can only be used to print messages to log window, browser console or alerts.\r\nIt is NOT designed for features like step code, breakpoints etc.
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
index 056b19c00..55e0333ec 100644
--- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
+++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties
@@ -513,4 +513,11 @@ button.snapshot.hint = Sn\u00edmek do schr\u00e1nky
editorTruncateWarning = Text je o\u0159\u00edznut na pozici %chars% v lad\u00edc\u00edm m\u00f3du.
-font.name.intag = N\u00e1zev p\u00edsma v tagu:
\ No newline at end of file
+font.name.intag = N\u00e1zev p\u00edsma v tagu:
+
+menu.debugger = Debugger
+menu.debugger.switch = Debugger
+menu.debugger.replacetrace = Nahradit vol\u00e1n\u00ed trace
+menu.debugger.showlog = Zobrazit Log
+
+message.debugger = Tento SWF Debugger slou\u017e\u00ed jen k pos\u00edl\u00e1n\u00ed zpr\u00e1v do okna logu, konzole prohl\u00ed\u017ee\u010de nebo alert oken.\r\nNEN\u00cd ur\u010den pro krokov\u00e1n\u00ed k\u00f3du, breakpointy atd.
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog.properties
new file mode 100644
index 000000000..2408c3fa2
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog.properties
@@ -0,0 +1,20 @@
+# Copyright (C) 2014 JPEXS
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+dialog.title = Replace Trace function calls
+
+function.debugAlert = debugAlert - web browser javascript alert
+function.debugConsole = debugConsole - web browser javascript console.log
+function.debugSocket = debugSocket - socket connection to the decompiler
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog_cs.properties
new file mode 100644
index 000000000..6c4dce006
--- /dev/null
+++ b/src/com/jpexs/decompiler/flash/gui/locales/ReplaceTraceDialog_cs.properties
@@ -0,0 +1,20 @@
+# Copyright (C) 2014 JPEXS
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+dialog.title = Nahrazen\u00ed vol\u00e1n\u00ed funkce Trace
+
+function.debugAlert = debugAlert - javascriptov\u00e1 funkce alert webov\u00e9ho prohl\u00ed\u017ee\u010de
+function.debugConsole = debugConsole - javascriptov\u00e1 funkce console.log webov\u00e9ho prohl\u00ed\u017ee\u010de
+function.debugSocket = debugSocket - p\u0159ipojen\u00ed sockety k dekompil\u00e1toru
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java
index badf20b02..3896b82de 100644
--- a/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java
+++ b/src/com/jpexs/decompiler/flash/gui/player/FlashPlayerPanel.java
@@ -17,7 +17,10 @@
package com.jpexs.decompiler.flash.gui.player;
import com.jpexs.decompiler.flash.gui.FlashUnsupportedException;
+import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.javactivex.ActiveX;
+import com.jpexs.javactivex.ActiveXEvent;
+import com.jpexs.javactivex.ActiveXEventListener;
import com.jpexs.javactivex.example.controls.flash.ShockwaveFlash;
import com.sun.jna.Platform;
import java.awt.AWTException;
@@ -30,6 +33,8 @@ import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
*
@@ -107,6 +112,35 @@ public class FlashPlayerPanel extends Panel implements Closeable, MediaDisplay {
throw new FlashUnsupportedException();
}
flash = ActiveX.createObject(ShockwaveFlash.class, this);
+ flash.setAllowScriptAccess("always");
+ flash.setAllowNetworking("all");
+ flash.addFlashCallListener(new ActiveXEventListener() {
+
+ @Override
+ public void onEvent(ActiveXEvent axe) {
+ String req = (String) axe.args.get("request");
+ Matcher m = Pattern.compile("(.*)").matcher(req);
+ if (m.matches()) {
+ String funname = m.group(1);
+ String msg = m.group(2);
+ if (funname.equals("alert") || funname.equals("console.log")) {
+ if (Main.debugDialog != null) {
+ Main.debugDialog.log(funname + ":" + msg);
+ }
+ }
+ }
+ }
+ });
+ flash.addFSCommandListener(new ActiveXEventListener() {
+
+ @Override
+ public void onEvent(ActiveXEvent axe) {
+ System.out.println("Event:" + axe.name);
+ for (String k : axe.args.keySet()) {
+ System.out.println(k + "=" + axe.args.get(k));
+ }
+ }
+ });
}
public synchronized void stopSWF() {