diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index e76171418..f428e1ab3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash; import SevenZip.Compression.LZMA.Encoder; import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.ActionGraphSource; @@ -559,10 +560,20 @@ public class SWF { public final void addEventListener(EventListener listener) { listeners.add(listener); + for (Tag t : tags) { + if (t instanceof ABCContainerTag) { + (((ABCContainerTag) t).getABC()).addEventListener(listener); + } + } } public final void removeEventListener(EventListener listener) { listeners.remove(listener); + for (Tag t : tags) { + if (t instanceof ABCContainerTag) { + (((ABCContainerTag) t).getABC()).removeEventListener(listener); + } + } } protected void informListeners(String event, Object data) { @@ -1057,6 +1068,7 @@ public class SWF { private HashSet allVariableNamesStr = new HashSet<>(); private List allFunctions = new ArrayList<>(); private HashMap allStrings = new HashMap<>(); + private HashMap usageTypes = new HashMap<>(); private String fooString(String orig, boolean firstUppercase, int rndSize) { boolean exists; @@ -1098,7 +1110,7 @@ public class SWF { return ret; } - public String deobfuscateName(HashMap namesMap, String s, boolean firstUppercase) { + public String deobfuscateName(HashMap namesMap, String s, boolean firstUppercase, String usageType, RenameType renameType) { boolean isValid = true; if (isReserved(s)) { isValid = false; @@ -1119,19 +1131,36 @@ public class SWF { isValid = false; } } - if (!isValid) { if (namesMap.containsKey(s)) { return namesMap.get(s); } else { - String ret = fooString(s, firstUppercase, DEFAULT_FOO_SIZE); + Integer cnt = typeCounts.get(usageType); + if (cnt == null) { + cnt = 0; + } + + String ret; + if (renameType == RenameType.TYPENUMBER) { + + boolean found; + do { + found = false; + cnt++; + ret = usageType + "_" + cnt; + found = allVariableNamesStr.contains(ret); + } while (found); + typeCounts.put(usageType, cnt); + } else { + ret = fooString(s, firstUppercase, DEFAULT_FOO_SIZE); + } return ret; } } return null; } - private static void getVariables(ConstantPool constantPool, List localData, Stack stack, List output, ActionGraphSource code, int ip, int lastIp, HashMap variables, List functions, HashMap strings, List visited) { + private static void getVariables(ConstantPool constantPool, List localData, Stack stack, List output, ActionGraphSource code, int ip, int lastIp, HashMap variables, List functions, HashMap strings, List visited, HashMap usageTypes) { boolean debugMode = false; while ((ip > -1) && ip < code.size()) { if (visited.contains(ip)) { @@ -1149,6 +1178,7 @@ public class SWF { continue; } + String usageType = "name"; GraphTargetItem name = null; if ((ins instanceof ActionGetVariable) || (ins instanceof ActionGetMember) @@ -1160,6 +1190,21 @@ public class SWF { name = stack.peek(); } + if ((ins instanceof ActionGetVariable) || (ins instanceof ActionDefineLocal2)) { + usageType = "variable"; + } + if (ins instanceof ActionGetMember) { + usageType = "member"; + } + if ((ins instanceof ActionNewMethod) || (ins instanceof ActionNewObject)) { + usageType = "class"; + } + if (ins instanceof ActionCallMethod) { + usageType = "function"; //can there be method? + } + if (ins instanceof ActionCallFunction) { + usageType = "function"; + } if ((ins instanceof ActionDefineFunction) || (ins instanceof ActionDefineFunction2)) { functions.add(ins); @@ -1176,18 +1221,33 @@ public class SWF { ip = code.adr2pos(addr); addr += size; int nextip = code.adr2pos(addr); - getVariables(variables, functions, strings, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap(), new HashMap(), new HashMap()), 0); + getVariables(variables, functions, strings, usageTypes, new ActionGraphSource(code.getActions().subList(ip, nextip), code.version, new HashMap(), new HashMap(), new HashMap()), 0); ip = nextip; } - ((GraphSourceItemContainer) ins).translateContainer(new ArrayList>(), stack, output, new HashMap(), new HashMap(), new HashMap()); + List> r = new ArrayList<>(); + r.add(new ArrayList()); + r.add(new ArrayList()); + r.add(new ArrayList()); + ((GraphSourceItemContainer) ins).translateContainer(r, stack, output, new HashMap(), new HashMap(), new HashMap()); + ip++; continue; } if ((ins instanceof ActionSetVariable) || (ins instanceof ActionSetMember) || (ins instanceof ActionDefineLocal)) { name = stack.get(stack.size() - 2); } + + if ((ins instanceof ActionSetVariable) || (ins instanceof ActionDefineLocal)) { + usageType = "variable"; + } + + if (ins instanceof ActionSetMember) { + usageType = "member"; + } + if (name instanceof DirectValueTreeItem) { variables.put((DirectValueTreeItem) name, constantPool); + usageTypes.put((DirectValueTreeItem) name, usageType); } //for..in return @@ -1230,7 +1290,7 @@ public class SWF { @SuppressWarnings("unchecked") Stack brStack = (Stack) stack.clone(); if (b >= 0) { - getVariables(constantPool, localData, brStack, output, code, b, ip, variables, functions, strings, visited); + getVariables(constantPool, localData, brStack, output, code, b, ip, variables, functions, strings, visited, usageTypes); } else { if (debugMode) { System.out.println("Negative branch:" + b); @@ -1244,29 +1304,38 @@ public class SWF { }; } - private static void getVariables(HashMap variables, List functions, HashMap strings, ActionGraphSource code, int addr) { + private static void getVariables(HashMap variables, List functions, HashMap strings, HashMap usageType, ActionGraphSource code, int addr) { List localData = Helper.toList(new HashMap(), new HashMap(), new HashMap()); try { - getVariables(null, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, variables, functions, strings, new ArrayList()); + getVariables(null, localData, new Stack(), new ArrayList(), code, code.adr2pos(addr), 0, variables, functions, strings, new ArrayList(), usageType); } catch (Exception ex) { Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Getting variables error", ex); } } - private HashMap getVariables(HashMap variables, List functions, HashMap strings, ASMSource src) { + private HashMap getVariables(HashMap variables, List functions, HashMap strings, HashMap usageType, ASMSource src) { HashMap ret = new HashMap<>(); List actions = src.getActions(version); actionsMap.put(src, actions); - getVariables(variables, functions, strings, new ActionGraphSource(actions, version, new HashMap(), new HashMap(), new HashMap()), 0); + getVariables(variables, functions, strings, usageType, new ActionGraphSource(actions, version, new HashMap(), new HashMap(), new HashMap()), 0); return ret; } private HashMap> actionsMap = new HashMap<>(); private void getVariables(List objs, String path) { + List processed = new ArrayList<>(); for (Object o : objs) { if (o instanceof ASMSource) { - informListeners("getVariables", path + "/" + o.toString()); - getVariables(allVariableNames, allFunctions, allStrings, (ASMSource) o); + String infPath = path + "/" + o.toString(); + int pos = 1; + String infPath2 = infPath; + while (processed.contains(infPath2)) { + pos++; + infPath2 = infPath + "[" + pos + "]"; + } + processed.add(infPath2); + informListeners("getVariables", infPath2); + getVariables(allVariableNames, allFunctions, allStrings, usageTypes, (ASMSource) o); } if (o instanceof Container) { getVariables(((Container) o).getSubItems(), path + "/" + o.toString()); @@ -1274,11 +1343,11 @@ public class SWF { } } - public int deobfuscateAS3Identifiers() { + public int deobfuscateAS3Identifiers(RenameType renameType) { HashMap namesMap = new HashMap<>(); for (Tag tag : tags) { if (tag instanceof ABCContainerTag) { - ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(namesMap); + ((ABCContainerTag) tag).getABC().deobfuscateIdentifiers(namesMap, renameType); } } for (Tag tag : tags) { @@ -1318,55 +1387,61 @@ public class SWF { } return namesMap.size(); } + HashMap typeCounts = new HashMap<>(); - public int deobfuscateAS2Identifiers() { + public int deobfuscateAS2Identifiers(RenameType renameType) { actionsMap = new HashMap<>(); allFunctions = new ArrayList<>(); allVariableNames = new HashMap<>(); allStrings = new HashMap<>(); + List objs = new ArrayList<>(); int ret = 0; objs.addAll(tags); getVariables(objs, ""); + informListeners("deobfuscate", ""); + int fc = 0; + for (DirectValueTreeItem ti : allVariableNames.keySet()) { + String name = ti.toStringNoH(allVariableNames.get(ti)); + allVariableNamesStr.add(name); + } for (GraphSourceItem fun : allFunctions) { + fc++; + informListeners("deobfuscate", "function " + fc + "/" + allFunctions.size()); if (fun instanceof ActionDefineFunction) { ActionDefineFunction f = (ActionDefineFunction) fun; - String changed = deobfuscateName(deobfuscated, f.functionName, false); + String changed = deobfuscateName(deobfuscated, f.functionName, false, "function", renameType); if (changed != null) { f.replacedFunctionName = changed; } } if (fun instanceof ActionDefineFunction2) { ActionDefineFunction2 f = (ActionDefineFunction2) fun; - String changed = deobfuscateName(deobfuscated, f.functionName, false); + String changed = deobfuscateName(deobfuscated, f.functionName, false, "function", renameType); if (changed != null) { f.replacedFunctionName = changed; } } } - for (DirectValueTreeItem ti : allVariableNames.keySet()) { - String name = ti.toStringNoH(allVariableNames.get(ti)); - allVariableNamesStr.add(name); - } - //Ommit variables from all strings - HashMap stringsNoVar = new HashMap<>(); + + HashSet stringsNoVarH = new HashSet<>(); for (DirectValueTreeItem ti : allStrings.keySet()) { if (!allVariableNames.containsKey(ti)) { - stringsNoVar.put(ti, allStrings.get(ti)); + stringsNoVarH.add(System.identityHashCode(allStrings.get(ti)) + "_" + ti.toStringNoH(allStrings.get(ti))); } } + + int vc = 0; for (DirectValueTreeItem ti : allVariableNames.keySet()) { + vc++; + informListeners("deobfuscate", "variable " + vc + "/" + allVariableNames.size()); String name = ti.toStringNoH(allVariableNames.get(ti)); - String changed = deobfuscateName(deobfuscated, name, false); + String changed = deobfuscateName(deobfuscated, name, false, usageTypes.get(ti), renameType); if (changed != null) { boolean addNew = false; - for (DirectValueTreeItem snv : stringsNoVar.keySet()) { - if (stringsNoVar.get(snv) == allVariableNames.get(ti)) { //Same constantpool - if (snv.toStringNoH(stringsNoVar.get(snv)).equals(name)) { //Same string - addNew = true; - break; - } - } + String h = System.identityHashCode(allVariableNames.get(ti)) + "_" + name; + if (stringsNoVarH.contains(h)) { + addNew = true; } ActionPush pu = (ActionPush) ti.src; if (pu.replacement == null) { @@ -1376,6 +1451,12 @@ public class SWF { if (pu.replacement.get(ti.pos) instanceof ConstantIndex) { ConstantIndex ci = (ConstantIndex) pu.replacement.get(ti.pos); ConstantPool pool = allVariableNames.get(ti); + if (pool == null) { + continue; + } + if (pool.constants == null) { + continue; + } if (addNew) { pool.constants.add(changed); ci.index = pool.constants.size() - 1; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java index 40412ca9b..c426dd7b5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -23,6 +23,8 @@ import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.types.*; 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.TraitFunction; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.abc.types.traits.Traits; @@ -33,6 +35,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.ExecutorService; @@ -111,21 +114,90 @@ public class ABC { return ret; } - public void deobfuscateIdentifiers(HashMap namesMap) { + private void setStringUsageType(Map ret, int strIndex, String usageType) { + if (ret.containsKey(strIndex)) { + if (!ret.get(strIndex).equals(usageType)) { + ret.put(strIndex, "name"); + } + } else { + ret.put(strIndex, usageType); + } + } + + private void getStringUsageTypes(Map ret, Traits traits) { + for (Trait t : traits.traits) { + int strIndex = constants.constant_multiname[t.name_index].name_index; + String usageType = ""; + if (t instanceof TraitClass) { + TraitClass tc = (TraitClass) t; + getStringUsageTypes(ret, class_info[tc.class_info].static_traits); + getStringUsageTypes(ret, instance_info[tc.class_info].instance_traits); + + if (instance_info[tc.class_info].name_index != 0) { + setStringUsageType(ret, constants.constant_multiname[instance_info[tc.class_info].name_index].name_index, "class"); + } + if (instance_info[tc.class_info].super_index != 0) { + setStringUsageType(ret, constants.constant_multiname[instance_info[tc.class_info].super_index].name_index, "class"); + } + + usageType = "class"; + } + if (t instanceof TraitMethodGetterSetter) { + TraitMethodGetterSetter tm = (TraitMethodGetterSetter) t; + usageType = "method"; + MethodBody body = findBody(tm.method_info); + if (body != null) { + getStringUsageTypes(ret, body.traits); + } + } + if (t instanceof TraitFunction) { + TraitFunction tf = (TraitFunction) t; + MethodBody body = findBody(tf.method_info); + if (body != null) { + getStringUsageTypes(ret, body.traits); + } + usageType = "function"; + } + if (t instanceof TraitSlotConst) { + TraitSlotConst ts = (TraitSlotConst) t; + if (ts.isVar()) { + usageType = "var"; + } + if (ts.isConst()) { + usageType = "const"; + } + } + setStringUsageType(ret, strIndex, usageType); + } + } + + public void getStringUsageTypes(Map ret) { + for (ScriptInfo script : script_info) { + getStringUsageTypes(ret, script.traits); + } + } + + public void deobfuscateIdentifiers(HashMap namesMap, RenameType renameType) { Set stringUsages = getStringUsages(); + Map stringUsageTypes = new HashMap<>(); + informListeners("deobfuscate", "Getting usage types..."); + getStringUsageTypes(stringUsageTypes); for (int i = 1; i < instance_info.length; i++) { + informListeners("deobfuscate", "class " + i + "/" + instance_info.length); if (instance_info[i].name_index != 0) { - constants.constant_multiname[instance_info[i].name_index].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true); + constants.constant_multiname[instance_info[i].name_index].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[instance_info[i].name_index].name_index, true, renameType); } if (instance_info[i].super_index != 0) { - constants.constant_multiname[instance_info[i].super_index].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true); + constants.constant_multiname[instance_info[i].super_index].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[instance_info[i].super_index].name_index, true, renameType); } } for (int i = 1; i < constants.constant_multiname.length; i++) { - constants.constant_multiname[i].name_index = deobfuscateName(stringUsages, namesMap, constants.constant_multiname[i].name_index, false); + informListeners("deobfuscate", "name " + i + "/" + constants.constant_multiname.length); + constants.constant_multiname[i].name_index = deobfuscateName(stringUsageTypes, stringUsages, namesMap, constants.constant_multiname[i].name_index, false, renameType); } for (int i = 1; i < constants.constant_namespace.length; i++) { - constants.constant_namespace[i].name_index = deobfuscateNameSpace(stringUsages, namesMap, constants.constant_namespace[i].name_index); + informListeners("deobfuscate", "namespace " + i + "/" + constants.constant_namespace.length); + constants.constant_namespace[i].name_index = deobfuscateNameSpace(stringUsageTypes, stringUsages, namesMap, constants.constant_namespace[i].name_index, renameType); } } @@ -654,7 +726,7 @@ public class ABC { "extends", "false", "finally", "for", "function", "get", "if", "implements", "import", "in", "instanceof", "interface", "internal", "is", "native", "new", "null", "override", "package", "private", "protected", "public", "return", "set", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while", - "with", "dynamic", "default", "final", "in"}; + "with", "dynamic", "default", "final", "in", "static"}; public static final String validFirstCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; public static final String validNextCharacters = validFirstCharacters + "0123456789"; public static final String validNsCharacters = ".:$"; @@ -663,26 +735,42 @@ public class ABC { private HashMap deobfuscated = new HashMap<>(); private Random rnd = new Random(); private final int DEFAULT_FOO_SIZE = 10; + private Map usageTypesCount = new HashMap<>(); - private String fooString(String orig, boolean firstUppercase, int rndSize) { + private String fooString(String orig, boolean firstUppercase, int rndSize, String usageType, RenameType renameType) { boolean exists; String ret; + int pos = 0; + + if (usageType == null) { + usageType = "name"; + } + if (usageTypesCount.containsKey(usageType)) { + pos = usageTypesCount.get(usageType); + } + loopfoo: do { exists = false; - int len = 3 + rnd.nextInt(rndSize - 3); ret = ""; - for (int i = 0; i < len; i++) { - String c = ""; - if ((i % 2) == 0) { - c = "" + fooCharacters.charAt(rnd.nextInt(fooCharacters.length())); - } else { - c = "" + fooJoinCharacters.charAt(rnd.nextInt(fooJoinCharacters.length())); + if (renameType == RenameType.TYPENUMBER) { + pos++; + ret = usageType + "_" + pos; + } else if (renameType == RenameType.RANDOMWORD) { + int len = 3 + rnd.nextInt(rndSize - 3); + + for (int i = 0; i < len; i++) { + String c = ""; + if ((i % 2) == 0) { + c = "" + fooCharacters.charAt(rnd.nextInt(fooCharacters.length())); + } else { + c = "" + fooJoinCharacters.charAt(rnd.nextInt(fooJoinCharacters.length())); + } + if (i == 0 && firstUppercase) { + c = c.toUpperCase(); + } + ret += c; } - if (i == 0 && firstUppercase) { - c = c.toUpperCase(); - } - ret += c; } for (int i = 1; i < constants.constant_string.length; i++) { if (constants.constant_string[i].equals(ret)) { @@ -702,6 +790,7 @@ public class ABC { continue; } } while (exists); + usageTypesCount.put(usageType, pos); deobfuscated.put(orig, ret); return ret; } @@ -738,7 +827,7 @@ public class ABC { return isValid; } - public int deobfuscateNameSpace(Set stringUsages, HashMap namesMap, int strIndex) { + public int deobfuscateNameSpace(Map stringUsageTypes, Set stringUsages, HashMap namesMap, int strIndex, RenameType renameType) { if (strIndex <= 0) { return strIndex; } @@ -761,7 +850,7 @@ public class ABC { ret += "."; } if (!isValidNSPart(parts[p])) { - ret += fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE); + ret += fooString(constants.constant_string[strIndex], false, DEFAULT_FOO_SIZE, "package", renameType); } else { ret += parts[p]; } @@ -779,7 +868,7 @@ public class ABC { return strIndex; } - public int deobfuscateName(Set stringUsages, HashMap namesMap, int strIndex, boolean firstUppercase) { + public int deobfuscateName(Map stringUsageTypes, Set stringUsages, HashMap namesMap, int strIndex, boolean firstUppercase, RenameType renameType) { if (strIndex <= 0) { return strIndex; } @@ -810,7 +899,7 @@ public class ABC { if (namesMap.containsKey(s)) { newname = namesMap.get(s); } else { - newname = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE); + newname = fooString(constants.constant_string[strIndex], firstUppercase, DEFAULT_FOO_SIZE, stringUsageTypes.get(strIndex), renameType); } if (stringUsages.contains(strIndex)) { //this name is already referenced as String strIndex = constants.addString(s); //add new index diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/RenameType.java b/trunk/src/com/jpexs/decompiler/flash/abc/RenameType.java new file mode 100644 index 000000000..c955265c3 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/abc/RenameType.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2013 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.abc; + +/** + * + * @author JPEXS + */ +public enum RenameType { + + TYPENUMBER, + RANDOMWORD +} diff --git a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/DirectValueTreeItem.java b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/DirectValueTreeItem.java index 782478636..295c27053 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/treemodel/DirectValueTreeItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/treemodel/DirectValueTreeItem.java @@ -213,10 +213,9 @@ public class DirectValueTreeItem extends TreeItem { if (!Objects.equals(this.constants, other.constants)) { return false; } - if(other.pos!=this.pos){ + if (other.pos != this.pos) { return false; } return true; } - } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index c8cccd4aa..493252e53 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -181,6 +181,12 @@ public class Main { if (event.equals("export")) { startWork((String) data); } + if (event.equals("getVariables")) { + startWork("Getting variables..." + (String) data); + } + if (event.equals("deobfuscate")) { + startWork("Deobfuscating..." + (String) data); + } } }); return locswf; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 64388293d..989cacfb2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.FrameNode; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.TagNode; +import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.gui.ABCPanel; import com.jpexs.decompiler.flash.abc.gui.ClassesListTreeModel; @@ -1696,34 +1697,35 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi if (e.getActionCommand().equals("RENAMEIDENTIFIERS")) { if (confirmExperimental()) { + final RenameType renameType = new RenameDialog().display(); + if (renameType != null) { + Main.startWork("Renaming identifiers..."); + new SwingWorker() { + @Override + protected Object doInBackground() throws Exception { + try { + int cnt = 0; - Main.startWork("Renaming identifiers..."); - new SwingWorker() { - @Override - protected Object doInBackground() throws Exception { - try { - int cnt = 0; - - if (abcPanel != null) { - cnt = swf.deobfuscateAS3Identifiers(); - } else { - cnt = swf.deobfuscateAS2Identifiers(); + if (abcPanel != null) { + cnt = swf.deobfuscateAS3Identifiers(renameType); + } else { + cnt = swf.deobfuscateAS2Identifiers(renameType); + } + Main.stopWork(); + JOptionPane.showMessageDialog(null, "Identifiers renamed: " + cnt); + if (abcPanel != null) { + abcPanel.reload(); + } + doFilter(); + reload(true); + } catch (Exception ex) { + Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "message", ex); } - Main.stopWork(); - JOptionPane.showMessageDialog(null, "Identifiers renamed: " + cnt); - if (abcPanel != null) { - abcPanel.reload(); - } - doFilter(); - reload(true); - } catch (Exception ex) { - Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, "message", ex); + return true; } - return true; - } - }.execute(); - + }.execute(); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/RenameDialog.java b/trunk/src/com/jpexs/decompiler/flash/gui/RenameDialog.java new file mode 100644 index 000000000..1b73dbd5b --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/RenameDialog.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2013 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.abc.RenameType; +import java.awt.BorderLayout; +import java.awt.FlowLayout; +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.JDialog; +import javax.swing.JPanel; +import javax.swing.JRadioButton; + +/** + * + * @author JPEXS + */ +public class RenameDialog extends JDialog implements ActionListener { + + private JRadioButton typeNumberRadioButton = new JRadioButton("Type + Number (class_27, method_456,...)"); + private JRadioButton randomWordRadioButton = new JRadioButton("Random word (abada, kof, supo, kosuri,...)"); + private JButton okButton = new JButton("OK"); + private JButton cancelButton = new JButton("Cancel"); + private boolean confirmed = false; + + public RenameType getRenameType() { + if (!isConfirmed()) { + return null; + } + if (typeNumberRadioButton.isSelected()) { + return RenameType.TYPENUMBER; + } + return RenameType.RANDOMWORD; + } + + public RenameDialog() { + setSize(300, 150); + setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); + ButtonGroup group = new ButtonGroup(); + group.add(typeNumberRadioButton); + group.add(randomWordRadioButton); + JPanel pan = new JPanel(); + pan.setLayout(new BoxLayout(pan, BoxLayout.Y_AXIS)); + pan.add(typeNumberRadioButton); + pan.add(randomWordRadioButton); + typeNumberRadioButton.setSelected(true); + setLayout(new BorderLayout()); + add(pan, BorderLayout.CENTER); + JPanel panButtons = new JPanel(new FlowLayout()); + panButtons.add(okButton); + okButton.setActionCommand("OK"); + okButton.addActionListener(this); + panButtons.add(cancelButton); + cancelButton.setActionCommand("CANCEL"); + cancelButton.addActionListener(this); + add(panButtons, BorderLayout.SOUTH); + setModalityType(ModalityType.APPLICATION_MODAL); + View.centerScreen(this); + View.setWindowIcon(this); + setTitle("Rename Identifiers"); + getRootPane().setDefaultButton(okButton); + } + + @Override + public void setVisible(boolean b) { + if (b) { + confirmed = false; + } + super.setVisible(b); + } + + @Override + public void actionPerformed(ActionEvent e) { + switch (e.getActionCommand()) { + case "OK": + confirmed = true; + setVisible(false); + break; + case "CANCEL": + confirmed = false; + setVisible(false); + break; + } + } + + public boolean isConfirmed() { + return confirmed; + } + + public RenameType display() { + setVisible(true); + return getRenameType(); + } +}