diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index db9bad2a7..d94faf62c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.EndOfStreamException; @@ -264,7 +265,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.AssignedValue; import com.jpexs.decompiler.flash.abc.types.ConvertData; 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 758f06c8f..8d0499b23 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 @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; import com.jpexs.decompiler.flash.BaseLocalData; @@ -32,7 +33,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIn import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java index 99d0da6e8..a53ab1816 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; import com.jpexs.decompiler.flash.BaseLocalData; @@ -30,7 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.graph.Graph; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 5f07c9ba6..a9d054920 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.graph; import com.jpexs.decompiler.flash.BaseLocalData; @@ -571,8 +572,8 @@ public class AVM2Graph extends Graph { } @Override - protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { - super.finalProcessAfter(list, level, localData); + protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { + super.finalProcessAfter(list, level, localData, path); for (int i = 0; i < list.size(); i++) { if (list.get(i) instanceof SetLocalAVM2Item) { SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i); @@ -585,7 +586,7 @@ public class AVM2Graph extends Graph { } @Override - protected void finalProcess(List list, int level, FinalProcessLocalData localData) throws InterruptedException { + protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { if (level == 0) { if (!list.isEmpty()) { @@ -702,7 +703,7 @@ public class AVM2Graph extends Graph { } } //Handle for loops at the end: - super.finalProcess(list, level, localData); + super.finalProcess(list, level, localData, path); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index 935238674..a6bb038d5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.graph; import com.jpexs.decompiler.flash.BaseLocalData; @@ -21,7 +22,7 @@ import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphPart; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index e8c59b02e..066712ffd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.instructions; import com.jpexs.decompiler.flash.abc.ABC; @@ -29,7 +30,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 9e3a06e4c..09b0239ef 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SWFInputStream; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index c7becee79..fbb64fec9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SWC; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java index 1f18b8d90..2534c027f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AssignableAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java index 43b5b5715..fc65d41f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java index 87e7c09f7..c91e506a7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/IndexAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; import com.jpexs.decompiler.flash.abc.types.Multiname; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java index 46a4ad5a6..b03546135 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java index ca056fc58..c2cec4d21 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.Namespace; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java index 819697414..8c82b63f5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespacedAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index f30291de5..0f06f88d4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -12,9 +12,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java index 28f4a0c6f..0be700720 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java @@ -21,7 +21,7 @@ import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.DisassemblyListener; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFOutputStream; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; import com.jpexs.decompiler.flash.action.model.ActionItem; import com.jpexs.decompiler.flash.action.model.CallMethodActionItem; @@ -1214,262 +1214,6 @@ public abstract class Action implements GraphSourceItem { return ti; } - public static List checkClass(List output) { - if (true) { - //return output; - } - List ret = new ArrayList<>(); - List> traits = new ArrayList<>(); - List traitsStatic = new ArrayList<>(); - GraphTargetItem className; - GraphTargetItem extendsOp = null; - List implementsOp = new ArrayList<>(); - boolean ok = true; - int prevCount = 0; - for (GraphTargetItem t : output) { - if (t instanceof IfItem) { - IfItem it = (IfItem) t; - if (it.expression instanceof NotItem) { - NotItem nti = (NotItem) it.expression; - if ((nti.value instanceof GetMemberActionItem) || (nti.value instanceof GetVariableActionItem)) { - if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { - // ignore - } else { - List parts = it.onTrue; - className = getWithoutGlobal(nti.value); - if (parts.size() >= 1) { - int ipos = 0; - - while ((parts.get(ipos) instanceof PopItem) || ((parts.get(ipos) instanceof IfItem) && ((((IfItem) parts.get(ipos)).onTrue.size() == 1) && (((IfItem) parts.get(ipos)).onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) ((IfItem) parts.get(ipos)).onTrue.get(0)).value instanceof NewObjectActionItem)))) { - ipos++; - } - if (parts.get(ipos) instanceof ExtendsActionItem) { - ExtendsActionItem et = (ExtendsActionItem) parts.get(ipos); - extendsOp = getWithoutGlobal(et.superclass); - ipos++; - } - int instanceReg = -1; - int classReg = -1; - if (parts.get(ipos) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); - instanceReg = sr.register.number; - if (sr.value instanceof GetMemberActionItem) { - GetMemberActionItem gm = (GetMemberActionItem) sr.value; - //gm.memberName should be "prototype" - if (gm.object instanceof TemporaryRegister) { - TemporaryRegister tm = (TemporaryRegister) gm.object; - classReg = tm.getRegId(); - if (tm.value instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) tm.value; - if (sm.value instanceof StoreRegisterActionItem) { - sr = (StoreRegisterActionItem) sm.value; - if (sr.value instanceof FunctionActionItem) { - ((FunctionActionItem) (sr.value)).calculatedFunctionName = sm.objectName; //(className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - //This is probably a constructor - traits.add(new MyEntry<>(((FunctionActionItem) (sr.value)).calculatedFunctionName, ((FunctionActionItem) sr.value))); - traitsStatic.add(false); - } - - } - } - } - } - } else if (parts.get(ipos) instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) parts.get(0); - if (sm.value instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) sm.value; - if (f.actions.isEmpty()) { - if (parts.size() == 2) { - if (parts.get(1) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem iot = (ImplementsOpActionItem) parts.get(1); - implementsOp = iot.superclasses; - } else { - //ok = false; - break; - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new InterfaceActionItem(sm.objectName, implementsOp)); - return output2; - } - } - } - - for (; ipos < parts.size(); ipos++) { - if (parts.get(ipos) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); - implementsOp = io.superclasses; - continue; - } else if (parts.get(ipos) instanceof SetMemberActionItem) { - SetMemberActionItem sm = (SetMemberActionItem) parts.get(ipos); - - if (sm.object instanceof TemporaryRegister) { - TemporaryRegister treg = (TemporaryRegister) sm.object; - if (classReg > -1 && treg.getRegId() == classReg) { - - } else if (instanceReg > -1 && treg.getRegId() == instanceReg) { - - } else if (sm.object.value instanceof SetMemberActionItem) { - SetMemberActionItem sm2 = (SetMemberActionItem) sm.object.value; - if ((sm2.objectName instanceof DirectValueActionItem) && "prototype".equals(((DirectValueActionItem) sm2.objectName).getAsString())) { - instanceReg = treg.getRegId(); - extendsOp = getWithoutGlobal(sm2.object); - } else { - classReg = treg.getRegId(); - GraphTargetItem val = sm2.value; - if (val instanceof StoreRegisterActionItem) { - val = val.value; - } - if (val instanceof FunctionActionItem) { - //Is this a constructor? - //((FunctionActionItem) (constructor)).calculatedFunctionName = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - } - } - } - - } - - int rnum = -1; - if (sm.object instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) sm.object; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - rnum = rn.number; - } - } - if (sm.object instanceof TemporaryRegister) { - rnum = ((TemporaryRegister) sm.object).getRegId(); - } - - if (rnum == instanceReg || rnum == classReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - } - traits.add(new MyEntry<>(sm.objectName, sm.value)); - traitsStatic.add(rnum == classReg); - } - } else if (parts.get(ipos) instanceof PushItem) { - if (parts.get(ipos).value instanceof CallMethodActionItem) { - CallMethodActionItem cm = (CallMethodActionItem) parts.get(ipos).value; - if (cm.methodName instanceof DirectValueActionItem) { - if ("addProperty".equals(((DirectValueActionItem) cm.methodName).getAsString())) { - int rnum = -1; - if (cm.scriptObject instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) cm.scriptObject; - if (dv.value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) dv.value; - rnum = rn.number; - } - } - if (cm.scriptObject instanceof TemporaryRegister) { - rnum = ((TemporaryRegister) cm.scriptObject).getRegId(); - } - - if (cm.arguments.size() > 1) { - GraphTargetItem propertyName = cm.arguments.get(0); //name - GraphTargetItem propertyGetter = cm.arguments.get(1); //getter - GraphTargetItem propertySetter = cm.arguments.get(2); //setter - if ((propertyName instanceof DirectValueActionItem) && ((DirectValueActionItem) propertyName).isString()) { - String propertyNameStr = ((DirectValueActionItem) propertyName).getAsString(); - if (propertyGetter instanceof GetMemberActionItem) { - if (((GetMemberActionItem) propertyGetter).object instanceof TemporaryRegister) { - if (((TemporaryRegister) ((GetMemberActionItem) propertyGetter).object).getRegId() == rnum) { - if (((GetMemberActionItem) propertyGetter).memberName instanceof DirectValueActionItem) { - DirectValueActionItem mNameDv = (DirectValueActionItem) ((GetMemberActionItem) propertyGetter).memberName; - if (mNameDv.isString()) { - String getterNameStr = mNameDv.getAsString(); - if (getterNameStr.equals("__get__" + propertyNameStr)) { - //TODO: handle setter - } - } - } - - } - } - } else if (propertyGetter instanceof FunctionActionItem) { - FunctionActionItem getterFunc = (FunctionActionItem) propertyGetter; - if (getterFunc.actions.isEmpty() && getterFunc.functionName.isEmpty() && ((FunctionActionItem) propertyGetter).paramNames.isEmpty()) { - //well, no getter then - } else { - logger.severe("unexpected getter value for property " + propertyNameStr); - } - } else { - logger.severe("unexpected getter value for property " + propertyNameStr + ": " + propertyGetter.getClass().getSimpleName()); - } - - if (propertySetter instanceof GetMemberActionItem) { - if (((GetMemberActionItem) propertySetter).object instanceof TemporaryRegister) { - if (((TemporaryRegister) ((GetMemberActionItem) propertySetter).object).getRegId() == rnum) { - if (((GetMemberActionItem) propertySetter).memberName instanceof DirectValueActionItem) { - DirectValueActionItem mNameDv = (DirectValueActionItem) ((GetMemberActionItem) propertySetter).memberName; - if (mNameDv.isString()) { - String getterNameStr = mNameDv.getAsString(); - if (getterNameStr.equals("__set__" + propertyNameStr)) { - //TODO: handle setter - } - } - } - - } - } - } else if (propertySetter instanceof FunctionActionItem) { - FunctionActionItem setterFunc = (FunctionActionItem) propertySetter; - if (setterFunc.actions.isEmpty() && setterFunc.functionName.isEmpty() && ((FunctionActionItem) propertySetter).paramNames.isEmpty()) { - //well, no setter then - } else { - logger.severe("unexpected setter value for property " + propertyNameStr); - } - //no setter - } else { - logger.severe("unexpected setter value for property " + propertyNameStr + ": " + propertySetter.getClass().getSimpleName()); - } - } - } - } - } - } - } else { - break; - } - } - boolean isAClass = !(traits.isEmpty() && extendsOp == null && implementsOp.isEmpty()); - - if (isAClass) { - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new ClassActionItem(className, extendsOp, implementsOp, traits, traitsStatic)); - return output2; - } else { - ok = false; - } - - } else { - ok = false; - } - } - - } else { - ok = false; - } - } else { - ok = false; - } - } else if (!(t instanceof PopItem)) { - prevCount++; - //ok = false; - } - if (!ok) { - break; - } - } - return output; - } - @Override public boolean ignoredLoops() { return false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index dcab0b63b..145f228e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action; import com.jpexs.decompiler.flash.BaseLocalData; @@ -81,7 +82,7 @@ public class ActionGraph extends Graph { } @Override - public void finalProcessStack(TranslateStack stack, List output) { + public void finalProcessStack(TranslateStack stack, List output, String path) { if (stack.size() > 0) { for (int i = stack.size() - 1; i >= 0; i--) { //System.err.println(stack.get(i)); @@ -96,12 +97,10 @@ public class ActionGraph extends Graph { } @Override - protected void finalProcess(List list, int level, FinalProcessLocalData localData) throws InterruptedException { - List ret = Action.checkClass(list); - if (ret != list) { - list.clear(); - list.addAll(ret); - } + protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { + + ActionScript2ClassDetector detector = new ActionScript2ClassDetector(); + detector.checkClass(list, path); int targetStart; int targetEnd; @@ -188,7 +187,7 @@ public class ActionGraph extends Graph { } } //Handle for loops at the end: - super.finalProcess(list, level, localData); + super.finalProcess(list, level, localData, path); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java index 75b5cf097..664a19b25 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java @@ -12,11 +12,12 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.action; import com.jpexs.decompiler.flash.BaseLocalData; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSource; import com.jpexs.decompiler.graph.GraphSourceItem; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScript2ClassDetector.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScript2ClassDetector.java new file mode 100644 index 000000000..d3e70c8c2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScript2ClassDetector.java @@ -0,0 +1,685 @@ +/* + * Copyright (C) 2010-2018 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.action; + +import com.jpexs.decompiler.flash.action.model.CallFunctionActionItem; +import com.jpexs.helpers.Reference; +import com.jpexs.decompiler.flash.action.model.CallMethodActionItem; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.ExtendsActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; +import com.jpexs.decompiler.flash.action.model.NewMethodActionItem; +import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; +import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.SetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.TemporaryRegister; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.PopItem; +import com.jpexs.decompiler.graph.model.PushItem; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author JPEXS + */ +public class ActionScript2ClassDetector { + + private static final Logger logger = Logger.getLogger(ActionScript2ClassDetector.class.getName()); + + private class AssertException extends Exception { + + private final String condition; + + public AssertException(String condition) { + super(condition); + this.condition = condition; + } + + public String getCondition() { + return condition; + } + + } + + /** + * Checks whether an item is direct submember of path. a.b.c.d is submember + * of a.b.c, x.y.z is not submember of x, + * + * @param item + * @param objectPath + * @param newPathItem New submember name + * @return + */ + private boolean isMemberOfPath(GraphTargetItem item, List objectPath, Reference newPathItem) { + List path = getMembersPath(item); + if (path == null) { + return false; + } + if (path.size() != objectPath.size() + 1) { + return false; + } + for (int i = 0; i < objectPath.size(); i++) { + if (!path.get(i).equals(objectPath.get(i))) { + return false; + } + } + newPathItem.setVal(path.get(path.size() - 1)); + return true; + } + + /** + * Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d] + * + * @param item + * @return List of path or null if not members path + */ + private List getMembersPath(GraphTargetItem item) { + List ret = new ArrayList<>(); + while (item instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) item; + if (!(mem.memberName instanceof DirectValueActionItem)) { + return null; + } + DirectValueActionItem dv = ((DirectValueActionItem) mem.memberName); + if (!dv.isString()) { + return null; + } + ret.add(0, dv.getAsString()); + item = mem.object; + } + if (!(item instanceof GetVariableActionItem)) { + return null; + } + GetVariableActionItem gv = (GetVariableActionItem) item; + if (!(gv.name instanceof DirectValueActionItem)) { + return null; + } + DirectValueActionItem dv = ((DirectValueActionItem) gv.name); + if (!dv.isString()) { + return null; + } + String varName = dv.getAsString(); + ret.add(0, varName); + return ret; + } + + private GraphTargetItem setMemberToGetMember(GraphTargetItem item) { + if (item instanceof SetMemberActionItem) { + return new GetMemberActionItem(null, null, ((SetMemberActionItem) item).object, ((SetMemberActionItem) item).objectName); + } else if (item instanceof SetVariableActionItem) { + return new GetVariableActionItem(null, null, ((SetVariableActionItem) item).name); + } + return null; + } + + private GraphTargetItem newToGetMember(GraphTargetItem nobj) throws AssertException { + if (nobj instanceof NewMethodActionItem) { + NewMethodActionItem nm = (NewMethodActionItem) nobj; + return new GetMemberActionItem(nobj.getSrc(), nobj.getLineStartItem(), nm.scriptObject, nm.methodName); + } else if (nobj instanceof NewObjectActionItem) { + NewObjectActionItem no = (NewObjectActionItem) nobj; + return new GetVariableActionItem(nobj.getSrc(), nobj.getLineStartItem(), no.objectName); + } + throw new AssertException("NewMethod or NewObject expected"); + } + + private List getSetMembersPath(GraphTargetItem item) { + if (item instanceof SetVariableActionItem) { + SetVariableActionItem sv = (SetVariableActionItem) item; + if (!(sv.name instanceof DirectValueActionItem)) { + return null; + } + DirectValueActionItem nDv = (DirectValueActionItem) sv.name; + if (!nDv.isString()) { + return null; + } + List ret = new ArrayList<>(); + ret.add(nDv.getAsString()); + return ret; + } else if (item instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) item; + if (!(sm.objectName instanceof DirectValueActionItem)) { + return null; + } + DirectValueActionItem onDv = (DirectValueActionItem) sm.objectName; + if (!onDv.isString()) { + return null; + } + String currentMemberName = onDv.getAsString(); + List path = getMembersPath(sm.object); + if (path == null) { + return null; + } + path.add(currentMemberName); + return path; + } else { + return null; + } + } + + /** + * Get register id or -1 if not found + * + * @param item + * @return + */ + private int getAsRegisterNum(GraphTargetItem item, String assertName) throws AssertException { + if (item instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) item; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + return rn.number; + } + } + if (item instanceof TemporaryRegister) { + TemporaryRegister tr = (TemporaryRegister) item; + return tr.getRegId(); + } + throw new AssertException("not a register - " + assertName); + } + + /*private boolean isInstanceRegister(GraphTargetItem item, Reference instanceReg, Reference classReg,Reference extracted, String assertName) throws AssertException { + if (item instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) item; + if (dv.value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) dv.value; + if (rn.number == instanceReg.getVal()) { + return true; + } else if (rn.number == classReg.getVal()) { + return false; + }else{ + throw new AssertException(assertName + " - unknown register"); + } + } + } + if (item instanceof TemporaryRegister) { + TemporaryRegister tr = (TemporaryRegister) item; + if (!"prototype".equals(getAsString(gm.memberName, "memberName"))) { + throw new AssertException("memberName not \"prototype\""); + } + return tr.getRegId(); + } + } + */ + public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) { + GraphTargetItem t = ti; + if (!(t instanceof GetMemberActionItem)) { + return ti; + } + GetMemberActionItem lastMember = null; + while (((GetMemberActionItem) t).object instanceof GetMemberActionItem) { + lastMember = (GetMemberActionItem) t; + t = ((GetMemberActionItem) t).object; + } + if (((GetMemberActionItem) t).object instanceof GetVariableActionItem) { + GetVariableActionItem v = (GetVariableActionItem) ((GetMemberActionItem) t).object; + if (v.name instanceof DirectValueActionItem) { + if (((DirectValueActionItem) v.name).value instanceof String) { + if (((DirectValueActionItem) v.name).value.equals("_global")) { + GetVariableActionItem gvt = new GetVariableActionItem(null, null, ((GetMemberActionItem) t).memberName); + if (lastMember == null) { + return gvt; + } else { + lastMember.object = gvt; + } + } + } + } + } + return ti; + } + + private String getAsString(GraphTargetItem item, String itemName) throws AssertException { + if (!(item instanceof DirectValueActionItem)) { + throw new AssertException(itemName + " not DirectValue"); + } + DirectValueActionItem mnDv = (DirectValueActionItem) item; + if (!mnDv.isString()) { + throw new AssertException(itemName + " not string"); + } + return mnDv.getAsString(); + } + + public void checkClass(List commands, String scriptPath) { + /* + class a.b.c.D: + + if(!_global.a) + { + _global.a = new Object(); + } + §§pop(); + if(!_global.a.b) + { + _global.a.b = new Object(); + } + §§pop(); + if(!_global.a.b.c) + { + _global.a.b.c = new Object(); + } + §§pop(); + if(!_global.a.b.c.D) + { + ... + §§push(ASSetPropFlags(a.b.c.D.prototype,null,1)); + } + §§pop(); + + */ + + List pathToSearchInIfCond = new ArrayList<>(); + pathToSearchInIfCond.add("_global"); + + looppos: + for (int pos = 0; pos < commands.size(); pos++) { + + //start with _global. + if (pathToSearchInIfCond.size() > 1) { + pathToSearchInIfCond.clear(); + pathToSearchInIfCond.add("_global"); + } + + loopcheck: + for (int checkPos = pos; checkPos < commands.size(); checkPos++) { + GraphTargetItem t = commands.get(checkPos); + if (t instanceof IfItem) { + IfItem it = (IfItem) t; + if (it.expression instanceof NotItem) { + NotItem nti = (NotItem) it.expression; + GraphTargetItem condType = nti.value; + Reference newMemberNameRef = new Reference<>(""); + if (isMemberOfPath(condType, pathToSearchInIfCond, newMemberNameRef)) { + pathToSearchInIfCond.add(newMemberNameRef.getVal()); + + //_global.a.b.c = new Object(); + if ((it.onTrue.size() == 1) && (it.onTrue.get(0) instanceof SetMemberActionItem) && (((SetMemberActionItem) it.onTrue.get(0)).value instanceof NewObjectActionItem)) { + //skip §§pop item if its there right after if + if (checkPos + 1 < commands.size()) { + GraphTargetItem tnext = commands.get(checkPos + 1); + if (tnext instanceof PopItem) { + checkPos++; + } + } + continue loopcheck; + } + + List parts = it.onTrue; + + List classNamePath = pathToSearchInIfCond; + classNamePath.remove(0); //remove "_global" + + int ppos = 0; + GraphTargetItem item = parts.get(ppos); + GraphTargetItem extendsOp = null; + List implementsOp = new ArrayList<>(); + if (item instanceof ExtendsActionItem) { + ExtendsActionItem et = (ExtendsActionItem) parts.get(ppos); + extendsOp = getWithoutGlobal(et.superclass); + ppos++; + item = parts.get(ppos); + } + try { + int instanceReg = -1; + int classReg = -1; + GraphTargetItem classNameTargetPath = null; + GraphTargetItem constructor = null; + if (item instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) item; + instanceReg = sr.register.number; + if (sr.value instanceof GetMemberActionItem) { + GetMemberActionItem gm = (GetMemberActionItem) sr.value; + if (gm.object instanceof TemporaryRegister) { + TemporaryRegister treg = (TemporaryRegister) gm.object; + classReg = treg.getRegId(); + if (!"prototype".equals(getAsString(gm.memberName, "memberName"))) { + throw new AssertException("memberName not \"prototype\""); + } + if ((treg.value instanceof SetMemberActionItem) || (treg.value instanceof SetVariableActionItem)) { + List path = getSetMembersPath(treg.value); + if (path == null || path.isEmpty()) { + logger.severe("Cannot detect class - tempreg value is not a path"); + break loopcheck; + } + //remove _global if it's there - happens for classes in global package + if ("_global".equals(path.get(0))) { + path.remove(0); + } + if (classNamePath.equals(path)) { + //can start with _global for classes on top level + classNameTargetPath = getWithoutGlobal(setMemberToGetMember(treg.value)); + + //treg.value.value is the value being set - treg.value is setmember ot setvariable + if (!(treg.value.value instanceof StoreRegisterActionItem)) { + throw new AssertException("Constructor expected to be in storeregister"); + } + if (!(treg.value.value.value instanceof FunctionActionItem)) { + throw new AssertException("Constructor expected as functionitem"); + } + constructor = treg.value.value.value; + } else { + throw new AssertException("temporaryreg value does not match class path"); + } + } else { + throw new AssertException("temporaryreg value not setmember/setvariable"); + } + } else { + throw new AssertException("Getmember does not have TemporaryRegister as object"); + } + } else { + throw new AssertException("Not Getmember in StoreRegister"); + } + ppos++; + } + List> traits = new ArrayList<>(); + List traitsStatic = new ArrayList<>(); + loopsetmembers: + for (; ppos < parts.size(); ppos++) { + item = parts.get(ppos); + if (item instanceof SetMemberActionItem) { + SetMemberActionItem sm = (SetMemberActionItem) item; + GraphTargetItem regValue; + int currentRegId = -1; + if (sm.object instanceof TemporaryRegister) { + TemporaryRegister tempReg = (TemporaryRegister) sm.object; + currentRegId = tempReg.getRegId(); + regValue = tempReg.value; + } else if ((sm.object instanceof DirectValueActionItem) && (((DirectValueActionItem) sm.object).value instanceof RegisterNumber)) { + DirectValueActionItem dv = (DirectValueActionItem) sm.object; + RegisterNumber rn = ((RegisterNumber) dv.value); + currentRegId = rn.number; + regValue = dv.computedRegValue; + } else { + //might be an interface + List path = getSetMembersPath(item); + if (path == null || path.isEmpty()) { + throw new AssertException("invalid setmember"); + } + //remove _global if it's there - happens for classes in global package + if ("_global".equals(path.get(0))) { + path.remove(0); + } + if (!path.equals(classNamePath)) { + throw new AssertException("wrong path in setmember"); + } + GraphTargetItem interfaceClass = getWithoutGlobal(setMemberToGetMember(item)); + if (!(sm.value instanceof FunctionActionItem)) { + logger.severe("Cannot detect class - not a function in setmember"); + break loopcheck; + } + FunctionActionItem f = (FunctionActionItem) sm.value; + if (!"".equals(f.functionName)) { + throw new AssertException("not unnamed func in setmember"); + } + if (!f.actions.isEmpty()) { + throw new AssertException("not empty function in setmember"); + } + if (!f.paramNames.isEmpty()) { + throw new AssertException("not empty params for function in setmember"); + } + ppos++; + for (; ppos < parts.size(); ppos++) { + item = parts.get(ppos); + if (item instanceof ImplementsOpActionItem) { + if (!implementsOp.isEmpty()) { + throw new AssertException("multiple implementsAction"); + } + ImplementsOpActionItem io = (ImplementsOpActionItem) item; + implementsOp = io.superclasses; + } else { + throw new AssertException("unknown iface item: " + item.getClass().getSimpleName()); + } + } + + InterfaceActionItem ifsItem = new InterfaceActionItem(interfaceClass, implementsOp); + for (int k = pos; k <= checkPos; k++) { + commands.remove(pos); + } + commands.add(pos, ifsItem); + + //remove §§pop after, if it's there + if (pos + 1 < commands.size()) { + if (commands.get(pos + 1) instanceof PopItem) { + commands.remove(pos + 1); + } + } + + // goto next line and check next classes + continue looppos; + } + //it was register .. continue class detection + if (currentRegId != instanceReg && currentRegId != classReg) { + if (!(regValue instanceof SetMemberActionItem)) { + throw new AssertException("temp register do not contain setmember"); + } + SetMemberActionItem sm2 = (SetMemberActionItem) regValue; + GraphTargetItem pathSource; + boolean isPrototype; + if ("prototype".equals(getAsString(sm2.objectName, "objectName"))) { + pathSource = sm2.object; + isPrototype = true; + } else { + pathSource = setMemberToGetMember(sm2); + isPrototype = false; + } + List memPath = getMembersPath(pathSource); + if (memPath == null) { + throw new AssertException("Invalid pathsource"); + } + if (!classNamePath.equals(memPath)) { + throw new AssertException("Invalid path of setmember:" + String.join(".", memPath)); + } + classNameTargetPath = pathSource; + if (!(sm2.value instanceof StoreRegisterActionItem)) { + throw new AssertException("Not storeregister"); + } + StoreRegisterActionItem sr = (StoreRegisterActionItem) sm2.value; + if (sr.register.number != currentRegId) { + throw new AssertException("Invalid storeregister"); + } + if (isPrototype && ((sr.value instanceof NewMethodActionItem) || (sr.value instanceof NewObjectActionItem))) { + extendsOp = newToGetMember(sr.value); + instanceReg = currentRegId; + } else if (!isPrototype && (sr.value instanceof FunctionActionItem)) { //constructor + constructor = sr.value; + classReg = currentRegId; + } else { + throw new AssertException("invalid storeregister value: " + sr.value.getClass().getSimpleName()); + } + } + + MyEntry trait = new MyEntry<>(sm.objectName, sm.value); + if (sm.value instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) sm.value; + f.calculatedFunctionName = sm.objectName; + } + traits.add(trait); + if (currentRegId == instanceReg) { + traitsStatic.add(false); + } else if (currentRegId == classReg) { + traitsStatic.add(true); + } + } else if (item instanceof ImplementsOpActionItem) { + ImplementsOpActionItem iot = (ImplementsOpActionItem) item; + implementsOp = iot.superclasses; + } else { + break loopsetmembers; + } + } + looppushes: + for (; ppos < parts.size(); ppos++) { + item = parts.get(ppos); + if (item instanceof PushItem) { + PushItem pi = (PushItem) item; + if (pi.value instanceof CallMethodActionItem) { + CallMethodActionItem cm = (CallMethodActionItem) pi.value; + String pushMethodName = getAsString(cm.methodName, "push methodName"); + if ("addProperty".equals(pushMethodName)) { + int rnumObject = getAsRegisterNum(cm.scriptObject, "addProperty not on register"); + if ((rnumObject != instanceReg) && (rnumObject != classReg)) { + throw new AssertException("unexpected addProperty object register " + rnumObject); + } + + if (cm.arguments.size() != 3) { + throw new AssertException("invalid number of arguments to addProperty: " + cm.arguments.size()); + } + GraphTargetItem propertyName = cm.arguments.get(0); + GraphTargetItem propertyGetter = cm.arguments.get(1); + GraphTargetItem propertySetter = cm.arguments.get(2); + String propertyNameStr = getAsString(propertyName, "propertyName"); + if (propertyGetter instanceof GetMemberActionItem) { + int regId = getAsRegisterNum(((GetMemberActionItem) propertyGetter).object, "getter member not register"); + if (rnumObject != regId) { + throw new AssertException("getter register does not match property register " + regId + " <=> " + rnumObject); + } + String getterNameStr = getAsString(((GetMemberActionItem) propertyGetter).memberName, "getter memberName"); + if (!(getterNameStr.equals("__get__" + propertyNameStr))) { + throw new AssertException("getter does not match property name"); + } + //TODO: handle getter HERE + + } else if (propertyGetter instanceof FunctionActionItem) { + FunctionActionItem getterFunc = (FunctionActionItem) propertyGetter; + if (!(getterFunc.actions.isEmpty() && getterFunc.functionName.isEmpty() && ((FunctionActionItem) propertyGetter).paramNames.isEmpty())) { + logger.severe("Cannot detect class - unexpected getter value for property " + propertyNameStr); + break loopcheck; + } + //we got empty getter + } else { + logger.severe("Cannot detect class - unexpected getter value for property " + propertyNameStr + ": " + propertyGetter.getClass().getSimpleName()); + break loopcheck; + } + + if (propertySetter instanceof GetMemberActionItem) { + int regId = getAsRegisterNum(((GetMemberActionItem) propertySetter).object, "setter member"); + if (rnumObject != regId) { + throw new AssertException("setter register does not match property register " + regId + " <=> " + rnumObject); + } + String setterNameStr = getAsString(((GetMemberActionItem) propertySetter).memberName, "setter memberNAme"); + if (!(setterNameStr.equals("__set__" + propertyNameStr))) { + throw new AssertException("setter does not match property name"); + } + //TODO: handle setter HERE + } else if (propertySetter instanceof FunctionActionItem) { + FunctionActionItem setterFunc = (FunctionActionItem) propertySetter; + if (!(setterFunc.actions.isEmpty() && setterFunc.functionName.isEmpty() && ((FunctionActionItem) propertySetter).paramNames.isEmpty())) { + throw new AssertException("unexpected getter value for property " + propertyNameStr); + } + //we got empty setter + } else { + throw new AssertException("unexpected setter value for property " + propertyNameStr + ": " + propertySetter.getClass().getSimpleName()); + } + + } else { + throw new AssertException("unknown push method name: " + pushMethodName); + } + + } else if (pi.value instanceof CallFunctionActionItem) { + CallFunctionActionItem cf = (CallFunctionActionItem) pi.value; + String funName = getAsString(cf.functionName, "pushitem function name"); + if (funName.equals("ASSetPropFlags")) { + //it should be ASSetPropFlags(a.b.c.D.prototype,null,1) as it sets prototype to hidden + //see http://www.ryanjuckett.com/programming/how-to-use-assetpropflags-in-actionscript-2-0/ + if (cf.arguments.size() != 3) { + throw new AssertException("Invalid number of arguments to ASSetPropFlags:" + cf.arguments.size() + ", 3 expected"); + } + GraphTargetItem obj = cf.arguments.get(0); + GraphTargetItem props = cf.arguments.get(1); + GraphTargetItem flags = cf.arguments.get(2); + List path = getMembersPath(obj); + if (path != null && !path.isEmpty() && "_global".equals(path.get(0))) { //For classes in toplevel package, there's _global in path + path.remove(0); //remove that _global + } + List classPathWithPrototype = new ArrayList<>(); + classPathWithPrototype.addAll(classNamePath); + classPathWithPrototype.add("prototype"); + if (!classPathWithPrototype.equals(path)) { + throw new AssertException("ASSetPropFlags not on prototype"); + } + if (!((props instanceof DirectValueActionItem) && (((DirectValueActionItem) props).value == Null.INSTANCE))) { + throw new AssertException("ASSetPropFlags properties param not null"); + } + if (!((flags instanceof DirectValueActionItem) && (((DirectValueActionItem) flags).value == (Long) 1L))) { + throw new AssertException("ASSetPropFlags flags not set to 1"); + } + } else { + throw new AssertException("unknown pushitem function call " + funName); + } + } else { + throw new AssertException("unknown pushitem - " + pi.value.getClass().getSimpleName()); + } + } else { + throw new AssertException("unknown item - " + item.getClass().getSimpleName()); + } + }//end loop pushes + + if (constructor != null) { //constructor should be there always, but just in calse + //add constructor as trait + traitsStatic.add(0, false); + DirectValueActionItem classBaseName = new DirectValueActionItem(classNamePath.get(classNamePath.size() - 1)); + ((FunctionActionItem) constructor).calculatedFunctionName = classBaseName; + traits.add(0, new MyEntry<>(classBaseName, constructor)); + } else { + throw new AssertException("No constructor found"); + } + + ClassActionItem clsItem = new ClassActionItem(classNameTargetPath, extendsOp, implementsOp, traits, traitsStatic); + for (int k = pos; k <= checkPos; k++) { + commands.remove(pos); + } + commands.add(pos, clsItem); + + //remove §§pop after, if it's there + if (pos + 1 < commands.size()) { + if (commands.get(pos + 1) instanceof PopItem) { + commands.remove(pos + 1); + } + } + + // goto next line and check next classes + continue looppos; + } catch (AssertException ex) { + logger.log(Level.WARNING, "{0}: Cannot detect class - {1}", new Object[]{scriptPath, ex.getCondition()}); + break loopcheck; + } + } else { + break loopcheck; //not !_global.a.b or not member of previous + } + } else { + break loopcheck; //not an if ! + } + } else { + break loopcheck; //not an if + } + } //loopcheck + }//looppos + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 2d21d6dbc..0347d2c0c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.BaseLocalData; @@ -643,25 +644,25 @@ public class Graph { System.err.println("");//*/ List ret = printGraph(new HashMap<>(), new HashMap<>(), localData, stack, allParts, null, heads.get(0), null, loops, staticOperation, path); processIfs(ret); - finalProcessStack(stack, ret); - finalProcessAll(ret, 0, new FinalProcessLocalData()); + finalProcessStack(stack, ret, path); + finalProcessAll(ret, 0, new FinalProcessLocalData(), path); return ret; } - public void finalProcessStack(TranslateStack stack, List output) { + public void finalProcessStack(TranslateStack stack, List output, String path) { } - private void finalProcessAll(List list, int level, FinalProcessLocalData localData) throws InterruptedException { - finalProcess(list, level, localData); + private void finalProcessAll(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { + finalProcess(list, level, localData, path); for (GraphTargetItem item : list) { if (item instanceof Block) { List> subs = ((Block) item).getSubs(); for (List sub : subs) { - finalProcessAll(sub, level + 1, localData); + finalProcessAll(sub, level + 1, localData, path); } } } - finalProcessAfter(list, level, localData); + finalProcessAfter(list, level, localData, path); } private boolean processSubBlk(Block b, GraphTargetItem replacement) { @@ -703,7 +704,7 @@ public class Graph { return allSubPush && atleastOne; } - protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData) { + protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { if (list.size() >= 2) { if (list.get(list.size() - 1) instanceof ExitItem) { ExitItem e = (ExitItem) list.get(list.size() - 1); @@ -719,7 +720,7 @@ public class Graph { } } - protected void finalProcess(List list, int level, FinalProcessLocalData localData) throws InterruptedException { + protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { //For detection based on debug line information boolean[] toDelete = new boolean[list.size()]; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/Reference.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/Reference.java similarity index 91% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/Reference.java rename to libsrc/ffdec_lib/src/com/jpexs/helpers/Reference.java index 04e3465f1..6b86b8ca7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/Reference.java +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/Reference.java @@ -12,8 +12,9 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ -package com.jpexs.decompiler.flash.abc.avm2.parser.script; + * License along with this library. + */ +package com.jpexs.helpers; /** * diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 4c20d3422..ebe9bd36d 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -35,7 +35,7 @@ import com.jpexs.decompiler.flash.SwfOpenException; import com.jpexs.decompiler.flash.UrlResolver; import com.jpexs.decompiler.flash.Version; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration; import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index a8d1732b5..36f463c38 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -27,7 +27,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 485208609..0e6a42a48 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -24,7 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.abc.types.ClassInfo; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.Multiname; diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java index 06c67ecbe..5bbdded28 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java @@ -16,7 +16,7 @@ */ package com.jpexs.decompiler.flash.gui.editor; -import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference; +import com.jpexs.helpers.Reference; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.gui.AppStrings; import java.awt.Color;