diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index 1c0784137..c0fd51a1e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -61,7 +61,6 @@ import java.util.Set; */ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { - //private final int executionLimit = 30000; @Override public void actionListParsed(ActionList actions, SWF swf) { @@ -118,7 +117,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { MethodBody bodybefore = body; body = bodybefore.clone(); setReg = getFirstRegisterSetter(assignmentRef, classIndex, isStatic, scriptIndex, abc, body, ignoredRegs, ignoredRegGets); - //System.err.println("setreg " + setReg + " ass:" + assignment); + //System.err.println("setreg " + setReg + " ass:" + assignmentRef.getVal()); if (setReg < 0) { break; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java index c3d668120..59f7f8d3f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ConvertData.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; +import com.jpexs.decompiler.flash.configuration.Configuration; import java.util.HashMap; import java.util.Map; @@ -26,5 +27,11 @@ import java.util.Map; */ public class ConvertData { + public int deobfuscationMode; + public Map assignedValues = new HashMap<>(); + + public ConvertData() { + deobfuscationMode = Configuration.autoDeobfuscate.get() ? (Configuration.deobfuscationOldMode.get() ? 0 : 1) : -1; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index ef7084b8d..eafea2014 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFField; @@ -294,7 +295,7 @@ public final class MethodBody implements Cloneable { @Override public Void call() throws InterruptedException { try (Statistics s1 = new Statistics("MethodBody.convert")) { - MethodBody converted = convertMethodBody(path, isStatic, scriptIndex, classIndex, abc, trait, scopeStack, initializerType != GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, fullyQualifiedNames, initTraits); + MethodBody converted = convertMethodBody(convertData, path, isStatic, scriptIndex, classIndex, abc, trait, scopeStack, initializerType != GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, fullyQualifiedNames, initTraits); HashMap localRegNames = getLocalRegNames(abc); List convertedItems1; try (Statistics s = new Statistics("AVM2Code.toGraphTargetItems")) { @@ -365,13 +366,13 @@ public final class MethodBody implements Cloneable { return writer; } - public MethodBody convertMethodBody(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, List initTraits) throws InterruptedException { + public MethodBody convertMethodBody(ConvertData convertData, String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, Trait trait, ScopeStack scopeStack, boolean isStaticInitializer, List fullyQualifiedNames, List initTraits) throws InterruptedException { MethodBody body = clone(); AVM2Code code = body.getCode(); code.markMappedOffsets(); code.fixJumps(path, body); - if (Configuration.autoDeobfuscate.get()) { + if (convertData.deobfuscationMode != -1) { try { code.removeTraps(trait, method_info, body, abc, scriptIndex, classIndex, isStatic, path); } catch (ThreadDeath | InterruptedException ex) { @@ -390,6 +391,23 @@ public final class MethodBody implements Cloneable { return body; } + public String toSource() { + ConvertData convertData = new ConvertData(); + convertData.deobfuscationMode = -1; + try { + convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + writer.indent().indent().indent(); + toString("", ScriptExportMode.AS, abc, null, writer, new ArrayList<>()); + writer.unindent().unindent().unindent(); + return writer.toString(); + } catch (InterruptedException ex) { + Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, null, ex); + } + + return null; + } + @Override public MethodBody clone() { try { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerPlugin.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerPlugin.java index a7dd39591..940142d19 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerPlugin.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerPlugin.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.helpers.Helper; import com.jpexs.helpers.Path; @@ -53,9 +54,18 @@ public class SWFDecompilerPlugin { public static void loadPlugins() { try { - File f = new File(SWFDecompilerPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); - File dir = f.getAbsoluteFile().getParentFile().getParentFile(); - File pluginPath = new File(Path.combine(dir.getPath(), "plugins")).getCanonicalFile(); + File pluginPath = null; + String pluginPathConfig = Configuration.pluginPath.get(); + if (pluginPathConfig != null && !pluginPathConfig.isEmpty()) { + pluginPath = new File(pluginPathConfig); + } + + if (pluginPath == null || !pluginPath.exists()) { + File f = new File(SWFDecompilerPlugin.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); + File dir = f.getAbsoluteFile().getParentFile().getParentFile(); + pluginPath = new File(Path.combine(dir.getPath(), "plugins")).getCanonicalFile(); + } + if (pluginPath.exists()) { System.out.println("Loading plugins from " + pluginPath.getPath()); File[] files = pluginPath.listFiles(); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java index f80d6bf50..5c663b03e 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; @@ -32,6 +33,7 @@ import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @@ -91,6 +93,23 @@ public class ActionScript3Test extends ActionScriptTestBase { assertEquals(actualResult, expectedResult); } + private void decompileScriptPack(String path, String expectedResult) { + ScriptPack scriptPack = abc.findScriptPackByPath(path, Arrays.asList(abc)); + assertTrue(scriptPack != null); + HighlightedTextWriter writer = null; + try { + List ts = new ArrayList<>(); + ts.add(abc.instance_info.get(clsIndex).instance_traits); + writer = new HighlightedTextWriter(new CodeFormatting(), false); + scriptPack.toSource(writer, abc.script_info.get(scriptPack.scriptIndex).traits.traits, new ConvertData(), ScriptExportMode.AS, false); + } catch (InterruptedException ex) { + fail(); + } + String actualResult = cleanPCode(writer.toString()); + expectedResult = cleanPCode(expectedResult); + assertEquals(actualResult, expectedResult); + } + @Test public void testHello() { decompileMethod("testHello", "trace(\"hello\");\r\n", false); @@ -934,6 +953,172 @@ public class ActionScript3Test extends ActionScriptTestBase { + "}\r\n", false); } + //@Test + public void testMyPackage1TestClass() { + decompileScriptPack("classes.mypackage1.TestClass", "package classes.mypackage1\n" + + "{\n" + + " import classes.mypackage2.TestInterface;\n" + + " import classes.mypackage2.TestClass;\n" + + " \n" + + " public class TestClass extends Object implements TestInterface\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg1hello\");\n" + + " return \"pkg1hello\";\n" + + " }\n" + + " \n" + + " public function testMethod1() : void\n" + + " {\n" + + " var a:classes.mypackage1.TestInterface = this;\n" + + " a.testMethod1();\n" + + " var b:classes.mypackage2.TestInterface = this;\n" + + " b = new classes.mypackage2.TestClass();\n" + + " }\n" + + " \n" + + " public function testMethod2() : void\n" + + " {\n" + + " var a:classes.mypackage1.TestInterface = this;\n" + + " a.testMethod1();\n" + + " var b:classes.mypackage2.TestInterface = this;\n" + + " b = new classes.mypackage2.TestClass();\n" + + " }\n" + + " }\n" + + "}"); + } + + //@Test + public void testMyPackage1TestClass2() { + decompileScriptPack("classes.mypackage1.TestClass2", "package classes.mypackage1\n" + + "{\n" + + " import classes.mypackage2.TestClass;\n" + + " import classes.mypackage3.TestClass;\n" + + " \n" + + " public class TestClass2 extends Object\n" + + " {\n" + + " \n" + + " public function TestClass2()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : *\n" + + " {\n" + + " var a:classes.mypackage1.TestClass = null;\n" + + " var b:classes.mypackage2.TestClass = null;\n" + + " var c:classes.mypackage3.TestClass = null;\n" + + " a = new classes.mypackage1.TestClass();\n" + + " b = new classes.mypackage2.TestClass();\n" + + " c = new classes.mypackage3.TestClass();\n" + + " var res:String = a.testCall() + b.testCall() + c.testCall() + this.testCall2() + myNamespace::testCall3();\n" + + " trace(res);\n" + + " return res;\n" + + " }\n" + + " \n" + + " myNamespace function testCall2() : String\n" + + " {\n" + + " return \"1\";\n" + + " }\n" + + " \n" + + " myNamespace function testCall3() : String\n" + + " {\n" + + " return myNamespace::testCall2();\n" + + " }\n" + + " \n" + + " public function testCall2() : String\n" + + " {\n" + + " return \"2\";\n" + + " }\n" + + " }\n" + + "}"); + } + + //@Test + public void testMyPackage1TestInterface() { + decompileScriptPack("classes.mypackage1.TestInterface", "package classes.mypackage1\n" + + "{\n" + + " import classes.mypackage2.TestInterface;\n" + + " \n" + + " public interface TestInterface extends classes.mypackage2.TestInterface\n" + + " {\n" + + " \n" + + " function testMethod1() : void;\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage1MyNamespace() { + decompileScriptPack("classes.mypackage1.myNamespace", "package classes.mypackage1\n" + + "{\n" + + " public namespace myNamespace = \"https://www.free-decompiler.com/flash/test/namespace\";\n" + + "}"); + } + + @Test + public void testMyPackage2TestClass() { + decompileScriptPack("classes.mypackage2.TestClass", "package classes.mypackage2\n" + + "{\n" + + " public class TestClass extends Object implements TestInterface\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg2hello\");\n" + + " return \"pkg2hello\";\n" + + " }\n" + + " \n" + + " public function testMethod2() : void\n" + + " {\n" + + " }\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage2TestInterface() { + decompileScriptPack("classes.mypackage2.TestInterface", "package classes.mypackage2\n" + + "{\n" + + " public interface TestInterface\n" + + " {\n" + + " \n" + + " function testMethod2() : void;\n" + + " }\n" + + "}"); + } + + @Test + public void testMyPackage3TestClass() { + decompileScriptPack("classes.mypackage3.TestClass", "package classes.mypackage3\n" + + "{\n" + + " public class TestClass extends Object\n" + + " {\n" + + " \n" + + " public function TestClass()\n" + + " {\n" + + " super();\n" + + " }\n" + + " \n" + + " public function testCall() : String\n" + + " {\n" + + " trace(\"pkg3hello\");\n" + + " return \"pkg3hello\";\n" + + " }\n" + + " }\n" + + "}"); + } + @Test public void testOptionalParameters() { String methodName = "testOptionalParameters"; diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 4d68cc83a..8e0f5860f 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -1146,9 +1146,6 @@ public class Main { public static void main(String[] args) throws IOException { clearTemp(); - //String pluginPath = Configuration.pluginPath.get(); - //if (pluginPath != null && !pluginPath.isEmpty()) { - //} try { SWFDecompilerPlugin.loadPlugins(); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index 6585b91cb..9aa81050b 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Embed font files in SVG using font config.name.lzmaFastBytes = LZMA fast bytes (valid values: 5-255) config.description.lzmaFastBytes = Fast bytes parameter of the LZMA encoder -#temporary setting, do not translate it config.name.pluginPath = Plugin Path config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties index 3ae6ce705..58ac0d655 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ca.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Incrusta els fitxers de tipografie config.name.lzmaFastBytes = Bytes r\u00e0pids LZMA (v\u00e0lors valids: 5-255) config.description.lzmaFastBytes = Par\u00e0metre de bytes r\u00e0pids del codificador LZMA -#temporary setting, do not translate it config.name.pluginPath = Cam\u00ed de l'Extensi\u00f3 config.description.pluginPath = - 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 8fc025ca6..342884498 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Vkl\u00e1dat soubory p\u00edsem do 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 = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties index d0d89aa09..924845565 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Incrustar archivos de fuente en el config.name.lzmaFastBytes = Bytes r\u00e1pidos de LZMA (valores v\u00e1lidos: 5-255) config.description.lzmaFastBytes = Par\u00e1metro de bytes r\u00e1pidos del codificador LZMA -#temporary setting, do not translate it config.name.pluginPath = Directorio de Plugin config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties index 5a5cbe8bf..001003154 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_fr.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Embarquer le style de police de ca config.name.lzmaFastBytes = LZMA fast bytes (valeurs permises : 5-255) config.description.lzmaFastBytes = Param\u00e8tre vitesse des octets de l'encodeur LZMA -#temporary setting, do not translate it config.name.pluginPath = Plugin Path config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties index e920f8a4b..ebce28516 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_hu.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Bet\u0171t\u00edpus f\u00e1jlok be config.name.lzmaFastBytes = LZMA fast bytes (\u00e9rv\u00e9nyes \u00e9rt\u00e9kek: 5-255) config.description.lzmaFastBytes = Az LZMA t\u00f6m\u00f6r\u00edt\u0151 "Fast bytes" param\u00e9tere -#temporary setting, do not translate it config.name.pluginPath = Plugin Path config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties index aeb48ef11..414010399 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_it.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = Incorpora font in SVG utilizzando config.name.lzmaFastBytes = Byte LZMA veloci (valori validi: 5-255) config.description.lzmaFastBytes = Parametro byte veloci del codificatore LZMA -#temporary setting, do not translate it config.name.pluginPath = Percorso Plugin config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_pl.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_pl.properties index 868f2c042..d82063894 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_pl.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_pl.properties @@ -263,7 +263,6 @@ config.description.lzmaFastBytes = Parametr fast bytes kodera LZMA config.name.showMethodBodyId = Poka\u017c id korpusu metody config.description.showMethodBodyId = Pokazuje id korpusu metody dla importu linii polece\u0144 -#temporary setting, do not translate it config.name.pluginPath = Plugin Path config.description.pluginPath = - diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties index cfc7ce41d..15740b5be 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_sv.properties @@ -260,7 +260,6 @@ config.description.textExportExportFontFace = B\u00e4dda in typsnitssfiler i SVG config.name.lzmaFastBytes = LZMA snabba bytes (Giltiga v\u00e4rden: 5-255) config.description.lzmaFastBytes = Snabb bytes parameter av LZMA kodare -#temporary setting, do not translate it config.name.pluginPath = Plugin S\u00f6kv\u00e4g config.description.pluginPath = -