Handling script traits as separate objects

This commit is contained in:
Jindra Petk
2013-05-05 12:50:24 +02:00
parent cb9c183b82
commit 7ddac525a2
9 changed files with 115 additions and 93 deletions

View File

@@ -18,6 +18,8 @@ package com.jpexs.decompiler.flash;
import SevenZip.Compression.LZMA.Encoder;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.gui.TreeLeafScript;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionGraphSource;
import com.jpexs.decompiler.flash.action.swf4.ActionEquals;
@@ -413,20 +415,16 @@ public class SWF {
}
for (int i = 0; i < abcTags.size(); i++) {
ABC abc = abcTags.get(i).getABC();
int scriptIndex = abc.findScriptByPath(className);
if (scriptIndex > -1) {
TreeLeafScript scr = abc.findScriptTraitByPath(className);
if (scr != null) {
String cnt = "";
if (abc.script_info.length > 1) {
cnt = "script " + (i + 1) + "/" + abc.script_info.length + " ";
}
String path = abc.script_info[scriptIndex].getPath(abc);
String packageName = path.substring(0, path.lastIndexOf("."));
if (packageName.equals("")) {
path = path.substring(1);
}
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + path + " ...";
Trait t = abc.script_info[scr.scriptIndex].traits.traits[scr.traitIndex];
String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + t.getPath(abc) + " ...";
informListeners("export", exStr);
abc.script_info[scriptIndex].export(abc, abcTags, outdir, isPcode, scriptIndex);
t.export(outdir, abc, abcTags, isPcode, scr.scriptIndex, -1,false);
return true;
}
}

View File

@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.gui.TreeLeafScript;
import com.jpexs.decompiler.flash.abc.types.*;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
@@ -565,18 +566,16 @@ public class ABC {
public void export(String directory, boolean pcode, List<ABCContainerTag> abcList, String abcStr) throws IOException {
for (int i = 0; i < script_info.length; i++) {
String path = script_info[i].getPath(this);
String packageName = path.substring(0, path.lastIndexOf("."));
if (packageName.equals("")) {
path = path.substring(1);
}
String cnt = "";
if (script_info.length > 1) {
cnt = "script " + (i + 1) + "/" + script_info.length + " ";
}
String exStr = "Exporting " + abcStr + cnt + path + " ...";
informListeners("export", exStr);
script_info[i].export(this, abcList, directory, pcode, i);
for (Trait t : script_info[i].traits.traits) {
String exStr = "Exporting " + abcStr + cnt + t.getPath(this) + " ...";
informListeners("export", exStr);
t.export(directory, this, abcList, pcode, i, -1, false);
}
}
}
@@ -889,13 +888,15 @@ public class ABC {
return -1;
}
public int findScriptByPath(String name) {
public TreeLeafScript findScriptTraitByPath(String name) {
for (int c = 0; c < script_info.length; c++) {
String s = script_info[c].getPath(this);
if (name.equals(s)) {
return c;
for (int t = 0; t < script_info[c].traits.traits.length; t++) {
Trait tr = script_info[c].traits.traits[t];
if (tr.getPath(this).equals(name)) {
return new TreeLeafScript(this, c, t);
}
}
}
return -1;
return null;
}
}

View File

@@ -17,6 +17,10 @@
package com.jpexs.decompiler.flash.abc.gui;
import com.jpexs.decompiler.flash.Main;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.abc.types.ScriptInfo;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.gui.View;
@@ -95,9 +99,20 @@ public class ClassesListTree extends JTree implements TreeSelectionListener {
public HashMap<String, TreeLeafScript> getTreeList(List<ABCContainerTag> list) {
HashMap<String, TreeLeafScript> ret = new HashMap<String, TreeLeafScript>();
for (ABCContainerTag tag : list) {
for (int i = 0; i < tag.getABC().script_info.length; i++) {
String path = tag.getABC().script_info[i].getPath(tag.getABC());
ret.put(path, new TreeLeafScript(tag.getABC(), i));
ABC abc = tag.getABC();
for (int i = 0; i < abc.script_info.length; i++) {
ScriptInfo script = abc.script_info[i];
for (int j = 0; j < script.traits.traits.length; j++) {
Trait t = script.traits.traits[j];
Multiname name = t.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
String packageName = ns.getName(abc.constants);
String objectName = name.getName(abc.constants, new ArrayList<String>());
String path = packageName + "." + objectName;
ret.put(path, new TreeLeafScript(abc, i, j));
}
}
}
return ret;
@@ -141,7 +156,7 @@ public class ClassesListTree extends JTree implements TreeSelectionListener {
abcPanel.navigator.setABC(abcList, scriptLeaf.abc);
abcPanel.navigator.setClassIndex(classIndex, scriptLeaf.scriptIndex);
abcPanel.setAbc(scriptLeaf.abc);
abcPanel.decompiledTextArea.setScript(scriptLeaf.scriptIndex, scriptLeaf.abc, abcList);
abcPanel.decompiledTextArea.setScript(scriptLeaf, abcList);
abcPanel.decompiledTextArea.setClassIndex(classIndex);
abcPanel.decompiledTextArea.setNoTrait();
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setCode("");

View File

@@ -38,7 +38,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
private List<Highlighting> classHighlights = new ArrayList<Highlighting>();
private Highlighting currentMethodHighlight;
private ABC abc;
private int scriptIndex = -1;
private TreeLeafScript script;
public int lastTraitIndex = 0;
private boolean ignoreCarret = false;
private boolean reset = false;
@@ -46,8 +46,8 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
private int classIndex = -1;
private boolean isStatic = false;
public int getScriptIndex() {
return scriptIndex;
public TreeLeafScript getScriptLeaf() {
return script;
}
public boolean getIsStatic() {
@@ -138,7 +138,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
for (Highlighting cm : classHighlights) {
if ((pos >= cm.startPos) && (pos < cm.startPos + cm.len)) {
classIndex = (int) cm.offset;
displayClass(classIndex, scriptIndex);
displayClass(classIndex, script.scriptIndex);
break;
}
}
@@ -155,7 +155,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
for (Highlighting th : traitHighlights) {
if ((pos >= th.startPos) && (pos < th.startPos + th.len)) {
lastTraitIndex = (int) th.offset;
if (abc != null) {
if ((abc != null) && (classIndex != -1)) {
t = abc.findTraitByTraitId(classIndex, lastTraitIndex);
isStatic = abc.isStaticTraitId(classIndex, lastTraitIndex);
if (t != null) {
@@ -227,7 +227,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
this.classHighlights = classHighlights;
}
}
private HashMap<Integer, BufferedClass> bufferedClasses = new HashMap<Integer, BufferedClass>();
private HashMap<TreeLeafScript, BufferedClass> bufferedClasses = new HashMap<TreeLeafScript, BufferedClass>();
public void gotoLastTrait() {
gotoTrait(lastTraitIndex);
@@ -285,8 +285,11 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
bufferedClasses.clear();
}
public void setScript(int scriptIndex, ABC abc, List<ABCContainerTag> abcList) {
public void setScript(TreeLeafScript scriptLeaf, List<ABCContainerTag> abcList) {
int scriptIndex = scriptLeaf.scriptIndex;
int scriptTraitIndex = scriptLeaf.traitIndex;
ScriptInfo script = null;
ABC abc = scriptLeaf.abc;
if (scriptIndex > -1) {
script = abc.script_info[scriptIndex];
}
@@ -294,22 +297,22 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
highlights = new ArrayList<Highlighting>();
traitHighlights = new ArrayList<Highlighting>();
methodHighlights = new ArrayList<Highlighting>();
this.scriptIndex = scriptIndex;
this.script = scriptLeaf;
return;
}
setText("//Please wait...");
String hilightedCode;
if (!bufferedClasses.containsKey(script)) {
hilightedCode = script.convert(abcList, abc, false, true, scriptIndex);
if (!bufferedClasses.containsKey(scriptLeaf)) {
hilightedCode = script.traits.traits[scriptTraitIndex].convertPackaged("", abcList, abc, false, false, scriptIndex, -1, true, new ArrayList<String>());
highlights = Highlighting.getInstrHighlights(hilightedCode);
traitHighlights = Highlighting.getTraitHighlights(hilightedCode);
methodHighlights = Highlighting.getMethodHighlights(hilightedCode);
classHighlights = Highlighting.getClassHighlights(hilightedCode);
hilightedCode = Highlighting.stripHilights(hilightedCode);
bufferedClasses.put(scriptIndex, new BufferedClass(hilightedCode, highlights, traitHighlights, methodHighlights, classHighlights));
bufferedClasses.put(scriptLeaf, new BufferedClass(hilightedCode, highlights, traitHighlights, methodHighlights, classHighlights));
} else {
BufferedClass bc = bufferedClasses.get(script);
BufferedClass bc = bufferedClasses.get(scriptLeaf);
hilightedCode = bc.text;
highlights = bc.highlights;
traitHighlights = bc.traitHighlights;
@@ -318,17 +321,17 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
}
this.abc = abc;
this.abcList = abcList;
this.scriptIndex = scriptIndex;
this.script = scriptLeaf;
setText(hilightedCode);
}
public void reloadClass() {
int ci = classIndex;
if (bufferedClasses.containsKey(scriptIndex)) {
bufferedClasses.remove(scriptIndex);
if (bufferedClasses.containsKey(script)) {
bufferedClasses.remove(script);
}
if ((scriptIndex != -1) && (abc != null)) {
setScript(scriptIndex, abc, abcList);
if ((script != null) && (abc != null)) {
setScript(script, abcList);
}
setNoTrait();
setClassIndex(ci);

View File

@@ -26,9 +26,11 @@ public class TreeLeafScript {
public ABC abc;
public int scriptIndex;
public int traitIndex = 0;
public TreeLeafScript(ABC abc, int scriptIndex) {
public TreeLeafScript(ABC abc, int scriptIndex, int traitIndex) {
this.abc = abc;
this.scriptIndex = scriptIndex;
this.traitIndex = traitIndex;
}
}

View File

@@ -18,11 +18,8 @@ package com.jpexs.decompiler.flash.abc.types;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitClass;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -45,43 +42,15 @@ public class ScriptInfo {
return "method_index=" + init_index + "\r\n" + traits.toString(abc, fullyQualifiedNames);
}
public String getPath(ABC abc) {
String packageName = "";
String scriptName = "";
int classCount = 0;
for (Trait t : traits.traits) {
Multiname name = t.getName(abc);
Namespace ns = name.getNamespace(abc.constants);
if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) {
packageName = ns.getName(abc.constants);
scriptName = name.getName(abc.constants, new ArrayList<String>());
if (t instanceof TraitClass) {
classCount++;
}
}
}
if (classCount > 1) {
scriptName = "[script]";
}
return packageName + "." + scriptName;
}
public String convert(List<ABCContainerTag> abcTags, ABC abc, boolean pcode, boolean highlighting, int scriptIndex) {
return traits.convert("", abcTags, abc, false, pcode, true, scriptIndex, -1, highlighting, new ArrayList<String>());
}
public void export(ABC abc, List<ABCContainerTag> abcList, String directory, boolean pcode, int scriptIndex) throws IOException {
String path = getPath(abc);
String packageName = path.substring(0, path.lastIndexOf("."));
String className = path.substring(path.lastIndexOf(".") + 1);
File outDir = new File(directory + File.separatorChar + packageName.replace('.', File.separatorChar));
if (!outDir.exists()) {
outDir.mkdirs();
for (Trait t : traits.traits) {
t.export(directory, abc, abcList, pcode, scriptIndex, -1, false);
}
String fileName = outDir.toString() + File.separator + className + ".as";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(convert(abcList, abc, pcode, false, scriptIndex).getBytes());
fos.close();
}
}

View File

@@ -21,7 +21,11 @@ import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.Namespace;
import com.jpexs.decompiler.flash.helpers.Helper;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public abstract class Trait implements Serializable {
@@ -140,4 +144,27 @@ public abstract class Trait implements Serializable {
}
public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc);
public String getPath(ABC abc) {
Multiname name = getName(abc);
Namespace ns = name.getNamespace(abc.constants);
String packageName = ns.getName(abc.constants);
String objectName = name.getName(abc.constants, new ArrayList<String>());
return packageName + "." + objectName;
}
public void export(String directory, ABC abc, List<ABCContainerTag> abcList, boolean pcode, int scriptIndex, int classIndex, boolean isStatic) throws IOException {
Multiname name = getName(abc);
Namespace ns = name.getNamespace(abc.constants);
String packageName = ns.getName(abc.constants);
String objectName = name.getName(abc.constants, new ArrayList<String>());
File outDir = new File(directory + File.separatorChar + packageName.replace('.', File.separatorChar));
if (!outDir.exists()) {
outDir.mkdirs();
}
String fileName = outDir.toString() + File.separator + objectName + ".as";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(convertPackaged("", abcList, abc, isStatic, pcode, scriptIndex, classIndex, false, new ArrayList<String>()).getBytes());
fos.close();
}
}

View File

@@ -326,16 +326,19 @@ public class TraitClass extends Trait implements TraitWithSlot {
List<String> namesInThisPackage = new ArrayList<String>();
for (ABCContainerTag tag : abcTags) {
for (ScriptInfo si : tag.getABC().script_info) {
String spath = si.getPath(tag.getABC());
String pkg = "";
String name = spath;
if (spath.contains(".")) {
pkg = spath.substring(0, spath.lastIndexOf("."));
name = spath.substring(spath.lastIndexOf(".") + 1);
}
if (pkg.equals(packageName)) {
namesInThisPackage.add(name);
for (Trait t : si.traits.traits) {
String spath = t.getPath(tag.getABC());
String pkg = "";
String name = spath;
if (spath.contains(".")) {
pkg = spath.substring(0, spath.lastIndexOf("."));
name = spath.substring(spath.lastIndexOf(".") + 1);
}
if (pkg.equals(packageName)) {
namesInThisPackage.add(name);
}
}
}
}
//imports

View File

@@ -1357,8 +1357,12 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
if (abcPanel != null) {
for (int i = 0; i < tlsList.size(); i++) {
TreeLeafScript tls = tlsList.get(i);
Main.startWork("Exporting " + (i + 1) + "/" + tlsList.size() + " " + tls.abc.script_info[tls.scriptIndex].getPath(tls.abc) + " ...");
tls.abc.script_info[tls.scriptIndex].export(tls.abc, abcPanel.list, selFile, isPcode, tls.scriptIndex);
for (Trait t : tls.abc.script_info[tls.scriptIndex].traits.traits) {
Main.startWork("Exporting " + (i + 1) + "/" + tlsList.size() + " " + t.getPath(tls.abc) + " ...");
t.export(selFile, tls.abc, abcList, isPcode, tls.scriptIndex, -1, false);
}
}
} else {
List<TagNode> allNodes = new ArrayList<TagNode>();
@@ -1483,7 +1487,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
} else {
int bi = abcPanel.detailPanel.methodTraitPanel.methodCodePanel.getBodyIndex();
if (bi != -1) {
cnt += abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptIndex(), abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
cnt += abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptLeaf().scriptIndex, abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
}
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setBodyIndex(bi, abcPanel.abc);
}
@@ -1587,9 +1591,9 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_DEAD_CODE) {
abcPanel.abc.bodies[bi].removeDeadCode(abcPanel.abc.constants);
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_REMOVE_TRAPS) {
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptIndex(), abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptLeaf().scriptIndex, abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
} else if (deobfuscationDialog.codeProcessingLevel.getValue() == DeobfuscationDialog.LEVEL_RESTORE_CONTROL_FLOW) {
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptIndex(), abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
abcPanel.abc.bodies[bi].removeTraps(abcPanel.abc.constants, abcPanel.abc, abcPanel.decompiledTextArea.getScriptLeaf().scriptIndex, abcPanel.decompiledTextArea.getClassIndex(), abcPanel.decompiledTextArea.getIsStatic());
abcPanel.abc.bodies[bi].restoreControlFlow(abcPanel.abc.constants);
}
}
@@ -1675,7 +1679,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
abcPanel.navigator.setABC(abcList, scriptLeaf.abc);
abcPanel.navigator.setClassIndex(classIndex, scriptLeaf.scriptIndex);
abcPanel.setAbc(scriptLeaf.abc);
abcPanel.decompiledTextArea.setScript(scriptLeaf.scriptIndex, scriptLeaf.abc, abcList);
abcPanel.decompiledTextArea.setScript(scriptLeaf, abcList);
abcPanel.decompiledTextArea.setClassIndex(classIndex);
abcPanel.decompiledTextArea.setNoTrait();
abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setCode("");