diff --git a/src/com/jpexs/decompiler/flash/action/Action.java b/src/com/jpexs/decompiler/flash/action/Action.java index 41e2468d5..29c62a6ea 100644 --- a/src/com/jpexs/decompiler/flash/action/Action.java +++ b/src/com/jpexs/decompiler/flash/action/Action.java @@ -192,10 +192,9 @@ public class Action implements GraphSourceItem { * Gets all addresses which are referenced from the list of actions * * @param list List of actions - * @param version SWF version * @return List of addresses */ - public static List getActionsAllRefs(List list, int version) { + public static List getActionsAllRefs(List list) { List ret = new ArrayList<>(); for (Action a : list) { a.getRef(ret); @@ -211,13 +210,8 @@ public class Action implements GraphSourceItem { * Sets address of this instruction * * @param address Address - * @param version SWF version */ - public final void setAddress(long address, int version) { - setAddress(address, version, true); - } - - public void setAddress(long address, int version, boolean recursive) { + public void setAddress(long address) { this.address = address; } @@ -375,7 +369,7 @@ public class Action implements GraphSourceItem { public static void setActionsAddresses(List list, long baseAddress, int version) { long offset = baseAddress; for (Action a : list) { - a.setAddress(offset, version); + a.setAddress(offset); offset += a.getBytes(version).length; } } @@ -411,7 +405,7 @@ public class Action implements GraphSourceItem { */ private static GraphTextWriter actionsToString(List listeners, long address, List list, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer, String path) { long offset; - List importantOffsets = getActionsAllRefs(list, version); + List importantOffsets = getActionsAllRefs(list); /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); if (!cps.isEmpty()) { setConstantPool(list, cps.get(cps.size() - 1)); diff --git a/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/src/com/jpexs/decompiler/flash/action/ActionListReader.java index a86beb86e..77e1610e6 100644 --- a/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -131,7 +131,7 @@ public class ActionListReader { Map nextOffsets = new HashMap<>(); Action entryAction = readActionListAtPos(listeners, cpool, sis, actionMap, nextOffsets, - ip, ip, endIp, version, path, false, new ArrayList()); + ip, 0, endIp, path, false, new ArrayList()); List actions = new ArrayList<>(); if (actionMap.isEmpty()) { @@ -161,7 +161,7 @@ public class ActionListReader { if (nextIndex != -1 && nextOffset != nextIndex) { if (!action.isExit() && !(action instanceof ActionJump)) { ActionJump jump = new ActionJump(0); - jump.setAddress(action.getAddress(), version); + jump.setAddress(action.getAddress()); int size = jump.getTotalActionLength(); jump.setJumpOffset((int) (nextOffset - action.getAddress() - size)); actions.add(jump); @@ -181,7 +181,7 @@ public class ActionListReader { Action lastAction = actions.get(actions.size() - 1); Action aEnd = new ActionEnd(); if (!(lastAction instanceof ActionEnd)) { - aEnd.setAddress(endAddress, version); + aEnd.setAddress(endAddress); actions.add(aEnd); } else { endAddress -= aEnd.getTotalActionLength(); @@ -206,6 +206,19 @@ public class ActionListReader { return actions; } + public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { + ConstantPool cpool = new ConstantPool(); + + // Map of the actions. Use TreeMap to sort the keys in ascending order + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + readActionListAtPos(new ArrayList(), cpool, + sis, actionMap, nextOffsets, + startIp, startIp, endIp, "", false, new ArrayList()); + + return new ArrayList<>(actionMap.values()); + } + /** * Reads list of actions from the stream. Reading ends with * ActionEndFlag(=0) or end of the stream. @@ -230,7 +243,7 @@ public class ActionListReader { List retdups = new ArrayList<>(endIp); for (int i = 0; i < endIp; i++) { Action a = new ActionNop(); - a.setAddress(i, version); + a.setAddress(i); retdups.add(a); } List actionMap = new ArrayList<>(endIp); @@ -370,7 +383,7 @@ public class ActionListReader { private static long updateAddresses(List actions, long address, int version) { for (int i = 0; i < actions.size(); i++) { Action a = actions.get(i); - a.setAddress(address, version); + a.setAddress(address); int length = a.getBytes(version).length; if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { // placeholder for jump action @@ -457,7 +470,7 @@ public class ActionListReader { if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { ActionJump aJump = new ActionJump(0); aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); - aJump.setAddress(a.getAddress(), version); + aJump.setAddress(a.getAddress()); replaceJumpTargets(jumps, a, aJump); replaceContainerLastActions(containerLastActions, a, aJump); a = aJump; @@ -571,7 +584,7 @@ public class ActionListReader { private static Action readActionListAtPos(List listeners, ConstantPool cpool, SWFInputStream sis, Map actions, Map nextOffsets, - long ip, long startIp, long endIp, int version, String path, boolean indeterminate, List visitedContainers) throws IOException { + long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { Action entryAction = null; @@ -584,6 +597,10 @@ public class ActionListReader { jumpQueue.add(ip); while (!jumpQueue.isEmpty()) { ip = jumpQueue.remove(); + if (ip < startIp) { + continue; + } + while (endIp == -1 || endIp > ip) { sis.seek((int) ip); @@ -598,7 +615,7 @@ public class ActionListReader { if (a instanceof ActionNop) { ActionJump aJump = new ActionJump(0); int jumpLength = aJump.getTotalActionLength(); - aJump.setAddress(a.getAddress(), version); + aJump.setAddress(a.getAddress()); aJump.setJumpOffset(actionLengthWithHeader - jumpLength); a = aJump; actionLengthWithHeader = a.getTotalActionLength(); @@ -622,7 +639,7 @@ public class ActionListReader { listeners.get(i).progress(AppStrings.translate("disassemblingProgress.reading"), pos, length); } - a.setAddress(ip, version, false); + a.setAddress(ip); if (a instanceof ActionPush && cpool != null) { ((ActionPush) a).constantPool = cpool.constants; @@ -654,7 +671,7 @@ public class ActionListReader { //long endIp2 = ip + actionLengthWithHeader + size; readActionListAtPos(listeners, cpool, sis, actions, nextOffsets, - ip2, startIp, endIp, version, newPath, indeterminate, visitedContainers); + ip2, startIp, endIp, newPath, indeterminate, visitedContainers); actionLengthWithHeader += size; } } @@ -815,10 +832,10 @@ public class ActionListReader { if (a instanceof ActionNop) { int prevPos = (int) a.getAddress(); a = new ActionNop(); - a.setAddress(prevPos, version); + a.setAddress(prevPos); nopos++; if (nopos > 0) { - a.setAddress(a.getAddress() + 1, version); + a.setAddress(a.getAddress() + 1); } } diff --git a/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java b/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java index fd4c1876d..9d0590d3c 100644 --- a/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java +++ b/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java @@ -138,7 +138,7 @@ public class ASMParser { Stack containers = new Stack<>(); ActionConstantPool cpool = new ActionConstantPool(constantPool); - cpool.setAddress(address, version, false); + cpool.setAddress(address); address += cpool.getBytes(version).length; list.add(cpool); @@ -179,10 +179,10 @@ public class ASMParser { a = null; } if (a instanceof ActionNop) { - a.setAddress(address, version, false); + a.setAddress(address); address += 1; } else if (a != null) { - a.setAddress(address, version, false); + a.setAddress(address); address += a.getBytes(version).length; } if (a instanceof GraphSourceItemContainer) { diff --git a/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java b/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java index a93fd5b42..c620391b0 100644 --- a/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java +++ b/src/com/jpexs/decompiler/flash/action/swf5/ActionDefineFunction.java @@ -145,14 +145,6 @@ public class ActionDefineFunction extends Action implements GraphSourceItemConta return surroundWithAction(baos.toByteArray(), version).length; } - @Override - public void setAddress(long address, int version, boolean recursive) { - super.setAddress(address, version, recursive); - if (recursive) { - //Action.setActionsAddresses(, address + getPreLen(version), version); - } - } - @Override public String getASMSource(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode) { StringBuilder paramStr = new StringBuilder(); diff --git a/src/com/jpexs/decompiler/flash/action/swf5/ActionWith.java b/src/com/jpexs/decompiler/flash/action/swf5/ActionWith.java index 0b38a621d..ab0aebf0e 100644 --- a/src/com/jpexs/decompiler/flash/action/swf5/ActionWith.java +++ b/src/com/jpexs/decompiler/flash/action/swf5/ActionWith.java @@ -60,11 +60,6 @@ public class ActionWith extends Action implements GraphSourceItemContainer { lexBlockOpen(lexer); } - @Override - public void setAddress(long address, int version, boolean recursive) { - super.setAddress(address, version, recursive); - } - @Override public byte[] getBytes(int version) { ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); diff --git a/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java b/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java index 5444ed511..44c594038 100644 --- a/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java +++ b/src/com/jpexs/decompiler/flash/action/swf7/ActionDefineFunction2.java @@ -225,14 +225,6 @@ public class ActionDefineFunction2 extends Action implements GraphSourceItemCont return surroundWithAction(baos.toByteArray(), version).length; } - @Override - public void setAddress(long address, int version, boolean recursive) { - super.setAddress(address, version, recursive); - if (recursive) { - //Action.setActionsAddresses(code, address + getPreLen(version), version); - } - } - @Override public GraphTextWriter getASMSourceReplaced(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode, GraphTextWriter writer) { List oldParamNames = paramNames; diff --git a/src/com/jpexs/decompiler/flash/action/swf7/ActionTry.java b/src/com/jpexs/decompiler/flash/action/swf7/ActionTry.java index dc386ca1e..b98d214de 100644 --- a/src/com/jpexs/decompiler/flash/action/swf7/ActionTry.java +++ b/src/com/jpexs/decompiler/flash/action/swf7/ActionTry.java @@ -82,11 +82,6 @@ public class ActionTry extends Action implements GraphSourceItemContainer { } } - @Override - public void setAddress(long address, int version, boolean recursive) { - super.setAddress(address, version, recursive); - } - @Override public byte[] getBytes(int version) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java index 3913d923c..50e2175b9 100644 --- a/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java +++ b/src/com/jpexs/decompiler/flash/gui/dumpview/DumpTree.java @@ -16,6 +16,10 @@ */ package com.jpexs.decompiler.flash.gui.dumpview; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionListReader; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.dumpview.DumpInfo; import com.jpexs.decompiler.flash.dumpview.DumpInfoSwfNode; @@ -31,9 +35,9 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.File; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; @@ -58,6 +62,7 @@ public class DumpTree extends JTree implements ActionListener { private static final String ACTION_CLOSE_SWF = "CLOSESWF"; private static final String ACTION_EXPAND_RECURSIVE = "EXPANDRECURSIVE"; private static final String ACTION_SAVE_TO_FILE = "SAVETOFILE"; + private static final String ACTION_PARSE_ACTIONS = "PARSEACTIONS"; private final MainPanel mainPanel; @@ -120,6 +125,11 @@ public class DumpTree extends JTree implements ActionListener { closeSelectionMenuItem.addActionListener(this); contextPopupMenu.add(closeSelectionMenuItem); + final JMenuItem parseActionsMenuItem = new JMenuItem(mainPanel.translate("contextmenu.parseActions")); + parseActionsMenuItem.setActionCommand(ACTION_PARSE_ACTIONS); + parseActionsMenuItem.addActionListener(this); + contextPopupMenu.add(parseActionsMenuItem); + addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -138,6 +148,7 @@ public class DumpTree extends JTree implements ActionListener { closeSelectionMenuItem.setVisible(false); expandRecursiveMenuItem.setVisible(false); saveToFileMenuItem.setVisible(false); + parseActionsMenuItem.setVisible(false); if (paths.length == 1) { DumpInfo treeNode = (DumpInfo) paths[0].getLastPathComponent(); @@ -150,6 +161,10 @@ public class DumpTree extends JTree implements ActionListener { saveToFileMenuItem.setVisible(true); } + if (treeNode.name.equals("actionBytes") && treeNode.getChildCount() == 0) { + parseActionsMenuItem.setVisible(true); + } + TreeModel model = getModel(); expandRecursiveMenuItem.setVisible(model.getChildCount(treeNode) > 0); } @@ -193,9 +208,32 @@ public class DumpTree extends JTree implements ActionListener { } } break; + case ACTION_PARSE_ACTIONS: { + TreePath[] paths = getSelectionPaths(); + DumpInfo dumpInfo = (DumpInfo) paths[0].getLastPathComponent(); + SWF swf = DumpInfoSwfNode.getSwfNode(dumpInfo).getSwf(); + byte[] data = swf.uncompressedData; + int prevLength = (int) dumpInfo.startByte; + try { + SWFInputStream rri = new SWFInputStream(swf, data); + if (prevLength != 0) { + rri.seek(prevLength); + } + List actions = ActionListReader.getOriginalActions(rri, prevLength, (int) dumpInfo.getEndByte()); + for (Action action : actions) { + DumpInfo di = new DumpInfo(action.toString(), "Action", null, action.getAddress(), action.getTotalActionLength()); + di.parent = dumpInfo; + dumpInfo.getChildInfos().add(di); + } + } catch (IOException | InterruptedException ex) { + Logger.getLogger(DumpTree.class.getName()).log(Level.SEVERE, null, ex); + } + } + break; case ACTION_CLOSE_SWF: { Main.closeFile(mainPanel.getCurrentSwfList()); } + break; } } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index d88cf6bdf..5e5341706 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -510,3 +510,4 @@ header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twips header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% pixels contextmenu.saveToFile = Save to File +contextmenu.parseActions = Parse actions diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 0169867f8..5124c5040 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -510,3 +510,4 @@ header.displayrect.value.twips = %xmin%,%ymin% => %xmax%,%ymax% twip header.displayrect.value.pixels = %xmin%,%ymin% => %xmax%,%ymax% k\u00e9ppont contextmenu.saveToFile = Ment\u00e9s f\u00e1jlba +contextmenu.parseActions = Action-\u00f6k elemz\u00e9se