diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/InstanceOfIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/InstanceOfIns.java index 83505db8e..d97a6b3e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/InstanceOfIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/InstanceOfIns.java @@ -1,50 +1,50 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.InstanceOfAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class InstanceOfIns extends InstructionDefinition { - - public InstanceOfIns() { - super(0xb1, "instanceof", new int[]{}, true); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem type = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new InstanceOfAVM2Item(ins, value, type)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.InstanceOfAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class InstanceOfIns extends InstructionDefinition { + + public InstanceOfIns() { + super(0xb1, "instanceof", new int[]{}, true); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem type = stack.pop(); + GraphTargetItem value = stack.pop(); + stack.push(new InstanceOfAVM2Item(ins, value, type)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeIns.java index 37c5e803b..daddc0630 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeIns.java @@ -1,51 +1,51 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class IsTypeIns extends InstructionDefinition { - - public IsTypeIns() { - super(0xb2, "istype", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - int multinameIndex = ins.operands[0]; - GraphTargetItem value = stack.pop(); - stack.push(new IsTypeAVM2Item(ins, value, new FullMultinameAVM2Item(ins, multinameIndex))); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; //may not be runtime multiname - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class IsTypeIns extends InstructionDefinition { + + public IsTypeIns() { + super(0xb2, "istype", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + int multinameIndex = ins.operands[0]; + GraphTargetItem value = stack.pop(); + stack.push(new IsTypeAVM2Item(ins, value, new FullMultinameAVM2Item(ins, multinameIndex))); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; //may not be runtime multiname + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeLateIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeLateIns.java index 734f3fc1c..0b52d7ba4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeLateIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/IsTypeLateIns.java @@ -1,50 +1,50 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class IsTypeLateIns extends InstructionDefinition { - - public IsTypeLateIns() { - super(0xb3, "istypelate", new int[]{}, true); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem type = stack.pop(); - GraphTargetItem value = stack.pop(); - stack.push(new IsTypeAVM2Item(ins, value, type)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -2 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.IsTypeAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class IsTypeLateIns extends InstructionDefinition { + + public IsTypeLateIns() { + super(0xb3, "istypelate", new int[]{}, true); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem type = stack.pop(); + GraphTargetItem value = stack.pop(); + stack.push(new IsTypeAVM2Item(ins, value, type)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -2 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/TypeOfIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/TypeOfIns.java index c879ba890..93c390866 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/TypeOfIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/TypeOfIns.java @@ -1,48 +1,48 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.operations.TypeOfAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class TypeOfIns extends InstructionDefinition { - - public TypeOfIns() { - super(0x95, "typeof", new int[]{}, false); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new TypeOfAVM2Item(ins, stack.pop())); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.TypeOfAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class TypeOfIns extends InstructionDefinition { + + public TypeOfIns() { + super(0x95, "typeof", new int[]{}, false); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new TypeOfAVM2Item(ins, stack.pop())); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/CheckFilterIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/CheckFilterIns.java index c2eb0e741..890c8e2a6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/CheckFilterIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/CheckFilterIns.java @@ -1,55 +1,55 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class CheckFilterIns extends InstructionDefinition { - - public CheckFilterIns() { - super(0x78, "checkfilter", new int[]{}, true); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - //if pop() is not XML|XMLList throw - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem obj = stack.pop(); - stack.push(new FilteredCheckAVM2Item(ins, obj)); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class CheckFilterIns extends InstructionDefinition { + + public CheckFilterIns() { + super(0x78, "checkfilter", new int[]{}, true); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + //if pop() is not XML|XMLList throw + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem obj = stack.pop(); + stack.push(new FilteredCheckAVM2Item(ins, obj)); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java index a6066933c..1554e35a8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSIns.java @@ -1,54 +1,54 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.DefaultXMLNamespace; -import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class DXNSIns extends InstructionDefinition { - - public DXNSIns() { - super(0x06, "dxns", new int[]{AVM2Code.DAT_STRING_INDEX}, true); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - int strIndex = (int) ((Long) arguments.get(0)).longValue(); - String s = constants.getString(strIndex); - System.out.println("Set default XML space " + s); - - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - //FIXME!!! - search namespace - output.add(new DefaultXMLNamespace(ins, new StringAVM2Item(ins, constants.getString(ins.operands[0])))); - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.DefaultXMLNamespace; +import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class DXNSIns extends InstructionDefinition { + + public DXNSIns() { + super(0x06, "dxns", new int[]{AVM2Code.DAT_STRING_INDEX}, true); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + int strIndex = (int) ((Long) arguments.get(0)).longValue(); + String s = constants.getString(strIndex); + System.out.println("Set default XML space " + s); + + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + //FIXME!!! - search namespace + output.add(new DefaultXMLNamespace(ins, new StringAVM2Item(ins, constants.getString(ins.operands[0])))); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java index f87ab09af..dec64d8b4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/DXNSLateIns.java @@ -1,57 +1,57 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.DefaultXMLNamespace; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class DXNSLateIns extends InstructionDefinition { - - public DXNSLateIns() { - super(0x07, "dxnslate", new int[]{}, true); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - String s = lda.operandStack.pop().toString(); - System.out.println("Set default XML space " + s); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - GraphTargetItem xmlns = stack.pop(); - output.add(new DefaultXMLNamespace(ins, xmlns)); - - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.DefaultXMLNamespace; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class DXNSLateIns extends InstructionDefinition { + + public DXNSLateIns() { + super(0x07, "dxnslate", new int[]{}, true); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + String s = lda.operandStack.pop().toString(); + System.out.println("Set default XML space " + s); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + GraphTargetItem xmlns = stack.pop(); + output.add(new DefaultXMLNamespace(ins, xmlns)); + + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXAttrIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXAttrIns.java index a6ed1b67b..81949e578 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXAttrIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXAttrIns.java @@ -1,56 +1,56 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.EscapeXAttrAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class EscXAttrIns extends InstructionDefinition { - - public EscXAttrIns() { - super(0x72, "esc_xattr", new int[]{}, true); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - String s = lda.operandStack.pop().toString(); - //escape - lda.operandStack.push(s); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new EscapeXAttrAVM2Item(ins, stack.pop())); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.EscapeXAttrAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class EscXAttrIns extends InstructionDefinition { + + public EscXAttrIns() { + super(0x72, "esc_xattr", new int[]{}, true); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + String s = lda.operandStack.pop().toString(); + //escape + lda.operandStack.push(s); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new EscapeXAttrAVM2Item(ins, stack.pop())); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXElemIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXElemIns.java index 0aff0f51f..1a00051c6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXElemIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/EscXElemIns.java @@ -1,56 +1,56 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.model.EscapeXElemAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; -import java.util.HashMap; -import java.util.List; - -public class EscXElemIns extends InstructionDefinition { - - public EscXElemIns() { - super(0x71, "esc_xelem", new int[]{}, true); - } - - @Override - public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { - String s = lda.operandStack.pop().toString(); - //escape - lda.operandStack.push(s); - } - - @Override - public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { - stack.push(new EscapeXElemAVM2Item(ins, stack.pop())); - } - - @Override - public int getStackDelta(AVM2Instruction ins, ABC abc) { - return -1 + 1; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.instructions.xml; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.EscapeXElemAVM2Item; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.ScopeStack; +import com.jpexs.decompiler.graph.TranslateStack; +import java.util.HashMap; +import java.util.List; + +public class EscXElemIns extends InstructionDefinition { + + public EscXElemIns() { + super(0x71, "esc_xelem", new int[]{}, true); + } + + @Override + public void execute(LocalDataArea lda, AVM2ConstantPool constants, List arguments) { + String s = lda.operandStack.pop().toString(); + //escape + lda.operandStack.push(s); + } + + @Override + public void translate(boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2ConstantPool constants, AVM2Instruction ins, List method_info, List output, MethodBody body, ABC abc, HashMap localRegNames, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, HashMap> refs, AVM2Code code) { + stack.push(new EscapeXElemAVM2Item(ins, stack.pop())); + } + + @Override + public int getStackDelta(AVM2Instruction ins, ABC abc) { + return -1 + 1; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java index 303cc74fc..8ca8ea88c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ExceptionMarkAVM2Instruction.java @@ -1,43 +1,43 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.parser.script; - -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; - -/** - * - * @author JPEXS - */ -public class ExceptionMarkAVM2Instruction extends AVM2Instruction { - - public int markType; - - public int exceptionId; - - public ExceptionMarkAVM2Instruction(int exceptionId, int markType) { - super(0, null, null); - this.markType = markType; - this.exceptionId = exceptionId; - this.definition = new InstructionDefinition(0, "--mark", new int[0], false /*?*/); - } - - @Override - public byte[] getBytes() { - return new byte[0]; - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.parser.script; + +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; + +/** + * + * @author JPEXS + */ +public class ExceptionMarkAVM2Instruction extends AVM2Instruction { + + public int markType; + + public int exceptionId; + + public ExceptionMarkAVM2Instruction(int exceptionId, int markType) { + super(0, null, null); + this.markType = markType; + this.exceptionId = exceptionId; + this.definition = new InstructionDefinition(0, "--mark", new int[0], false /*?*/); + } + + @Override + public byte[] getBytes() { + return new byte[0]; + } +} 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 1d0d66740..2f37ccd59 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 @@ -1,355 +1,355 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.parser.script; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertBIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertUIns; -import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NanAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; -import com.jpexs.decompiler.flash.abc.types.NamespaceSet; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.TypeItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.decompiler.graph.model.UnboundedTypeItem; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class NameAVM2Item extends AssignableAVM2Item { - - private String variableName; - - private boolean definition; - - private int nsKind = -1; - - public List openedNamespaces; - - public int line; - - public GraphTargetItem type; - - private GraphTargetItem ns = null; - - private int regNumber = -1; - - public boolean unresolved = false; - - private int slotNumber = -1; - - private int slotScope = 0; - - public GraphTargetItem redirect; - - @Override - public AssignableAVM2Item copy() { - NameAVM2Item c = new NameAVM2Item(type, line, variableName, assignedValue, definition, openedNamespaces); - c.setNs(ns); - c.regNumber = regNumber; - c.unresolved = unresolved; - c.nsKind = nsKind; - return c; - } - - public void setSlotScope(int slotScope) { - this.slotScope = slotScope; - } - - public int getSlotScope() { - return slotScope; - } - - public void setNs(GraphTargetItem ns) { - this.ns = ns; - } - - public void setRegNumber(int regNumber) { - this.regNumber = regNumber; - } - - public int getSlotNumber() { - return slotNumber; - } - - public void setSlotNumber(int slotNumber) { - this.slotNumber = slotNumber; - } - - public int getRegNumber() { - return regNumber; - } - - public GraphTargetItem getNs() { - return ns; - } - - public void appendName(String name) { - this.variableName += "." + name; - } - - public void setDefinition(boolean definition) { - this.definition = definition; - } - - public void setNsKind(int nsKind) { - this.nsKind = nsKind; - } - - public int getNsKind() { - return nsKind; - } - - public String getVariableName() { - return variableName; - } - - public NameAVM2Item(GraphTargetItem type, int line, String variableName, GraphTargetItem storeValue, boolean definition, List openedNamespaces) { - super(storeValue); - this.variableName = variableName; - this.assignedValue = storeValue; - this.definition = definition; - this.line = line; - this.type = type; - this.openedNamespaces = openedNamespaces; - } - - public boolean isDefinition() { - return definition; - } - - public GraphTargetItem getStoreValue() { - return assignedValue; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - return writer; - } - - private int allNsSet(ABC abc) { - int[] nssa = new int[openedNamespaces.size()]; - for (int i = 0; i < openedNamespaces.size(); i++) { - nssa[i] = openedNamespaces.get(i); - } - return abc.constants.getNamespaceSetId(new NamespaceSet(nssa), true); - } - - public static GraphTargetItem getDefaultValue(String type) { - switch (type) { - case "*": - return new UndefinedAVM2Item(null); - case "int": - return new IntegerValueAVM2Item(null, 0L); - case "Number": - return new NanAVM2Item(null); - default: - return new NullAVM2Item(null); - } - } - - public static AVM2Instruction generateCoerce(SourceGeneratorLocalData localData, SourceGenerator generator, GraphTargetItem ttype) throws CompilationException { - if (ttype instanceof UnresolvedAVM2Item) { - ttype = ((UnresolvedAVM2Item) ttype).resolved; - } - AVM2Instruction ins; - if (ttype instanceof UnboundedTypeItem) { - ins = ins(new CoerceAIns()); - } else { - switch (ttype.toString()) { - case "int": - ins = ins(new ConvertIIns()); - break; - case "*": - ins = ins(new CoerceAIns()); - break; - case "String": - ins = ins(new CoerceSIns()); - break; - case "Boolean": - ins = ins(new ConvertBIns()); - break; - case "uint": - ins = ins(new ConvertUIns()); - break; - default: - int type_index = AVM2SourceGenerator.resolveType(localData, ttype, ((AVM2SourceGenerator) generator).abc, ((AVM2SourceGenerator) generator).allABCs); - ins = ins(new CoerceIns(), type_index); - break; - } - } - return ins; - } - - private List toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn) throws CompilationException { - if (variableName != null && regNumber == -1 && slotNumber == -1 && ns == null) { - throw new CompilationException("No register or slot set for " + variableName, line); - } - if (definition && assignedValue == null) { - return new ArrayList<>(); - } - String name = variableName; - boolean attr = false; - if (name != null && name.startsWith("@")) { - name = name.substring(1); - attr = true; - } - AVM2SourceGenerator g = (AVM2SourceGenerator) generator; - Reference ns_temp = new Reference<>(-1); - Reference index_temp = new Reference<>(-1); - Reference ret_temp = new Reference<>(-1); - - if (assignedValue != null) { - List basicTypes = Arrays.asList("int", "Number"); - if (slotNumber > -1) { - return toSourceMerge(localData, generator, - ins(new GetScopeObjectIns(), slotScope), - assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn - ? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1 - ? ins(new SetSlotIns(), slotNumber) - : null, - needsReturn ? getTemp(localData, generator, ret_temp) : null, - killTemp(localData, generator, Arrays.asList(ret_temp))); - } else { - - return toSourceMerge(localData, generator, assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn - ? ins(new DupIns()) : null, generateSetLoc(regNumber)); - } - } else { - return toSourceMerge(localData, generator, generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), - needsReturn ? null : ins(new PopIns())); - } - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (redirect != null) { - return redirect.toSource(localData, generator); - } - return toSource(localData, generator, true); - - } - - @Override - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (redirect != null) { - return redirect.toSourceIgnoreReturnValue(localData, generator); - } - return toSource(localData, generator, false); - } - - @Override - public boolean hasReturnValue() { - if (definition) { - return false; - } - return true; - } - - @Override - public boolean needsSemicolon() { - if (definition) { - return true; - } - return false; - } - - @Override - public String toString() { - return variableName; - } - - @Override - public GraphTargetItem returnType() { - if (type == null) { - return TypeItem.UNBOUNDED; - } - return type; - } - - @Override - public List toSourceChange(SourceGeneratorLocalData localData, SourceGenerator generator, boolean post, boolean decrement, boolean needsReturn) throws CompilationException { - if (redirect != null) { - return ((AssignableAVM2Item) redirect).toSourceChange(localData, generator, post, decrement, needsReturn); - } - AVM2SourceGenerator g = (AVM2SourceGenerator) generator; - Reference ns_temp = new Reference<>(-1); - Reference name_temp = new Reference<>(-1); - Reference index_temp = new Reference<>(-1); - Reference ret_temp = new Reference<>(-1); - boolean isInteger = returnType().toString().equals("int"); - /* - - - */ - if (!needsReturn) { - if (slotNumber > -1) { - return toSourceMerge(localData, generator, - ins(new GetScopeObjectIns(), slotScope), - generateGetSlot(slotScope, slotNumber), - (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())), - ins(new SetSlotIns(), slotNumber) - ); - } else { - return toSourceMerge(localData, generator, - (decrement ? ins(isInteger ? new DecLocalIIns() : new DecLocalIns(), regNumber) : ins(isInteger ? new IncLocalIIns() : new IncLocalIns(), regNumber))); - } - } - return toSourceMerge(localData, generator, - slotNumber > -1 ? ins(new GetScopeObjectIns(), slotScope) : null, - //Start get original - generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), - //End get original - //!isInteger ? ins(new ConvertDIns()) : null, - //End get original - (!post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, - needsReturn ? ins(new DupIns()) : null, - (post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, - generateCoerce(localData, generator, returnType()), - generateSetLoc(regNumber), - slotNumber > -1 ? ins(new SetSlotIns(), slotNumber) : null - ); - } -} +/* + * Copyright (C) 2010-2015 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.abc.avm2.parser.script; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertBIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertUIns; +import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NanAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.types.NamespaceSet; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.UnboundedTypeItem; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class NameAVM2Item extends AssignableAVM2Item { + + private String variableName; + + private boolean definition; + + private int nsKind = -1; + + public List openedNamespaces; + + public int line; + + public GraphTargetItem type; + + private GraphTargetItem ns = null; + + private int regNumber = -1; + + public boolean unresolved = false; + + private int slotNumber = -1; + + private int slotScope = 0; + + public GraphTargetItem redirect; + + @Override + public AssignableAVM2Item copy() { + NameAVM2Item c = new NameAVM2Item(type, line, variableName, assignedValue, definition, openedNamespaces); + c.setNs(ns); + c.regNumber = regNumber; + c.unresolved = unresolved; + c.nsKind = nsKind; + return c; + } + + public void setSlotScope(int slotScope) { + this.slotScope = slotScope; + } + + public int getSlotScope() { + return slotScope; + } + + public void setNs(GraphTargetItem ns) { + this.ns = ns; + } + + public void setRegNumber(int regNumber) { + this.regNumber = regNumber; + } + + public int getSlotNumber() { + return slotNumber; + } + + public void setSlotNumber(int slotNumber) { + this.slotNumber = slotNumber; + } + + public int getRegNumber() { + return regNumber; + } + + public GraphTargetItem getNs() { + return ns; + } + + public void appendName(String name) { + this.variableName += "." + name; + } + + public void setDefinition(boolean definition) { + this.definition = definition; + } + + public void setNsKind(int nsKind) { + this.nsKind = nsKind; + } + + public int getNsKind() { + return nsKind; + } + + public String getVariableName() { + return variableName; + } + + public NameAVM2Item(GraphTargetItem type, int line, String variableName, GraphTargetItem storeValue, boolean definition, List openedNamespaces) { + super(storeValue); + this.variableName = variableName; + this.assignedValue = storeValue; + this.definition = definition; + this.line = line; + this.type = type; + this.openedNamespaces = openedNamespaces; + } + + public boolean isDefinition() { + return definition; + } + + public GraphTargetItem getStoreValue() { + return assignedValue; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + return writer; + } + + private int allNsSet(ABC abc) { + int[] nssa = new int[openedNamespaces.size()]; + for (int i = 0; i < openedNamespaces.size(); i++) { + nssa[i] = openedNamespaces.get(i); + } + return abc.constants.getNamespaceSetId(new NamespaceSet(nssa), true); + } + + public static GraphTargetItem getDefaultValue(String type) { + switch (type) { + case "*": + return new UndefinedAVM2Item(null); + case "int": + return new IntegerValueAVM2Item(null, 0L); + case "Number": + return new NanAVM2Item(null); + default: + return new NullAVM2Item(null); + } + } + + public static AVM2Instruction generateCoerce(SourceGeneratorLocalData localData, SourceGenerator generator, GraphTargetItem ttype) throws CompilationException { + if (ttype instanceof UnresolvedAVM2Item) { + ttype = ((UnresolvedAVM2Item) ttype).resolved; + } + AVM2Instruction ins; + if (ttype instanceof UnboundedTypeItem) { + ins = ins(new CoerceAIns()); + } else { + switch (ttype.toString()) { + case "int": + ins = ins(new ConvertIIns()); + break; + case "*": + ins = ins(new CoerceAIns()); + break; + case "String": + ins = ins(new CoerceSIns()); + break; + case "Boolean": + ins = ins(new ConvertBIns()); + break; + case "uint": + ins = ins(new ConvertUIns()); + break; + default: + int type_index = AVM2SourceGenerator.resolveType(localData, ttype, ((AVM2SourceGenerator) generator).abc, ((AVM2SourceGenerator) generator).allABCs); + ins = ins(new CoerceIns(), type_index); + break; + } + } + return ins; + } + + private List toSource(SourceGeneratorLocalData localData, SourceGenerator generator, boolean needsReturn) throws CompilationException { + if (variableName != null && regNumber == -1 && slotNumber == -1 && ns == null) { + throw new CompilationException("No register or slot set for " + variableName, line); + } + if (definition && assignedValue == null) { + return new ArrayList<>(); + } + String name = variableName; + boolean attr = false; + if (name != null && name.startsWith("@")) { + name = name.substring(1); + attr = true; + } + AVM2SourceGenerator g = (AVM2SourceGenerator) generator; + Reference ns_temp = new Reference<>(-1); + Reference index_temp = new Reference<>(-1); + Reference ret_temp = new Reference<>(-1); + + if (assignedValue != null) { + List basicTypes = Arrays.asList("int", "Number"); + if (slotNumber > -1) { + return toSourceMerge(localData, generator, + ins(new GetScopeObjectIns(), slotScope), + assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn + ? dupSetTemp(localData, generator, ret_temp) : null, generateSetLoc(regNumber), slotNumber > -1 + ? ins(new SetSlotIns(), slotNumber) + : null, + needsReturn ? getTemp(localData, generator, ret_temp) : null, + killTemp(localData, generator, Arrays.asList(ret_temp))); + } else { + + return toSourceMerge(localData, generator, assignedValue, !(("" + assignedValue.returnType()).equals("" + type) && (basicTypes.contains("" + type))) ? generateCoerce(localData, generator, type) : null, needsReturn + ? ins(new DupIns()) : null, generateSetLoc(regNumber)); + } + } else { + return toSourceMerge(localData, generator, generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), + needsReturn ? null : ins(new PopIns())); + } + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + if (redirect != null) { + return redirect.toSource(localData, generator); + } + return toSource(localData, generator, true); + + } + + @Override + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + if (redirect != null) { + return redirect.toSourceIgnoreReturnValue(localData, generator); + } + return toSource(localData, generator, false); + } + + @Override + public boolean hasReturnValue() { + if (definition) { + return false; + } + return true; + } + + @Override + public boolean needsSemicolon() { + if (definition) { + return true; + } + return false; + } + + @Override + public String toString() { + return variableName; + } + + @Override + public GraphTargetItem returnType() { + if (type == null) { + return TypeItem.UNBOUNDED; + } + return type; + } + + @Override + public List toSourceChange(SourceGeneratorLocalData localData, SourceGenerator generator, boolean post, boolean decrement, boolean needsReturn) throws CompilationException { + if (redirect != null) { + return ((AssignableAVM2Item) redirect).toSourceChange(localData, generator, post, decrement, needsReturn); + } + AVM2SourceGenerator g = (AVM2SourceGenerator) generator; + Reference ns_temp = new Reference<>(-1); + Reference name_temp = new Reference<>(-1); + Reference index_temp = new Reference<>(-1); + Reference ret_temp = new Reference<>(-1); + boolean isInteger = returnType().toString().equals("int"); + /* + + + */ + if (!needsReturn) { + if (slotNumber > -1) { + return toSourceMerge(localData, generator, + ins(new GetScopeObjectIns(), slotScope), + generateGetSlot(slotScope, slotNumber), + (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())), + ins(new SetSlotIns(), slotNumber) + ); + } else { + return toSourceMerge(localData, generator, + (decrement ? ins(isInteger ? new DecLocalIIns() : new DecLocalIns(), regNumber) : ins(isInteger ? new IncLocalIIns() : new IncLocalIns(), regNumber))); + } + } + return toSourceMerge(localData, generator, + slotNumber > -1 ? ins(new GetScopeObjectIns(), slotScope) : null, + //Start get original + generateGetLoc(regNumber), generateGetSlot(slotScope, slotNumber), + //End get original + //!isInteger ? ins(new ConvertDIns()) : null, + //End get original + (!post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, + needsReturn ? ins(new DupIns()) : null, + (post) ? (decrement ? ins(isInteger ? new DecrementIIns() : new DecrementIns()) : ins(isInteger ? new IncrementIIns() : new IncrementIns())) : null, + generateCoerce(localData, generator, returnType()), + generateSetLoc(regNumber), + slotNumber > -1 ? ins(new SetSlotIns(), slotNumber) : null + ); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java index 4b06b8220..6e7b0a173 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/SymbolType.java @@ -1,242 +1,242 @@ -/* - * Copyright (C) 2010-2015 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.abc.avm2.parser.script; - -import com.jpexs.decompiler.graph.GraphTargetItem; - -/** - * - * @author JPEXS - */ -public enum SymbolType { - //Keywords - - BREAK, - CASE, - CONTINUE, - DEFAULT, - DO, - WHILE, - ELSE, - FOR, - EACH, - IN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IF, - RETURN, - SUPER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SWITCH, - THROW, - TRY, - CATCH, - FINALLY, - WITH, - DYNAMIC, - INTERNAL, - OVERRIDE, - PRIVATE, - PROTECTED, - PUBLIC, - STATIC, - CLASS, - CONST, - EXTENDS, - FUNCTION(GraphTargetItem.PRECEDENCE_PRIMARY, false), - GET, - IMPLEMENTS, - INTERFACE, - NAMESPACE, - PACKAGE, - SET, - VAR, - IMPORT, - USE, - FALSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NULL(GraphTargetItem.PRECEDENCE_PRIMARY, false), - THIS(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TRUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //Operators - PARENT_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - PARENT_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - CURLY_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_OPEN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - BRACKET_CLOSE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - SEMICOLON, - COMMA(GraphTargetItem.PRECEDENCE_COMMA, false), - REST, - DOT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - ASSIGN(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - GREATER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - LOWER_THAN(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT(GraphTargetItem.PRECEDENCE_UNARY, false), - NEGATE(GraphTargetItem.PRECEDENCE_UNARY, false), - TERNAR(GraphTargetItem.PRECEDENCE_CONDITIONAL, true, true), /*!! ternar !!!*/ - COLON(GraphTargetItem.PRECEDENCE_CONDITIONAL, false),/*!! ternar !!!*/ - EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_EQUALS(GraphTargetItem.PRECEDENCE_EQUALITY, true), - LOWER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - GREATER_EQUAL(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - STRICT_NOT_EQUAL(GraphTargetItem.PRECEDENCE_EQUALITY, true), - AND(GraphTargetItem.PRECEDENCE_LOGICALAND, true), - OR(GraphTargetItem.PRECEDENCE_LOGICALOR, true), - INCREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false),//OR Unary - DECREMENT(GraphTargetItem.PRECEDENCE_POSTFIX, false), //OR Unary - PLUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), - MINUS(GraphTargetItem.PRECEDENCE_ADDITIVE, true), //OR Unary - MULTIPLY(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - DIVIDE(GraphTargetItem.PRECEDENCE_MULTIPLICATIVE, true), - BITAND(GraphTargetItem.PRECEDENCE_BITWISEAND, true), - BITOR(GraphTargetItem.PRECEDENCE_BITWISEOR, true), - XOR(GraphTargetItem.PRECEDENCE_BITWISEXOR, true), - MODULO(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_LEFT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_BITWISESHIFT, true), - ASSIGN_PLUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MINUS(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MULTIPLY(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_DIVIDE(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITAND(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_BITOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_XOR(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_MODULO(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_LEFT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_SHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - ASSIGN_USHIFT_RIGHT(GraphTargetItem.PRECEDENCE_ASSIGMENT, true, true), - AS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - DELETE(GraphTargetItem.PRECEDENCE_UNARY, false), - INSTANCEOF(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - IS(GraphTargetItem.PRECEDENCE_RELATIONAL, true), - NAMESPACE_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - NEW(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPEOF(GraphTargetItem.PRECEDENCE_UNARY, false), - VOID, - ATTRIBUTE, - //Other - STRING(GraphTargetItem.PRECEDENCE_PRIMARY, false), - COMMENT, - //XML, - IDENTIFIER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - INTEGER(GraphTargetItem.PRECEDENCE_PRIMARY, false), - DOUBLE(GraphTargetItem.PRECEDENCE_PRIMARY, false), - TYPENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), - EOF, - //TRACE, - //GETURL, - //GOTOANDSTOP, - //NEXTFRAME, - //PLAY, - //PREVFRAME, - //TELLTARGET, - //STOP, - //STOPALLSOUNDS, - //TOGGLEHIGHQUALITY, - //ORD, - //CHR, - //DUPLICATEMOVIECLIP, - //STOPDRAG, - //GETTIMER, - //LOADVARIABLES, - //LOADMOVIE, - //GOTOANDPLAY, - //MBORD, - //MBCHR, - //MBLENGTH, - //MBSUBSTRING, - //RANDOM, - //REMOVEMOVIECLIP, - //STARTDRAG, - //SUBSTR, - //LENGTH, //string.length - INT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //TARGETPATH, - NUMBER_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - STRING_OP(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //IFFRAMELOADED, - INFINITY(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //EVAL, - UNDEFINED(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //NEWLINE, - NAN(GraphTargetItem.PRECEDENCE_PRIMARY, false), - //GETVERSION, - //CALL, - //LOADMOVIENUM, - //LOADVARIABLESNUM, - //PRINT, - //PRINTNUM, - //PRINTASBITMAP, - //PRINTASBITMAPNUM, - //UNLOADMOVIE, - //UNLOADMOVIENUM, - FINAL, - XML_STARTTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> - XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // - XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { - XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= - XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" - XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), - XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= - XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ - XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_FINISHVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_STARTFINISHTAG_END(GraphTargetItem.PRECEDENCE_PRIMARY, false), // /> + XML_COMMENT(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_CDATA(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_INSTR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // + XML_VAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // { + XML_ATTRIBUTENAME(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa= + XML_ATTRIBUTEVALUE(GraphTargetItem.PRECEDENCE_PRIMARY, false), // "vvv" + XML_TEXT(GraphTargetItem.PRECEDENCE_PRIMARY, false), + XML_ATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_ATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRATTRNAMEVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // {...}= + XML_INSTRATTRVALVAR_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // aaa={ + XML_INSTRVARTAG_BEGIN(GraphTargetItem.PRECEDENCE_PRIMARY, false), // fullyQualifiedNames) { - return "method_index=" + cinit_index + "\r\n" + static_traits.toString(abc, fullyQualifiedNames); - } -} +/* + * Copyright (C) 2010-2015 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.abc.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import java.util.List; + +public class ClassInfo { + + public int cinit_index; //MethodInfo - static initializer + + public Traits static_traits; + + @Internal + public boolean deleted; + + public ClassInfo() { + static_traits = new Traits(); + } + + public ClassInfo(Traits traits) { + static_traits = traits; + } + + @Override + public String toString() { + return "method_index=" + cinit_index + "\r\n" + static_traits.toString(); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + return "method_index=" + cinit_index + "\r\n" + static_traits.toString(abc, fullyQualifiedNames); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index 241567799..a97943b7d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -1,140 +1,140 @@ -/* - * Copyright (C) 2010-2015 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.abc.types; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.flash.types.annotations.Internal; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.List; - -public class InstanceInfo { - - public int name_index; - - public int super_index; - - public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs - - public int protectedNS; //if flags & 8 - - public int[] interfaces; - - public int iinit_index; // MethodInfo - constructor - - public Traits instance_traits; - - public static final int CLASS_SEALED = 1; //not dynamic - - public static final int CLASS_FINAL = 2; - - public static final int CLASS_INTERFACE = 4; - - public static final int CLASS_PROTECTEDNS = 8; - - @Internal - public boolean deleted; - - public InstanceInfo() { - instance_traits = new Traits(); - } - - public InstanceInfo(Traits traits) { - instance_traits = traits; - } - - @Override - public String toString() { - return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - String supIndexStr = "[nothing]"; - if (super_index > 0) { - supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); - } - return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); - } - - public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { - String modifiers; - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - modifiers = ns.getPrefix(abc); - if (!allowPrivate && modifiers.equals("private")) { - modifiers = ""; - } - if (!modifiers.isEmpty()) { - modifiers += " "; - } - - if (isFinal()) { - modifiers += "final "; - } - if (!isInterface() && isDynamic()) { - modifiers += "dynamic "; - } - String objType = "class "; - if (isInterface()) { - objType = "interface "; - } - - writer.appendNoHilight(modifiers + objType); - writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList<>()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); - - if (super_index > 0) { - String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants, true); - writer.appendNoHilight(" extends "); - writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - if (interfaces.length > 0) { - if (isInterface()) { - writer.appendNoHilight(" extends "); - } else { - writer.appendNoHilight(" implements "); - } - for (int i = 0; i < interfaces.length; i++) { - if (i > 0) { - writer.append(", "); - } - String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants, true); - writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); - } - } - - return writer; - } - - public Multiname getName(AVM2ConstantPool constants) { - return constants.getMultiname(name_index); - } - - public boolean isInterface() { - return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); - } - - public boolean isDynamic() { - return (flags & CLASS_SEALED) == 0; - } - - public boolean isFinal() { - return (flags & CLASS_FINAL) == CLASS_FINAL; - } -} +/* + * Copyright (C) 2010-2015 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.abc.types; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.List; + +public class InstanceInfo { + + public int name_index; + + public int super_index; + + public int flags; // 1 = sealed, 0 = dynamic, 2 = final, 4 = interface, 8 = ProtectedNs + + public int protectedNS; //if flags & 8 + + public int[] interfaces; + + public int iinit_index; // MethodInfo - constructor + + public Traits instance_traits; + + public static final int CLASS_SEALED = 1; //not dynamic + + public static final int CLASS_FINAL = 2; + + public static final int CLASS_INTERFACE = 4; + + public static final int CLASS_PROTECTEDNS = 8; + + @Internal + public boolean deleted; + + public InstanceInfo() { + instance_traits = new Traits(); + } + + public InstanceInfo(Traits traits) { + instance_traits = traits; + } + + @Override + public String toString() { + return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + String supIndexStr = "[nothing]"; + if (super_index > 0) { + supIndexStr = abc.constants.getMultiname(super_index).toString(abc.constants, fullyQualifiedNames); + } + return "name_index=" + abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " super_index=" + supIndexStr + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(abc, fullyQualifiedNames); + } + + public GraphTextWriter getClassHeaderStr(GraphTextWriter writer, ABC abc, List fullyQualifiedNames, boolean allowPrivate) { + String modifiers; + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + modifiers = ns.getPrefix(abc); + if (!allowPrivate && modifiers.equals("private")) { + modifiers = ""; + } + if (!modifiers.isEmpty()) { + modifiers += " "; + } + + if (isFinal()) { + modifiers += "final "; + } + if (!isInterface() && isDynamic()) { + modifiers += "dynamic "; + } + String objType = "class "; + if (isInterface()) { + objType = "interface "; + } + + writer.appendNoHilight(modifiers + objType); + writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, new ArrayList<>()/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); + + if (super_index > 0) { + String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants, true); + writer.appendNoHilight(" extends "); + writer.hilightSpecial(abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + if (interfaces.length > 0) { + if (isInterface()) { + writer.appendNoHilight(" extends "); + } else { + writer.appendNoHilight(" implements "); + } + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) { + writer.append(", "); + } + String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants, true); + writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); + } + } + + return writer; + } + + public Multiname getName(AVM2ConstantPool constants) { + return constants.getMultiname(name_index); + } + + public boolean isInterface() { + return ((flags & CLASS_INTERFACE) == CLASS_INTERFACE); + } + + public boolean isDynamic() { + return (flags & CLASS_SEALED) == 0; + } + + public boolean isFinal() { + return (flags & CLASS_FINAL) == CLASS_FINAL; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index ccdf13ee7..bc7bd4ed9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -1,200 +1,200 @@ -/* - * Copyright (C) 2010-2015 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.abc.types.traits; - -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.ClassPath; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.helpers.Helper; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -public abstract class Trait implements Serializable { - - private static final int[] EMPTY_METADATA_ARRAY = new int[0]; - - public int name_index; - - public int kindType; - - public int kindFlags; - - public int[] metadata = EMPTY_METADATA_ARRAY; - - public long fileOffset; - - public byte[] bytes; - - public static final int ATTR_Final = 0x1; - - public static final int ATTR_Override = 0x2; - - public static final int ATTR_Metadata = 0x4; - - public static final int TRAIT_SLOT = 0; - - public static final int TRAIT_METHOD = 1; - - public static final int TRAIT_GETTER = 2; - - public static final int TRAIT_SETTER = 3; - - public static final int TRAIT_CLASS = 4; - - public static final int TRAIT_FUNCTION = 5; - - public static final int TRAIT_CONST = 6; - - public abstract void delete(ABC abc, boolean d); - - public String getModifiers(ABC abc, boolean isStatic) { - String ret = ""; - if ((kindFlags & ATTR_Override) > 0) { - ret += "override"; - } - Multiname m = getName(abc); - if (m != null) { - String nsname = ""; - //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { - { - for (ABCContainerTag abcTag : abc.getAbcTags()) { - if (m.namespace_index == -1) { - break; - } - nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)); - if (nsname == null) { - break; - } - if (nsname.contains(".")) { - nsname = nsname.substring(nsname.lastIndexOf('.') + 1); - } - if (!nsname.isEmpty()) { - break; - } - } - } - Namespace ns = m.getNamespace(abc.constants); - - if (nsname.contains(":")) { - nsname = ""; - } - - if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { - } else { - if (ns != null) { - if (ns.kind == Namespace.KIND_NAMESPACE) { - nsname = ns.getName(abc.constants, true); - } - } - } - - if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { - ret += " " + nsname; - } - if (ns != null) { - ret += " " + ns.getPrefix(abc); - } - } - if (isStatic) { - if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { - //static is automatic - } else { - ret += " static"; - } - } - if ((kindFlags & ATTR_Final) > 0) { - if (!isStatic) { - ret += " final"; - } - } - return ret.trim(); - } - - @Override - public String toString() { - return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public String toString(ABC abc, List fullyQualifiedNames) { - return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); - } - - public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); - return writer; - } - - public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - } - - public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - writer.appendNoHilight("package"); - if (!nsname.isEmpty()) { - writer.appendNoHilight(" " + nsname); //assume not null name - } - writer.startBlock(); - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - writer.endBlock(); - writer.newLine(); - } - return writer; - } - - public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants, false); - convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - } - - public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - return writer; - } - - public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - - public Multiname getName(ABC abc) { - if (name_index == 0) { - return null; - } else { - return abc.constants.getMultiname(name_index); - } - } - - public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; - - public ClassPath getPath(ABC abc) { - Multiname name = getName(abc); - Namespace ns = name.getNamespace(abc.constants); - String packageName = ns.getName(abc.constants, false); - String objectName = name.getName(abc.constants, new ArrayList<>(), false); - return new ClassPath(packageName, objectName); //assume not null name - } -} +/* + * Copyright (C) 2010-2015 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.abc.types.traits; + +import com.jpexs.decompiler.flash.abc.ABC; +import com.jpexs.decompiler.flash.abc.ClassPath; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.flash.tags.ABCContainerTag; +import com.jpexs.helpers.Helper; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public abstract class Trait implements Serializable { + + private static final int[] EMPTY_METADATA_ARRAY = new int[0]; + + public int name_index; + + public int kindType; + + public int kindFlags; + + public int[] metadata = EMPTY_METADATA_ARRAY; + + public long fileOffset; + + public byte[] bytes; + + public static final int ATTR_Final = 0x1; + + public static final int ATTR_Override = 0x2; + + public static final int ATTR_Metadata = 0x4; + + public static final int TRAIT_SLOT = 0; + + public static final int TRAIT_METHOD = 1; + + public static final int TRAIT_GETTER = 2; + + public static final int TRAIT_SETTER = 3; + + public static final int TRAIT_CLASS = 4; + + public static final int TRAIT_FUNCTION = 5; + + public static final int TRAIT_CONST = 6; + + public abstract void delete(ABC abc, boolean d); + + public String getModifiers(ABC abc, boolean isStatic) { + String ret = ""; + if ((kindFlags & ATTR_Override) > 0) { + ret += "override"; + } + Multiname m = getName(abc); + if (m != null) { + String nsname = ""; + //if (abc.constants.getNamespace(m.namespace_index).kind == Namespace.KIND_NAMESPACE) { + { + for (ABCContainerTag abcTag : abc.getAbcTags()) { + if (m.namespace_index == -1) { + break; + } + nsname = abcTag.getABC().nsValueToName(abc.constants.getNamespace(m.namespace_index).getName(abc.constants, true)); + if (nsname == null) { + break; + } + if (nsname.contains(".")) { + nsname = nsname.substring(nsname.lastIndexOf('.') + 1); + } + if (!nsname.isEmpty()) { + break; + } + } + } + Namespace ns = m.getNamespace(abc.constants); + + if (nsname.contains(":")) { + nsname = ""; + } + + if ((!nsname.isEmpty()) && (!nsname.equals("-"))) { + } else { + if (ns != null) { + if (ns.kind == Namespace.KIND_NAMESPACE) { + nsname = ns.getName(abc.constants, true); + } + } + } + + if (nsname != null && (!nsname.contains(":")) && (!nsname.isEmpty())) { + ret += " " + nsname; + } + if (ns != null) { + ret += " " + ns.getPrefix(abc); + } + } + if (isStatic) { + if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { + //static is automatic + } else { + ret += " static"; + } + } + if ((kindFlags & ATTR_Final) > 0) { + if (!isStatic) { + ret += " final"; + } + } + return ret.trim(); + } + + @Override + public String toString() { + return "name_index=" + name_index + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public String toString(ABC abc, List fullyQualifiedNames) { + return abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata); + } + + public GraphTextWriter toString(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + writer.appendNoHilight(abc.constants.getMultiname(name_index).toString(abc.constants, fullyQualifiedNames) + " kind=" + kindType + " metadata=" + Helper.intArrToString(metadata)); + return writer; + } + + public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + } + + public GraphTextWriter toStringPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + writer.appendNoHilight("package"); + if (!nsname.isEmpty()) { + writer.appendNoHilight(" " + nsname); //assume not null name + } + writer.startBlock(); + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + writer.endBlock(); + writer.newLine(); + } + return writer; + } + + public void convertPackaged(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = ns.getName(abc.constants, false); + convert(parent, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + } + + public GraphTextWriter toStringHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + return writer; + } + + public void convertHeader(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + + public Multiname getName(ABC abc) { + if (name_index == 0) { + return null; + } else { + return abc.constants.getMultiname(name_index); + } + } + + public abstract int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException; + + public ClassPath getPath(ABC abc) { + Multiname name = getName(abc); + Namespace ns = name.getNamespace(abc.constants); + String packageName = ns.getName(abc.constants, false); + String objectName = name.getName(abc.constants, new ArrayList<>(), false); + return new ClassPath(packageName, objectName); //assume not null name + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 69d40bc0c..f1fd02df6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -1,216 +1,216 @@ -/* - * Copyright (C) 2010-2015 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.abc.types.traits; - -import com.jpexs.decompiler.flash.abc.ABC; -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.NulWriter; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class Traits implements Serializable { - - public List traits; - - public Traits() { - traits = new ArrayList<>(); - } - - public Traits(int initialCapacity) { - traits = new ArrayList<>(initialCapacity); - } - - public void delete(ABC abc, boolean d) { - for (Trait t : traits) { - t.delete(abc, d); - } - } - - public int addTrait(Trait t) { - traits.add(t); - return traits.size() - 1; - } - - public int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException { - int ret = 0; - for (Trait t : traits) { - ret += t.removeTraps(scriptIndex, classIndex, isStatic, abc, path); - } - return ret; - } - - @Override - public String toString() { - String s = ""; - for (int t = 0; t < traits.size(); t++) { - if (t > 0) { - s += "\r\n"; - } - s += traits.get(t).toString(); - } - return s; - } - - public String toString(ABC abc, List fullyQualifiedNames) { - String s = ""; - for (int t = 0; t < traits.size(); t++) { - if (t > 0) { - s += "\r\n"; - } - s += traits.get(t).toString(abc, fullyQualifiedNames); - } - return s; - } - - private class TraitConvertTask implements Callable { - - Trait trait; - - boolean makePackages; - - String path; - - ABC abc; - - boolean isStatic; - - ScriptExportMode exportMode; - - int scriptIndex; - - int classIndex; - - NulWriter writer; - - List fullyQualifiedNames; - - int traitIndex; - - boolean parallel; - - Trait parent; - - public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel) { - this.trait = trait; - this.parent = parent; - this.makePackages = makePackages; - this.path = path; - this.abc = abc; - this.isStatic = isStatic; - this.exportMode = exportMode; - this.scriptIndex = scriptIndex; - this.classIndex = classIndex; - this.writer = writer; - this.fullyQualifiedNames = fullyQualifiedNames; - this.traitIndex = traitIndex; - this.parallel = parallel; - } - - @Override - public Void call() throws InterruptedException { - if (makePackages) { - trait.convertPackaged(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } else { - trait.convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - return null; - } - } - - public GraphTextWriter toString(Class[] traitTypes, Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - for (int t = 0; t < traits.size(); t++) { - Trait trait = traits.get(t); - if (traitTypes != null) { - boolean found = false; - for (Class c : traitTypes) { - if (c.isInstance(trait)) { - found = true; - break; - } - } - if (!found) { - continue; - } - } - writer.newLine(); - int h = t; - if (classIndex != -1) { - if (!isStatic) { - h += abc.class_info.get(classIndex).static_traits.traits.size(); - } - } - if (trait instanceof TraitClass) { - writer.startClass(((TraitClass) trait).class_info); - } else { - writer.startTrait(h); - } - if (makePackages) { - trait.toStringPackaged(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } else { - trait.toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); - } - if (trait instanceof TraitClass) { - writer.endClass(); - } else { - writer.endTrait(); - } - } - return writer; - } - - public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { - if (!parallel || traits.size() < 2) { - for (int t = 0; t < traits.size(); t++) { - TraitConvertTask task = new TraitConvertTask(traits.get(t), parent, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel); - task.call(); - } - } else { - ExecutorService executor = Executors.newFixedThreadPool(Configuration.getParallelThreadCount()); - List> futureResults = null; - - futureResults = new ArrayList<>(); - for (int t = 0; t < traits.size(); t++) { - // each convert task needs a separate NulWriter, because they are executed parallel - TraitConvertTask task = new TraitConvertTask(traits.get(t), parent, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, new NulWriter(), fullyQualifiedNames, t, parallel); - Future future = executor.submit(task); - futureResults.add(future); - } - - for (int f = 0; f < futureResults.size(); f++) { - try { - futureResults.get(f).get(); - } catch (InterruptedException ex) { - executor.shutdownNow(); - throw ex; - } catch (ExecutionException ex) { - Logger.getLogger(Traits.class.getName()).log(Level.SEVERE, "Error during traits converting", ex); - } - } - executor.shutdown(); - } - } -} +/* + * Copyright (C) 2010-2015 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.abc.types.traits; + +import com.jpexs.decompiler.flash.abc.ABC; +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.NulWriter; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class Traits implements Serializable { + + public List traits; + + public Traits() { + traits = new ArrayList<>(); + } + + public Traits(int initialCapacity) { + traits = new ArrayList<>(initialCapacity); + } + + public void delete(ABC abc, boolean d) { + for (Trait t : traits) { + t.delete(abc, d); + } + } + + public int addTrait(Trait t) { + traits.add(t); + return traits.size() - 1; + } + + public int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) throws InterruptedException { + int ret = 0; + for (Trait t : traits) { + ret += t.removeTraps(scriptIndex, classIndex, isStatic, abc, path); + } + return ret; + } + + @Override + public String toString() { + String s = ""; + for (int t = 0; t < traits.size(); t++) { + if (t > 0) { + s += "\r\n"; + } + s += traits.get(t).toString(); + } + return s; + } + + public String toString(ABC abc, List fullyQualifiedNames) { + String s = ""; + for (int t = 0; t < traits.size(); t++) { + if (t > 0) { + s += "\r\n"; + } + s += traits.get(t).toString(abc, fullyQualifiedNames); + } + return s; + } + + private class TraitConvertTask implements Callable { + + Trait trait; + + boolean makePackages; + + String path; + + ABC abc; + + boolean isStatic; + + ScriptExportMode exportMode; + + int scriptIndex; + + int classIndex; + + NulWriter writer; + + List fullyQualifiedNames; + + int traitIndex; + + boolean parallel; + + Trait parent; + + public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel) { + this.trait = trait; + this.parent = parent; + this.makePackages = makePackages; + this.path = path; + this.abc = abc; + this.isStatic = isStatic; + this.exportMode = exportMode; + this.scriptIndex = scriptIndex; + this.classIndex = classIndex; + this.writer = writer; + this.fullyQualifiedNames = fullyQualifiedNames; + this.traitIndex = traitIndex; + this.parallel = parallel; + } + + @Override + public Void call() throws InterruptedException { + if (makePackages) { + trait.convertPackaged(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } else { + trait.convert(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + return null; + } + } + + public GraphTextWriter toString(Class[] traitTypes, Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + for (int t = 0; t < traits.size(); t++) { + Trait trait = traits.get(t); + if (traitTypes != null) { + boolean found = false; + for (Class c : traitTypes) { + if (c.isInstance(trait)) { + found = true; + break; + } + } + if (!found) { + continue; + } + } + writer.newLine(); + int h = t; + if (classIndex != -1) { + if (!isStatic) { + h += abc.class_info.get(classIndex).static_traits.traits.size(); + } + } + if (trait instanceof TraitClass) { + writer.startClass(((TraitClass) trait).class_info); + } else { + writer.startTrait(h); + } + if (makePackages) { + trait.toStringPackaged(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } else { + trait.toString(parent, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); + } + if (trait instanceof TraitClass) { + writer.endClass(); + } else { + writer.endTrait(); + } + } + return writer; + } + + public void convert(Trait parent, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) throws InterruptedException { + if (!parallel || traits.size() < 2) { + for (int t = 0; t < traits.size(); t++) { + TraitConvertTask task = new TraitConvertTask(traits.get(t), parent, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel); + task.call(); + } + } else { + ExecutorService executor = Executors.newFixedThreadPool(Configuration.getParallelThreadCount()); + List> futureResults = null; + + futureResults = new ArrayList<>(); + for (int t = 0; t < traits.size(); t++) { + // each convert task needs a separate NulWriter, because they are executed parallel + TraitConvertTask task = new TraitConvertTask(traits.get(t), parent, makePackages, path, abc, isStatic, exportMode, scriptIndex, classIndex, new NulWriter(), fullyQualifiedNames, t, parallel); + Future future = executor.submit(task); + futureResults.add(future); + } + + for (int f = 0; f < futureResults.size(); f++) { + try { + futureResults.get(f).get(); + } catch (InterruptedException ex) { + executor.shutdownNow(); + throw ex; + } catch (ExecutionException ex) { + Logger.getLogger(Traits.class.getName()).log(Level.SEVERE, "Error during traits converting", ex); + } + } + executor.shutdown(); + } + } +} 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 1e5ec49df..0161958ec 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 @@ -1,1363 +1,1363 @@ -/* - * Copyright (C) 2010-2015 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.AppResources; -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.action.model.ActionItem; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -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.GetPropertyActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; -import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; -import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; -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.UnsupportedActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; -import com.jpexs.decompiler.flash.action.parser.ActionParseException; -import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; -import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; -import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionStore; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.CodeFormatting; -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.helpers.collections.MyEntry; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.CommentItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.ScriptEndItem; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.EmptyStackException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Represents one ACTIONRECORD, also has some static method to work with Actions - */ -public abstract class Action implements GraphSourceItem { - - private static final int INFORM_LISTENER_RESOLUTION = 100; - - private boolean ignored = false; - - /** - * Action type identifier - */ - public int actionCode; - - /** - * Length of action data - */ - public int actionLength; - - private long address; - - /** - * Names of ActionScript properties - */ - public static final String[] propertyNames = new String[]{ - "_X", - "_Y", - "_xscale", - "_yscale", - "_currentframe", - "_totalframes", - "_alpha", - "_visible", - "_width", - "_height", - "_rotation", - "_target", - "_framesloaded", - "_name", - "_droptarget", - "_url", - "_highquality", - "_focusrect", - "_soundbuftime", - "_quality", - "_xmouse", - "_ymouse" - }; - - public static final List propertyNamesList = Arrays.asList(propertyNames); - - private static final Logger logger = Logger.getLogger(Action.class.getName()); - - /** - * Constructor - * - * @param actionCode Action type identifier - * @param actionLength Length of action data - */ - public Action(int actionCode, int actionLength) { - this.actionCode = actionCode; - this.actionLength = actionLength; - } - - public Action() { - } - - /** - * Returns address of this action - * - * @return address of this action - */ - public long getAddress() { - return address; - } - - /** - * Gets all addresses which are referenced from this action and/or - * subactions - * - * @param refs list of addresses - */ - public void getRef(Set refs) { - } - - /** - * Gets all addresses which are referenced from the list of actions - * - * @param list List of actions - * @return List of addresses - */ - public static Set getActionsAllRefs(List list) { - Set ret = new HashSet<>(); - for (Action a : list) { - a.getRef(ret); - } - return ret; - } - - public int getTotalActionLength() { - return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Sets address of this instruction - * - * @param address Address - */ - public void setAddress(long address) { - this.address = address; - } - - /** - * Returns a string representation of the object - * - * @return a string representation of the object. - */ - @Override - public String toString() { - return "Action" + actionCode; - } - - /** - * Reads String from FlasmLexer - * - * @param lex FlasmLexer - * @return String value - * @throws IOException - * @throws ActionParseException When read object is not String - */ - protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_STRING) { - throw new ActionParseException("String expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads Block startServer from FlasmLexer - * - * @param lex FlasmLexer - * @throws IOException - * @throws ActionParseException When read object is not Block startServer - */ - protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { - throw new ActionParseException("Block startServer ", lex.yyline()); - } - } - - /** - * Reads Identifier from FlasmLexer - * - * @param lex FlasmLexer - * @return Identifier name - * @throws IOException - * @throws ActionParseException When read object is not Identifier - */ - protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { - throw new ActionParseException("Identifier expected", lex.yyline()); - } - return (String) symb.value; - } - - /** - * Reads long value from FlasmLexer - * - * @param lex FlasmLexer - * @return long value - * @throws IOException - * @throws ActionParseException When read object is not long value - */ - protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { - throw new ActionParseException("Integer expected", lex.yyline()); - } - return (Long) symb.value; - } - - /** - * Reads boolean value from FlasmLexer - * - * @param lex FlasmLexer - * @return boolean value - * @throws IOException - * @throws ActionParseException When read object is not boolean value - */ - protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { - ASMParsedSymbol symb = lex.yylex(); - if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { - throw new ActionParseException("Boolean expected", lex.yyline()); - } - return (Boolean) symb.value; - } - - /** - * Gets action converted to bytes - * - * @param version SWF version - * @return Array of bytes - */ - public byte[] getBytes(int version) { - return surroundWithAction(new byte[0], version); - } - - /** - * Gets the length of action converted to bytes - * - * @param version SWF version - * @return Length - */ - public int getBytesLength(int version) { - return getBytes(version).length; - } - - /** - * Uptates the action length to the length calculated from action bytes - * - * @param version SWF version - */ - public void updateLength(int version) { - int length = getBytes(version).length; - actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); - } - - /** - * Surrounds byte array with Action header - * - * @param data Byte array - * @param version SWF version - * @return Byte array - */ - protected byte[] surroundWithAction(byte[] data, int version) { - ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); - SWFOutputStream sos2 = new SWFOutputStream(baos2, version); - try { - sos2.writeUI8(actionCode); - if (actionCode >= 0x80) { - sos2.writeUI16(data.length); - } - sos2.write(data); - sos2.close(); - } catch (IOException e) { - throw new Error("This should never happen.", e); - } - return baos2.toByteArray(); - } - - /** - * Converts list of Actions to bytes - * - * @param list List of actions - * @param addZero Whether or not to add 0 UI8 value to the end - * @param version SWF version - * @return Array of bytes - */ - public static byte[] actionsToBytes(List list, boolean addZero, int version) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Action lastAction = null; - for (Action a : list) { - try { - lastAction = a; - baos.write(a.getBytes(version)); - } catch (IOException e) { - } - } - if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { - baos.write(0); - } - return baos.toByteArray(); - } - - public static ByteArrayRange actionsToByteArrayRange(List list, boolean addZero, int version) { - byte[] bytes = Action.actionsToBytes(list, addZero, version); - return new ByteArrayRange(bytes); - } - - public static void setConstantPools(ASMSource src, List> constantPools) { - try { - ActionList actions = src.getActions(); - int poolIdx = 0; - for (Action action : actions) { - if (action instanceof ActionConstantPool) { - ActionConstantPool cPool = (ActionConstantPool) action; - List constantPool = constantPools.get(poolIdx); - cPool.constantPool = constantPool; - - poolIdx++; - if (constantPools.size() <= poolIdx) { - break; - } - } - } - - src.setActions(actions); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, null, ex); - } - } - - /** - * Set addresses of actions in the list - * - * @param list List of actions - * @param baseAddress Address of first action in the list - */ - public static void setActionsAddresses(List list, long baseAddress) { - long offset = baseAddress; - for (Action a : list) { - a.setAddress(offset); - offset += a.getTotalActionLength(); - } - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @return source ASM - * - */ - public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToString(listeners, address, list, version, exportMode, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ASM source - * - * @param listeners - * @param address - * @param list List of actions - * @param version SWF version - * @param exportMode PCode or hex? - * @param writer - * @return GraphTextWriter - */ - public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - if (exportMode == ScriptExportMode.CONSTANTS) { - return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); - } - - long offset; - Set importantOffsets = getActionsAllRefs(list); - /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); - if (!cps.isEmpty()) { - setConstantPool(list, cps.get(cps.size() - 1)); - }*/ - HashMap> containers = new HashMap<>(); - HashMap containersPos = new HashMap<>(); - offset = address; - int pos = 0; - boolean lastPush = false; - for (Action a : list) { - if (pos % INFORM_LISTENER_RESOLUTION == 0) { - for (DisassemblyListener listener : listeners) { - listener.progressToString(pos + 1, list.size()); - } - } - - if (exportMode == ScriptExportMode.PCODE_HEX) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("; "); - writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); - writer.newLine(); - } - - offset = a.getAddress(); - - if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - containersPos.put(cnt, 0); - List sizes = cnt.getContainerSizes(); - long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); - for (Long size : sizes) { - addr += size; - if (size == 0) { - continue; - } - if (!containers.containsKey(addr)) { - containers.put(addr, new ArrayList()); - } - containers.get(addr).add(cnt); - } - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("}").newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - } - - if (a.isIgnored()) { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - if (!(a instanceof ActionEnd)) { - int len = a.getTotalActionLength(); - for (int i = 0; i < len; i++) { - writer.appendNoHilight("Nop").newLine(); - } - } - } else { - //if (!(a instanceof ActionNop)) { - String add = ""; - // honfika: commented out the following lines, because it makes no sense - /*if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - add = "; ofs" + Helper.formatAddress(offset) + add; - add = "";*/ - if ((a instanceof ActionPush) && lastPush) { - writer.appendNoHilight(" "); - ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); - } else { - if (lastPush) { - writer.newLine(); - lastPush = false; - } - - writer.append("", offset); - - int fixBranch = -1; - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - if (aif.jumpUsed && !aif.ignoreUsed) { - fixBranch = 0; - } - if (!aif.jumpUsed && aif.ignoreUsed) { - fixBranch = 1; - } - } - - if (fixBranch > -1) { - writer.appendNoHilight("FFDec_DeobfuscatePop"); - if (fixBranch == 0) { //jump - writer.newLine(); - writer.appendNoHilight("Jump loc"); - writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); - } else { - //nojump, ignore - } - } else { - a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); - } - writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); - writer.appendNoHilight(add); - if (!(a instanceof ActionPush)) { - writer.newLine(); - } - } - if (a instanceof ActionPush) { - lastPush = true; - } else { - lastPush = false; - } - //} - } - - offset += a.getTotalActionLength(); - pos++; - } - if (lastPush) { - writer.newLine(); - } - - if (containers.containsKey(offset)) { - for (int i = 0; i < containers.get(offset).size(); i++) { - writer.appendNoHilight("}"); - writer.newLine(); - GraphSourceItemContainer cnt = containers.get(offset).get(i); - int cntPos = containersPos.get(cnt); - writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); - cntPos++; - containersPos.put(cnt, cntPos); - } - } - - if (importantOffsets.contains(offset)) { - writer.appendNoHilight("loc"); - writer.appendNoHilight(Helper.formatAddress(offset)); - writer.appendNoHilight(":"); - writer.newLine(); - } - - return writer; - } - - public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { - int poolIdx = 0; - writer.appendNoHilight(Helper.constants).newLine(); - for (Action a : list) { - if (a instanceof ActionConstantPool) { - if (poolIdx > 0) { - writer.appendNoHilight("---").newLine(); - } - - ActionConstantPool cPool = (ActionConstantPool) a; - int constIdx = 0; - for (String c : cPool.constantPool) { - writer.appendNoHilight(constIdx); - writer.appendNoHilight("|"); - writer.appendNoHilight(Helper.escapeString(c)); - writer.newLine(); - constIdx++; - } - - poolIdx++; - } - } - - return writer; - } - - /** - * Convert action to ASM source - * - * @param container - * @param knownAddreses List of important offsets to mark as labels - * @param exportMode PCode or hex? - * @return String of P-code source - */ - public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { - return toString(); - } - - /** - * Translates this function to stack and output. - * - * @param stack Stack - * @param output Output - * @param regNames Register names - * @param variables Variables - * @param functions Functions - * @param staticOperation the value of staticOperation - * @param path the value of path - * @throws java.lang.InterruptedException - */ - public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { - } - - /** - * Pops long value off the stack - * - * @param stack Stack - * @return long value - */ - protected long popLong(TranslateStack stack) { - GraphTargetItem item = stack.pop(); - if (item instanceof DirectValueActionItem) { - if (((DirectValueActionItem) item).value instanceof Long) { - return (long) (Long) ((DirectValueActionItem) item).value; - } - } - return 0; - } - - /** - * Converts action index to address in the specified list of actions - * - * @param actions List of actions - * @param ip Action index - * @return address - */ - public static long ip2adr(List actions, int ip) { - /* List actions=new ArrayList(); - for(GraphSourceItem s:sources){ - if(s instanceof Action){ - actions.add((Action)s); - } - }*/ - if (ip >= actions.size()) { - if (actions.isEmpty()) { - return 0; - } - return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - } - if (ip == -1) { - return 0; - } - return actions.get(ip).getAddress(); - } - - /** - * Converts address to action index in the specified list of actions - * - * @param actions List of actions - * @param addr Address - * @return action index - */ - public static int adr2ip(List actions, long addr) { - for (int ip = 0; ip < actions.size(); ip++) { - if (actions.get(ip).getAddress() == addr) { - return ip; - } - } - if (actions.size() > 0) { - long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); - if (addr == outpos) { - return actions.size(); - } - } - return -1; - } - - public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { - return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @return source - * @throws java.lang.InterruptedException - */ - public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { - HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - actionsToSource(asm, actions, path, writer); - return writer.toString(); - } - - /** - * Converts list of actions to ActionScript source code - * - * @param asm - * @param actions List of actions - * @param path - * @param writer - * @throws java.lang.InterruptedException - */ - public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { - writer.suspendMeasure(); - List tree = null; - Throwable convertException = null; - int timeout = Configuration.decompilationTimeoutSingleMethod.get(); - final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; - try { - tree = CancellableWorker.call(new Callable>() { - @Override - public List call() throws Exception { - int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; - List tree = actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); - Graph.graphToString(tree, new NulWriter(), new LocalData()); - return tree; - } - }, timeout, TimeUnit.SECONDS); - } catch (InterruptedException ex) { - throw ex; - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { - if (ex instanceof TimeoutException) { - logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); - } else { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); - } - convertException = ex; - Throwable cause = ex.getCause(); - if (ex instanceof ExecutionException && cause instanceof Exception) { - convertException = cause; - } - } - writer.continueMeasure(); - - if (asm != null) { - asm.getActionSourcePrefix(writer); - } - if (convertException == null) { - Graph.graphToString(tree, writer, new LocalData()); - } else if (convertException instanceof TimeoutException) { - Helper.appendTimeoutComment(writer, timeout); - } else { - Helper.appendErrorComment(writer, convertException); - } - if (asm != null) { - asm.getActionSourceSuffix(writer); - } - } - - /** - * Converts list of actions to List of treeItems - * - * @param regNames Register names - * @param variables - * @param functions - * @param actions List of actions - * @param version SWF version - * @param staticOperation - * @param path - * @return List of treeItems - * @throws java.lang.InterruptedException - */ - public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { - return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); - } - - @Override - public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { - ActionLocalData aLocalData = (ActionLocalData) localData; - translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); - } - - @Override - public boolean isJump() { - return false; - } - - @Override - public boolean isBranch() { - return false; - } - - @Override - public boolean isExit() { - return false; - } - - @Override - public long getOffset() { - return getAddress(); - } - - @Override - public List getBranches(GraphSource code) { - return new ArrayList<>(); - } - - @Override - public boolean isIgnored() { - return ignored; - } - - @Override - public void setIgnored(boolean ignored, int pos) { - this.ignored = ignored; - } - - private static class Loop { - - public long loopContinue; - - public long loopBreak; - - public int continueCount = 0; - - public int breakCount = 0; - - public Loop(long loopContinue, long loopBreak) { - this.loopContinue = loopContinue; - this.loopBreak = loopBreak; - } - - @Override - public String toString() { - return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; - } - } - - private static void log(String s) { - logger.fine(s); - } - - public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { - if (start < actions.size() && (end > 0) && (start > 0)) { - log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); - } - ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); - List output = new ArrayList<>(); - int ip = start; - boolean isWhile = false; - boolean isForIn = false; - GraphTargetItem inItem = null; - int loopStart = 0; - loopip: - while (ip <= end) { - - long addr = ip2adr(actions, ip); - if (ip > end) { - break; - } - if (ip >= actions.size()) { - output.add(new ScriptEndItem()); - break; - } - Action action = actions.get(ip); - if (action.isIgnored()) { - ip++; - continue; - } - if (action instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; - //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); - long endAddr = action.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> outs = new ArrayList<>(); - HashMap variables2 = Helper.deepCopy(variables); - if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { - for (int r = 0; r < 256; r++) { - if (variables2.containsKey("__register" + r)) { - variables2.remove("__register" + r); - } - } - } - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - outs.add(new ArrayList()); - continue; - } - List out; - try { - out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); - } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); - if (ex2 instanceof OutOfMemoryError) { - Helper.freeMem(); - } - out = new ArrayList<>(); - out.add(new CommentItem(new String[]{ - "", - " * " + AppResources.translate("decompilationError"), - " * " + AppResources.translate("decompilationError.obfuscated"), - Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, - " * " + AppResources.translate("decompilationError.errorType") + ": " - + ex2.getClass().getSimpleName(), - ""})); - } - outs.add(out); - endAddr += size; - } - ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); - ip = adr2ip(actions, endAddr); - continue; - } - - //return in for..in - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 <= end) { - if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { - if (actions.get(ip + 2) instanceof ActionNot) { - if (actions.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) actions.get(ip + 3); - if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - continue; - } - } - } - } - } - } - - /*ActionJump && ActionIf removed*/ - /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { - loopStart = ip + 1; - isForIn = true; - ip += 4; - action.translate(localData, stack, output); - EnumerateActionItem en = (EnumerateActionItem) stack.peek(); - inItem = en.object; - continue; - } else*/ /*if (action instanceof ActionTry) { - ActionTry atry = (ActionTry) action; - List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); - ActionItem catchName; - if (atry.catchInRegisterFlag) { - catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>()); - } else { - catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>()); - } - List catchExceptions = new ArrayList(); - catchExceptions.add(catchName); - List> catchCommands = new ArrayList>(); - catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); - List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); - output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); - } else if (action instanceof ActionWith) { - ActionWith awith = (ActionWith) action; - List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions - output.add(new WithActionItem(action, stack.pop(), withCommands)); - } else */ if (false) { - } /*if (action instanceof ActionStoreRegister) { - if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { - action.translate(localData, stack, output); - stack.pop(); - ip++; - } else { - try { - action.translate(localData, stack, output); - } catch (Exception ex) { - // ignore - } - } - } */ /*else if (action instanceof ActionStrictEquals) { - if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { - List caseValues = new ArrayList(); - List> caseCommands = new ArrayList>(); - caseValues.add(stack.pop()); - ActionItem switchedObject = stack.pop(); - if (output.size() > 0) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - output.remove(output.size() - 1); - } - } - int caseStart = ip + 2; - List caseBodyIps = new ArrayList(); - long defaultAddr = 0; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); - ip++; - do { - ip++; - if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { - caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); - caseStart = ip + 1; - caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); - if (actions.get(ip + 1) instanceof ActionJump) { - defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); - ip = adr2ip(actions, defaultAddr, version); - break; - } - } - } while (ip < end); - - for (int i = 0; i < caseBodyIps.size(); i++) { - int caseEnd = ip - 1; - if (i < caseBodyIps.size() - 1) { - caseEnd = caseBodyIps.get(i + 1) - 1; - } - caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); - } - output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); - continue; - } else { - action.translate(stack, constants, output, registerNames); - } - } */ else { - - if (action instanceof ActionStore) { - ActionStore store = (ActionStore) action; - store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); - ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; - } - - try { - action.translate(localData, stack, output, staticOperation, path); - } catch (EmptyStackException ese) { - logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); - output.add(new UnsupportedActionItem(action, "Empty stack")); - } - - } - - ip++; - } - //output = checkClass(output); - log("Leaving " + start + "-" + end); - return output; - } - - 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, ((GetMemberActionItem) t).memberName); - if (lastMember == null) { - return gvt; - } else { - lastMember.object = gvt; - } - } - } - } - } - return ti; - } - - public static List checkClass(List output) { - if (true) { - //return output; - } - List ret = new ArrayList<>(); - List functions = new ArrayList<>(); - List staticFunctions = new ArrayList<>(); - List> vars = new ArrayList<>(); - List> staticVars = 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 (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { - 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 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++; - } - if (parts.get(ipos) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); - int 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; - int 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 = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; - functions.add((FunctionActionItem) sr.value); - - for (; ipos < parts.size(); ipos++) { - if (parts.get(ipos) instanceof ImplementsOpActionItem) { - ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); - implementsOp = io.superclasses; - continue; - } - if (parts.get(ipos) instanceof SetMemberActionItem) { - sm = (SetMemberActionItem) parts.get(ipos); - 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) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - functions.add((FunctionActionItem) sm.value); - } else { - vars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } else if (rnum == classReg) { - if (sm.value instanceof FunctionActionItem) { - ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; - staticFunctions.add((FunctionActionItem) sm.value); - } else { - staticVars.add(new MyEntry<>(sm.objectName, sm.value)); - } - } - - } - } - - } - - } - } - List output2 = new ArrayList<>(); - for (int i = 0; i < prevCount; i++) { - output2.add(output.get(i)); - } - output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); - return output2; - } - } - } 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; - } - } - } - } - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - ok = false; - } - } else { - prevCount++; - //ok = false; - } - if (!ok) { - break; - } - } - return output; - } - - @Override - public boolean ignoredLoops() { - return false; - } - - public static void setConstantPool(List actions, ConstantPool cpool) { - for (GraphSourceItem a : actions) { - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - if (a instanceof ActionDefineFunction) { - if (cpool != null) { - //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); - } - } - if (a instanceof ActionDefineFunction2) { - if (cpool != null) { - //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); - } - } - } - } - - public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { - writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); - return writer; - } - - public static double toFloatPoint(Object o) { - if (o instanceof Double) { - return (Double) o; - } - if (o instanceof Integer) { - return (Integer) o; - } - if (o instanceof Long) { - return (Long) o; - } - if (o instanceof String) { - try { - return Double.parseDouble((String) o); - } catch (NumberFormatException nfe) { - return 0; - } - } - return 0; - } - - public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { - GraphTargetItem ret = get; - boolean boxed = false; - if (get instanceof VariableActionItem) { - boxed = true; - ret = ((VariableActionItem) ret).getBoxedValue(); - } - if (ret instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) ret; - ret = new SetVariableActionItem(null, gv.name, value); - } else if (ret instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) ret; - ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); - } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { - ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); - } else if (ret instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) ret; - ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); - } - if (boxed) { - GraphTargetItem b = ret; - ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); - ((VariableActionItem) ret).setBoxedValue((ActionItem) b); - variables.remove((VariableActionItem) get); - variables.add((VariableActionItem) ret); - } - return ret; - } - - @Override - public boolean isDeobfuscatePop() { - return false; - } - - @Override - public int getLine() { - return 0; - } - - @Override - public String getFile() { - return null; - } -} +/* + * Copyright (C) 2010-2015 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.AppResources; +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.action.model.ActionItem; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +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.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem; +import com.jpexs.decompiler.flash.action.model.NewObjectActionItem; +import com.jpexs.decompiler.flash.action.model.SetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem; +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.UnsupportedActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem; +import com.jpexs.decompiler.flash.action.parser.ActionParseException; +import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol; +import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.CodeFormatting; +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.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.CommentItem; +import com.jpexs.decompiler.graph.model.IfItem; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.decompiler.graph.model.NotItem; +import com.jpexs.decompiler.graph.model.ScriptEndItem; +import com.jpexs.helpers.ByteArrayRange; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents one ACTIONRECORD, also has some static method to work with Actions + */ +public abstract class Action implements GraphSourceItem { + + private static final int INFORM_LISTENER_RESOLUTION = 100; + + private boolean ignored = false; + + /** + * Action type identifier + */ + public int actionCode; + + /** + * Length of action data + */ + public int actionLength; + + private long address; + + /** + * Names of ActionScript properties + */ + public static final String[] propertyNames = new String[]{ + "_X", + "_Y", + "_xscale", + "_yscale", + "_currentframe", + "_totalframes", + "_alpha", + "_visible", + "_width", + "_height", + "_rotation", + "_target", + "_framesloaded", + "_name", + "_droptarget", + "_url", + "_highquality", + "_focusrect", + "_soundbuftime", + "_quality", + "_xmouse", + "_ymouse" + }; + + public static final List propertyNamesList = Arrays.asList(propertyNames); + + private static final Logger logger = Logger.getLogger(Action.class.getName()); + + /** + * Constructor + * + * @param actionCode Action type identifier + * @param actionLength Length of action data + */ + public Action(int actionCode, int actionLength) { + this.actionCode = actionCode; + this.actionLength = actionLength; + } + + public Action() { + } + + /** + * Returns address of this action + * + * @return address of this action + */ + public long getAddress() { + return address; + } + + /** + * Gets all addresses which are referenced from this action and/or + * subactions + * + * @param refs list of addresses + */ + public void getRef(Set refs) { + } + + /** + * Gets all addresses which are referenced from the list of actions + * + * @param list List of actions + * @return List of addresses + */ + public static Set getActionsAllRefs(List list) { + Set ret = new HashSet<>(); + for (Action a : list) { + a.getRef(ret); + } + return ret; + } + + public int getTotalActionLength() { + return actionLength + 1 + ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Sets address of this instruction + * + * @param address Address + */ + public void setAddress(long address) { + this.address = address; + } + + /** + * Returns a string representation of the object + * + * @return a string representation of the object. + */ + @Override + public String toString() { + return "Action" + actionCode; + } + + /** + * Reads String from FlasmLexer + * + * @param lex FlasmLexer + * @return String value + * @throws IOException + * @throws ActionParseException When read object is not String + */ + protected String lexString(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_STRING) { + throw new ActionParseException("String expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads Block startServer from FlasmLexer + * + * @param lex FlasmLexer + * @throws IOException + * @throws ActionParseException When read object is not Block startServer + */ + protected void lexBlockOpen(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BLOCK_START) { + throw new ActionParseException("Block startServer ", lex.yyline()); + } + } + + /** + * Reads Identifier from FlasmLexer + * + * @param lex FlasmLexer + * @return Identifier name + * @throws IOException + * @throws ActionParseException When read object is not Identifier + */ + protected String lexIdentifier(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_IDENTIFIER) { + throw new ActionParseException("Identifier expected", lex.yyline()); + } + return (String) symb.value; + } + + /** + * Reads long value from FlasmLexer + * + * @param lex FlasmLexer + * @return long value + * @throws IOException + * @throws ActionParseException When read object is not long value + */ + protected long lexLong(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_INTEGER) { + throw new ActionParseException("Integer expected", lex.yyline()); + } + return (Long) symb.value; + } + + /** + * Reads boolean value from FlasmLexer + * + * @param lex FlasmLexer + * @return boolean value + * @throws IOException + * @throws ActionParseException When read object is not boolean value + */ + protected boolean lexBoolean(FlasmLexer lex) throws IOException, ActionParseException { + ASMParsedSymbol symb = lex.yylex(); + if (symb.type != ASMParsedSymbol.TYPE_BOOLEAN) { + throw new ActionParseException("Boolean expected", lex.yyline()); + } + return (Boolean) symb.value; + } + + /** + * Gets action converted to bytes + * + * @param version SWF version + * @return Array of bytes + */ + public byte[] getBytes(int version) { + return surroundWithAction(new byte[0], version); + } + + /** + * Gets the length of action converted to bytes + * + * @param version SWF version + * @return Length + */ + public int getBytesLength(int version) { + return getBytes(version).length; + } + + /** + * Uptates the action length to the length calculated from action bytes + * + * @param version SWF version + */ + public void updateLength(int version) { + int length = getBytes(version).length; + actionLength = length - 1 - ((actionCode >= 0x80) ? 2 : 0); + } + + /** + * Surrounds byte array with Action header + * + * @param data Byte array + * @param version SWF version + * @return Byte array + */ + protected byte[] surroundWithAction(byte[] data, int version) { + ByteArrayOutputStream baos2 = new ByteArrayOutputStream(); + SWFOutputStream sos2 = new SWFOutputStream(baos2, version); + try { + sos2.writeUI8(actionCode); + if (actionCode >= 0x80) { + sos2.writeUI16(data.length); + } + sos2.write(data); + sos2.close(); + } catch (IOException e) { + throw new Error("This should never happen.", e); + } + return baos2.toByteArray(); + } + + /** + * Converts list of Actions to bytes + * + * @param list List of actions + * @param addZero Whether or not to add 0 UI8 value to the end + * @param version SWF version + * @return Array of bytes + */ + public static byte[] actionsToBytes(List list, boolean addZero, int version) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Action lastAction = null; + for (Action a : list) { + try { + lastAction = a; + baos.write(a.getBytes(version)); + } catch (IOException e) { + } + } + if (addZero && (lastAction == null || !(lastAction instanceof ActionEnd))) { + baos.write(0); + } + return baos.toByteArray(); + } + + public static ByteArrayRange actionsToByteArrayRange(List list, boolean addZero, int version) { + byte[] bytes = Action.actionsToBytes(list, addZero, version); + return new ByteArrayRange(bytes); + } + + public static void setConstantPools(ASMSource src, List> constantPools) { + try { + ActionList actions = src.getActions(); + int poolIdx = 0; + for (Action action : actions) { + if (action instanceof ActionConstantPool) { + ActionConstantPool cPool = (ActionConstantPool) action; + List constantPool = constantPools.get(poolIdx); + cPool.constantPool = constantPool; + + poolIdx++; + if (constantPools.size() <= poolIdx) { + break; + } + } + } + + src.setActions(actions); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + /** + * Set addresses of actions in the list + * + * @param list List of actions + * @param baseAddress Address of first action in the list + */ + public static void setActionsAddresses(List list, long baseAddress) { + long offset = baseAddress; + for (Action a : list) { + a.setAddress(offset); + offset += a.getTotalActionLength(); + } + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @return source ASM + * + */ + public static String actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode) { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToString(listeners, address, list, version, exportMode, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ASM source + * + * @param listeners + * @param address + * @param list List of actions + * @param version SWF version + * @param exportMode PCode or hex? + * @param writer + * @return GraphTextWriter + */ + public static GraphTextWriter actionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + if (exportMode == ScriptExportMode.CONSTANTS) { + return constantPoolActionsToString(listeners, address, list, version, exportMode, writer); + } + + long offset; + Set importantOffsets = getActionsAllRefs(list); + /*List cps = SWFInputStream.getConstantPool(new ArrayList(), new ActionGraphSource(list, version, new HashMap(), new HashMap(), new HashMap()), 0, version, path); + if (!cps.isEmpty()) { + setConstantPool(list, cps.get(cps.size() - 1)); + }*/ + HashMap> containers = new HashMap<>(); + HashMap containersPos = new HashMap<>(); + offset = address; + int pos = 0; + boolean lastPush = false; + for (Action a : list) { + if (pos % INFORM_LISTENER_RESOLUTION == 0) { + for (DisassemblyListener listener : listeners) { + listener.progressToString(pos + 1, list.size()); + } + } + + if (exportMode == ScriptExportMode.PCODE_HEX) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("; "); + writer.appendNoHilight(Helper.bytesToHexString(a.getBytes(version))); + writer.newLine(); + } + + offset = a.getAddress(); + + if ((!(a.isIgnored())) && (a instanceof GraphSourceItemContainer)) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + containersPos.put(cnt, 0); + List sizes = cnt.getContainerSizes(); + long addr = ((Action) cnt).getAddress() + cnt.getHeaderSize(); + for (Long size : sizes) { + addr += size; + if (size == 0) { + continue; + } + if (!containers.containsKey(addr)) { + containers.put(addr, new ArrayList()); + } + containers.get(addr).add(cnt); + } + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("}").newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (Configuration.showAllAddresses.get() || importantOffsets.contains(offset)) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + } + + if (a.isIgnored()) { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + if (!(a instanceof ActionEnd)) { + int len = a.getTotalActionLength(); + for (int i = 0; i < len; i++) { + writer.appendNoHilight("Nop").newLine(); + } + } + } else { + //if (!(a instanceof ActionNop)) { + String add = ""; + // honfika: commented out the following lines, because it makes no sense + /*if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + add = "; ofs" + Helper.formatAddress(offset) + add; + add = "";*/ + if ((a instanceof ActionPush) && lastPush) { + writer.appendNoHilight(" "); + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, exportMode, writer); + } else { + if (lastPush) { + writer.newLine(); + lastPush = false; + } + + writer.append("", offset); + + int fixBranch = -1; + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + if (aif.jumpUsed && !aif.ignoreUsed) { + fixBranch = 0; + } + if (!aif.jumpUsed && aif.ignoreUsed) { + fixBranch = 1; + } + } + + if (fixBranch > -1) { + writer.appendNoHilight("FFDec_DeobfuscatePop"); + if (fixBranch == 0) { //jump + writer.newLine(); + writer.appendNoHilight("Jump loc"); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getTotalActionLength() + ((ActionIf) a).getJumpOffset())); + } else { + //nojump, ignore + } + } else { + a.getASMSourceReplaced(list, importantOffsets, exportMode, writer); + } + writer.appendNoHilight(a.isIgnored() ? "; ignored" : ""); + writer.appendNoHilight(add); + if (!(a instanceof ActionPush)) { + writer.newLine(); + } + } + if (a instanceof ActionPush) { + lastPush = true; + } else { + lastPush = false; + } + //} + } + + offset += a.getTotalActionLength(); + pos++; + } + if (lastPush) { + writer.newLine(); + } + + if (containers.containsKey(offset)) { + for (int i = 0; i < containers.get(offset).size(); i++) { + writer.appendNoHilight("}"); + writer.newLine(); + GraphSourceItemContainer cnt = containers.get(offset).get(i); + int cntPos = containersPos.get(cnt); + writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); + cntPos++; + containersPos.put(cnt, cntPos); + } + } + + if (importantOffsets.contains(offset)) { + writer.appendNoHilight("loc"); + writer.appendNoHilight(Helper.formatAddress(offset)); + writer.appendNoHilight(":"); + writer.newLine(); + } + + return writer; + } + + public static GraphTextWriter constantPoolActionsToString(List listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) { + int poolIdx = 0; + writer.appendNoHilight(Helper.constants).newLine(); + for (Action a : list) { + if (a instanceof ActionConstantPool) { + if (poolIdx > 0) { + writer.appendNoHilight("---").newLine(); + } + + ActionConstantPool cPool = (ActionConstantPool) a; + int constIdx = 0; + for (String c : cPool.constantPool) { + writer.appendNoHilight(constIdx); + writer.appendNoHilight("|"); + writer.appendNoHilight(Helper.escapeString(c)); + writer.newLine(); + constIdx++; + } + + poolIdx++; + } + } + + return writer; + } + + /** + * Convert action to ASM source + * + * @param container + * @param knownAddreses List of important offsets to mark as labels + * @param exportMode PCode or hex? + * @return String of P-code source + */ + public String getASMSource(ActionList container, Set knownAddreses, ScriptExportMode exportMode) { + return toString(); + } + + /** + * Translates this function to stack and output. + * + * @param stack Stack + * @param output Output + * @param regNames Register names + * @param variables Variables + * @param functions Functions + * @param staticOperation the value of staticOperation + * @param path the value of path + * @throws java.lang.InterruptedException + */ + public void translate(TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions, int staticOperation, String path) throws InterruptedException { + } + + /** + * Pops long value off the stack + * + * @param stack Stack + * @return long value + */ + protected long popLong(TranslateStack stack) { + GraphTargetItem item = stack.pop(); + if (item instanceof DirectValueActionItem) { + if (((DirectValueActionItem) item).value instanceof Long) { + return (long) (Long) ((DirectValueActionItem) item).value; + } + } + return 0; + } + + /** + * Converts action index to address in the specified list of actions + * + * @param actions List of actions + * @param ip Action index + * @return address + */ + public static long ip2adr(List actions, int ip) { + /* List actions=new ArrayList(); + for(GraphSourceItem s:sources){ + if(s instanceof Action){ + actions.add((Action)s); + } + }*/ + if (ip >= actions.size()) { + if (actions.isEmpty()) { + return 0; + } + return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + } + if (ip == -1) { + return 0; + } + return actions.get(ip).getAddress(); + } + + /** + * Converts address to action index in the specified list of actions + * + * @param actions List of actions + * @param addr Address + * @return action index + */ + public static int adr2ip(List actions, long addr) { + for (int ip = 0; ip < actions.size(); ip++) { + if (actions.get(ip).getAddress() == addr) { + return ip; + } + } + if (actions.size() > 0) { + long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getTotalActionLength(); + if (addr == outpos) { + return actions.size(); + } + } + return -1; + } + + public static List actionsToTree(List actions, int version, int staticOperation, String path) throws InterruptedException { + return actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @return source + * @throws java.lang.InterruptedException + */ + public static String actionsToSource(final ASMSource asm, final List actions, final String path) throws InterruptedException { + HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); + actionsToSource(asm, actions, path, writer); + return writer.toString(); + } + + /** + * Converts list of actions to ActionScript source code + * + * @param asm + * @param actions List of actions + * @param path + * @param writer + * @throws java.lang.InterruptedException + */ + public static void actionsToSource(final ASMSource asm, final List actions, final String path, GraphTextWriter writer) throws InterruptedException { + writer.suspendMeasure(); + List tree = null; + Throwable convertException = null; + int timeout = Configuration.decompilationTimeoutSingleMethod.get(); + final int version = asm == null ? SWF.DEFAULT_VERSION : asm.getSwf().version; + try { + tree = CancellableWorker.call(new Callable>() { + @Override + public List call() throws Exception { + int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC; + List tree = actionsToTree(new HashMap(), new HashMap(), new HashMap(), actions, version, staticOperation, path); + Graph.graphToString(tree, new NulWriter(), new LocalData()); + return tree; + } + }, timeout, TimeUnit.SECONDS); + } catch (InterruptedException ex) { + throw ex; + } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + if (ex instanceof TimeoutException) { + logger.log(Level.SEVERE, "Decompilation timeout in: " + path, ex); + } else { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex); + } + convertException = ex; + Throwable cause = ex.getCause(); + if (ex instanceof ExecutionException && cause instanceof Exception) { + convertException = cause; + } + } + writer.continueMeasure(); + + if (asm != null) { + asm.getActionSourcePrefix(writer); + } + if (convertException == null) { + Graph.graphToString(tree, writer, new LocalData()); + } else if (convertException instanceof TimeoutException) { + Helper.appendTimeoutComment(writer, timeout); + } else { + Helper.appendErrorComment(writer, convertException); + } + if (asm != null) { + asm.getActionSourceSuffix(writer); + } + } + + /** + * Converts list of actions to List of treeItems + * + * @param regNames Register names + * @param variables + * @param functions + * @param actions List of actions + * @param version SWF version + * @param staticOperation + * @param path + * @return List of treeItems + * @throws java.lang.InterruptedException + */ + public static List actionsToTree(HashMap regNames, HashMap variables, HashMap functions, List actions, int version, int staticOperation, String path) throws InterruptedException { + return ActionGraph.translateViaGraph(regNames, variables, functions, actions, version, staticOperation, path); + } + + @Override + public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException { + ActionLocalData aLocalData = (ActionLocalData) localData; + translate(stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path); + } + + @Override + public boolean isJump() { + return false; + } + + @Override + public boolean isBranch() { + return false; + } + + @Override + public boolean isExit() { + return false; + } + + @Override + public long getOffset() { + return getAddress(); + } + + @Override + public List getBranches(GraphSource code) { + return new ArrayList<>(); + } + + @Override + public boolean isIgnored() { + return ignored; + } + + @Override + public void setIgnored(boolean ignored, int pos) { + this.ignored = ignored; + } + + private static class Loop { + + public long loopContinue; + + public long loopBreak; + + public int continueCount = 0; + + public int breakCount = 0; + + public Loop(long loopContinue, long loopBreak) { + this.loopContinue = loopContinue; + this.loopBreak = loopBreak; + } + + @Override + public String toString() { + return "[Loop continue:" + loopContinue + ", break:" + loopBreak + "]"; + } + } + + private static void log(String s) { + logger.fine(s); + } + + public static List actionsPartToTree(HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path) throws InterruptedException { + if (start < actions.size() && (end > 0) && (start > 0)) { + log("Entering " + start + "-" + end + (actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : "")); + } + ActionLocalData localData = new ActionLocalData(registerNames, variables, functions); + List output = new ArrayList<>(); + int ip = start; + boolean isWhile = false; + boolean isForIn = false; + GraphTargetItem inItem = null; + int loopStart = 0; + loopip: + while (ip <= end) { + + long addr = ip2adr(actions, ip); + if (ip > end) { + break; + } + if (ip >= actions.size()) { + output.add(new ScriptEndItem()); + break; + } + Action action = actions.get(ip); + if (action.isIgnored()) { + ip++; + continue; + } + if (action instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) action; + //List out=actionsPartToTree(new HashMap(), new HashMap(),new HashMap(), new TranslateStack(), src, ip+1,endip-1 , version); + long endAddr = action.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> outs = new ArrayList<>(); + HashMap variables2 = Helper.deepCopy(variables); + if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) { + for (int r = 0; r < 256; r++) { + if (variables2.containsKey("__register" + r)) { + variables2.remove("__register" + r); + } + } + } + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + outs.add(new ArrayList()); + continue; + } + List out; + try { + out = ActionGraph.translateViaGraph(cnt.getRegNames(), variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName)); + } catch (OutOfMemoryError | TranslateException | StackOverflowError ex2) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ex2); + if (ex2 instanceof OutOfMemoryError) { + Helper.freeMem(); + } + out = new ArrayList<>(); + out.add(new CommentItem(new String[]{ + "", + " * " + AppResources.translate("decompilationError"), + " * " + AppResources.translate("decompilationError.obfuscated"), + Helper.decompilationErrorAdd == null ? null : " * " + Helper.decompilationErrorAdd, + " * " + AppResources.translate("decompilationError.errorType") + ": " + + ex2.getClass().getSimpleName(), + ""})); + } + outs.add(out); + endAddr += size; + } + ((GraphSourceItemContainer) action).translateContainer(outs, stack, output, registerNames, variables, functions); + ip = adr2ip(actions, endAddr); + continue; + } + + //return in for..in + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 <= end) { + if ((actions.get(ip + 1) instanceof ActionEquals) || (actions.get(ip + 1) instanceof ActionEquals2)) { + if (actions.get(ip + 2) instanceof ActionNot) { + if (actions.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) actions.get(ip + 3); + if (adr2ip(actions, ip2adr(actions, ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + continue; + } + } + } + } + } + } + + /*ActionJump && ActionIf removed*/ + /*if ((action instanceof ActionEnumerate2) || (action instanceof ActionEnumerate)) { + loopStart = ip + 1; + isForIn = true; + ip += 4; + action.translate(localData, stack, output); + EnumerateActionItem en = (EnumerateActionItem) stack.peek(); + inItem = en.object; + continue; + } else*/ /*if (action instanceof ActionTry) { + ActionTry atry = (ActionTry) action; + List tryCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.tryBody, version); + ActionItem catchName; + if (atry.catchInRegisterFlag) { + catchName = new DirectValueActionItem(atry, -1, new RegisterNumber(atry.catchRegister), new ArrayList<>()); + } else { + catchName = new DirectValueActionItem(atry, -1, atry.catchName, new ArrayList<>()); + } + List catchExceptions = new ArrayList(); + catchExceptions.add(catchName); + List> catchCommands = new ArrayList>(); + catchCommands.add(ActionGraph.translateViaGraph(registerNames, variables, functions, atry.catchBody, version)); + List finallyCommands = ActionGraph.translateViaGraph(registerNames, variables, functions, atry.finallyBody, version); + output.add(new TryActionItem(tryCommands, catchExceptions, catchCommands, finallyCommands)); + } else if (action instanceof ActionWith) { + ActionWith awith = (ActionWith) action; + List withCommands = ActionGraph.translateViaGraph(registerNames, variables, functions,new ArrayList() , version); //TODO:parse with actions + output.add(new WithActionItem(action, stack.pop(), withCommands)); + } else */ if (false) { + } /*if (action instanceof ActionStoreRegister) { + if ((ip + 1 <= end) && (actions.get(ip + 1) instanceof ActionPop)) { + action.translate(localData, stack, output); + stack.pop(); + ip++; + } else { + try { + action.translate(localData, stack, output); + } catch (Exception ex) { + // ignore + } + } + } */ /*else if (action instanceof ActionStrictEquals) { + if ((ip + 1 < actions.size()) && (actions.get(ip + 1) instanceof ActionIf)) { + List caseValues = new ArrayList(); + List> caseCommands = new ArrayList>(); + caseValues.add(stack.pop()); + ActionItem switchedObject = stack.pop(); + if (output.size() > 0) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + output.remove(output.size() - 1); + } + } + int caseStart = ip + 2; + List caseBodyIps = new ArrayList(); + long defaultAddr = 0; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip + 1)).getRef(version), version)); + ip++; + do { + ip++; + if ((actions.get(ip - 1) instanceof ActionStrictEquals) && (actions.get(ip) instanceof ActionIf)) { + caseValues.add(actionsToStackTree(registerNames, jumpsOrIfs, actions, constants, caseStart, ip - 2, version).pop()); + caseStart = ip + 1; + caseBodyIps.add(adr2ip(actions, ((ActionIf) actions.get(ip)).getRef(version), version)); + if (actions.get(ip + 1) instanceof ActionJump) { + defaultAddr = ((ActionJump) actions.get(ip + 1)).getRef(version); + ip = adr2ip(actions, defaultAddr, version); + break; + } + } + } while (ip < end); + + for (int i = 0; i < caseBodyIps.size(); i++) { + int caseEnd = ip - 1; + if (i < caseBodyIps.size() - 1) { + caseEnd = caseBodyIps.get(i + 1) - 1; + } + caseCommands.add(actionsToTree(registerNames, unknownJumps, loopList, jumpsOrIfs, stack, constants, actions, caseBodyIps.get(i), caseEnd, version)); + } + output.add(new SwitchActionItem(action, defaultAddr, switchedObject, caseValues, caseCommands, null)); + continue; + } else { + action.translate(stack, constants, output, registerNames); + } + } */ else { + + if (action instanceof ActionStore) { + ActionStore store = (ActionStore) action; + store.setStore(actions.subList(ip + 1, ip + 1 + store.getStoreSize())); + ip = ip + 1 + store.getStoreSize() - 1/*ip++ will be next*/; + } + + try { + action.translate(localData, stack, output, staticOperation, path); + } catch (EmptyStackException ese) { + logger.log(Level.SEVERE, "Decompilation error in: " + path, ese); + output.add(new UnsupportedActionItem(action, "Empty stack")); + } + + } + + ip++; + } + //output = checkClass(output); + log("Leaving " + start + "-" + end); + return output; + } + + 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, ((GetMemberActionItem) t).memberName); + if (lastMember == null) { + return gvt; + } else { + lastMember.object = gvt; + } + } + } + } + } + return ti; + } + + public static List checkClass(List output) { + if (true) { + //return output; + } + List ret = new ArrayList<>(); + List functions = new ArrayList<>(); + List staticFunctions = new ArrayList<>(); + List> vars = new ArrayList<>(); + List> staticVars = 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 (true) { //it.onFalse.isEmpty()){ //||(it.onFalse.get(0) instanceof UnsupportedActionItem)) { + 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 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++; + } + if (parts.get(ipos) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem sr = (StoreRegisterActionItem) parts.get(ipos); + int 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; + int 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 = (className instanceof GetMemberActionItem) ? ((GetMemberActionItem) className).memberName : className; + functions.add((FunctionActionItem) sr.value); + + for (; ipos < parts.size(); ipos++) { + if (parts.get(ipos) instanceof ImplementsOpActionItem) { + ImplementsOpActionItem io = (ImplementsOpActionItem) parts.get(ipos); + implementsOp = io.superclasses; + continue; + } + if (parts.get(ipos) instanceof SetMemberActionItem) { + sm = (SetMemberActionItem) parts.get(ipos); + 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) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + functions.add((FunctionActionItem) sm.value); + } else { + vars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } else if (rnum == classReg) { + if (sm.value instanceof FunctionActionItem) { + ((FunctionActionItem) sm.value).calculatedFunctionName = sm.objectName; + staticFunctions.add((FunctionActionItem) sm.value); + } else { + staticVars.add(new MyEntry<>(sm.objectName, sm.value)); + } + } + + } + } + + } + + } + } + List output2 = new ArrayList<>(); + for (int i = 0; i < prevCount; i++) { + output2.add(output.get(i)); + } + output2.add(new ClassActionItem(className, extendsOp, implementsOp, null/*FIXME*/, functions, vars, staticFunctions, staticVars)); + return output2; + } + } + } 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; + } + } + } + } + } + } else { + ok = false; + } + } else { + ok = false; + } + } else { + ok = false; + } + } else { + prevCount++; + //ok = false; + } + if (!ok) { + break; + } + } + return output; + } + + @Override + public boolean ignoredLoops() { + return false; + } + + public static void setConstantPool(List actions, ConstantPool cpool) { + for (GraphSourceItem a : actions) { + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + if (a instanceof ActionDefineFunction) { + if (cpool != null) { + //((ActionDefineFunction) a).setConstantPool(cpool.constants,actions); + } + } + if (a instanceof ActionDefineFunction2) { + if (cpool != null) { + //((ActionDefineFunction2) a).setConstantPool(cpool.constants,actions); + } + } + } + } + + public GraphTextWriter getASMSourceReplaced(ActionList container, Set knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) { + writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode)); + return writer; + } + + public static double toFloatPoint(Object o) { + if (o instanceof Double) { + return (Double) o; + } + if (o instanceof Integer) { + return (Integer) o; + } + if (o instanceof Long) { + return (Long) o; + } + if (o instanceof String) { + try { + return Double.parseDouble((String) o); + } catch (NumberFormatException nfe) { + return 0; + } + } + return 0; + } + + public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List variables) { + GraphTargetItem ret = get; + boolean boxed = false; + if (get instanceof VariableActionItem) { + boxed = true; + ret = ((VariableActionItem) ret).getBoxedValue(); + } + if (ret instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) ret; + ret = new SetVariableActionItem(null, gv.name, value); + } else if (ret instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) ret; + ret = new SetMemberActionItem(null, mem.object, mem.memberName, value); + } else if ((ret instanceof DirectValueActionItem) && ((DirectValueActionItem) ret).value instanceof RegisterNumber) { + ret = new StoreRegisterActionItem(null, (RegisterNumber) ((DirectValueActionItem) ret).value, value, false); + } else if (ret instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) ret; + ret = new SetPropertyActionItem(null, gp.target, gp.propertyIndex, value); + } + if (boxed) { + GraphTargetItem b = ret; + ret = new VariableActionItem(((VariableActionItem) get).getVariableName(), value, ((VariableActionItem) get).isDefinition()); + ((VariableActionItem) ret).setBoxedValue((ActionItem) b); + variables.remove((VariableActionItem) get); + variables.add((VariableActionItem) ret); + } + return ret; + } + + @Override + public boolean isDeobfuscatePop() { + return false; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public String getFile() { + return null; + } +} 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 c8ad89d07..bf1288e03 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 @@ -1,487 +1,487 @@ -/* - * Copyright (C) 2010-2015 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.BaseLocalData; -import com.jpexs.decompiler.flash.FinalProcessLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; -import com.jpexs.decompiler.flash.action.model.FunctionActionItem; -import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; -import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; -import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; -import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; -import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; -import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; -import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.Loop; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.WhileItem; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * - * @author JPEXS - */ -public class ActionGraph extends Graph { - - public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { - super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); - //this.version = version; - /*heads = makeGraph(code, new ArrayList()); - for (GraphPart head : heads) { - fixGraph(head); - makeMulti(head, new ArrayList()); - }*/ - } - - public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { - - ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); - ActionLocalData localData = new ActionLocalData(registerNames); - g.init(localData); - return g.translate(localData, staticOperation, path); - } - - @Override - public void finalProcessStack(TranslateStack stack, List output) { - if (stack.size() > 0) { - for (int i = stack.size() - 1; i >= 0; i--) { - //System.err.println(stack.get(i)); - if (stack.get(i) instanceof FunctionActionItem) { - FunctionActionItem f = (FunctionActionItem) stack.remove(i); - if (!output.contains(f)) { - output.add(0, f); - } - } - } - } - } - - @Override - protected void finalProcess(List list, int level, FinalProcessLocalData localData) { - super.finalProcess(list, level, localData); - List ret = Action.checkClass(list); - if (ret != list) { - list.clear(); - list.addAll(ret); - } - int targetStart; - int targetEnd; - - boolean again; - do { - again = false; - targetStart = -1; - targetEnd = -1; - GraphTargetItem targetStartItem = null; - GraphTargetItem target = null; - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - if (it instanceof SetTargetActionItem) { - SetTargetActionItem st = (SetTargetActionItem) it; - if (st.target.isEmpty()) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - target = new DirectValueActionItem(null, 0, st.target, new ArrayList<>()); - targetStart = t; - targetStartItem = it; - } - } - if (it instanceof SetTarget2ActionItem) { - SetTarget2ActionItem st = (SetTarget2ActionItem) it; - if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { - if (targetStart > -1) { - targetEnd = t; - break; - } - } else { - targetStart = t; - target = st.target; - targetStartItem = it; - } - } - } - if ((targetStart > -1) && (targetEnd > -1)) { - List newlist = new ArrayList<>(); - for (int i = 0; i < targetStart; i++) { - newlist.add(list.get(i)); - } - List tellist = new ArrayList<>(); - for (int i = targetStart + 1; i < targetEnd; i++) { - tellist.add(list.get(i)); - } - newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); - for (int i = targetEnd + 1; i < list.size(); i++) { - newlist.add(list.get(i)); - } - list.clear(); - list.addAll(newlist); - again = true; - } - } while (again); - for (int t = 0; t < list.size(); t++) { - GraphTargetItem it = list.get(t); - - if (it instanceof WhileItem) { - WhileItem wi = (WhileItem) it; - if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { - SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); - if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { - NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); - if (ne.rightSide instanceof DirectValueActionItem) { - DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; - if (dv.value instanceof Null) { - GraphTargetItem en = ne.leftSide; - if (en instanceof StoreRegisterActionItem) { - en = ((StoreRegisterActionItem) en).value; - } - if (en instanceof EnumerateActionItem) { - EnumerateActionItem eti = (EnumerateActionItem) en; - list.remove(t); - wi.commands.remove(0); - list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); - } - } - } - } - } - - } - } - //detectChained(list, temporaryRegisters); - } - - @Override - protected List checkPrecoNextParts(GraphPart part) { - List items = getPartItems(part); - part = makeMultiPart(part); - if (items.size() > 1) { - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - List storeRegisters = new ArrayList<>(); - for (GraphSourceItem s : items) { - if (s instanceof ActionStoreRegister) { - ActionStoreRegister sr = (ActionStoreRegister) s; - storeRegisters.add(sr.registerNumber); - } - } - if (!storeRegisters.isEmpty()) { - List caseBodies = new ArrayList<>(); - boolean proceed = false; - do { - proceed = false; - caseBodies.add(part.nextParts.get(0)); //jump - part = part.nextParts.get(1); //nojump - items = getPartItems(part); - part = makeMultiPart(part); - if (!items.isEmpty()) { - if (items.get(0) instanceof ActionPush) { - ActionPush pu = (ActionPush) items.get(0); - if (!pu.values.isEmpty()) { - if (pu.values.get(0) instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) pu.values.get(0); - if (storeRegisters.contains(rn.number)) { - storeRegisters.clear(); - storeRegisters.add(rn.number); - if (items.get(items.size() - 1) instanceof ActionIf) { - if (items.size() > 1) { - if (items.get(items.size() - 2) instanceof ActionStrictEquals) { - proceed = true; - } - } - } - } - } - } - } - } - } while (proceed); - - if (caseBodies.size() > 1) { - caseBodies.add(part); //TODO: properly detect default clause (?) - return caseBodies; - } - } - } - } - } - return null; - } - - @Override - protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); - if (str.value instanceof EnumerateActionItem) { - output.remove(output.size() - 1); - } - } - } - List ret = null; - if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { - - GraphTargetItem switchedObject = null; - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; - } - } - if (switchedObject == null) { - switchedObject = new DirectValueActionItem(null, -1, new Null(), null); - } - HashMap caseValuesMap = new HashMap<>(); - - int pos = 0; - StrictEqActionItem set = (StrictEqActionItem) stack.pop(); - caseValuesMap.put(pos, set.rightSide); - if (set.leftSide instanceof StoreRegisterActionItem) { - switchedObject = ((StoreRegisterActionItem) set.leftSide).value; - } - //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); - List caseBodyParts = new ArrayList<>(); - caseBodyParts.add(part.nextParts.get(0)); - GraphTargetItem top = null; - int cnt = 1; - while (part.nextParts.size() > 1 - && part.nextParts.get(1).getHeight() > 1 - && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf - && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { - cnt++; - part = part.nextParts.get(1); - pos++; - caseBodyParts.add(part.nextParts.get(0)); - - set = (StrictEqActionItem) top; - caseValuesMap.put(pos, set.rightSide); - } - if (cnt == 1) { - stack.push(set); - } else { - part = part.nextParts.get(1); - - GraphPart defaultPart = part; //21-21 - //caseBodyParts.add(defaultPart); - - List defaultAndLastPart = new ArrayList<>(); - defaultAndLastPart.add(defaultPart); - defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); - - GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 - - List defaultCommands = new ArrayList<>(); - List stopPart2 = new ArrayList<>(stopPart); - stopPart2.add(defaultPart2); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); - - List loopContinues = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - loopContinues.add(l.loopContinue); - } - } - - List breakParts = new ArrayList<>(); - /*for (int g = 0; g < caseBodyParts.size(); g++) { - if (g < caseBodyParts.size() - 1) { - if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { - continue; - } - } - GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); - if (nsp != null) { - breakParts.add(nsp); - } - } - Collections.sort(breakParts, new Comparator() { - @Override - public int compare(GraphPart o1, GraphPart o2) { - return o2.path.length() - o1.path.length(); - } - });*/ - - //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); - List mcp = new ArrayList<>(); - mcp.addAll(caseBodyParts); - if (defaultPart2 != null) { - mcp.add(defaultPart2); - } - GraphPart breakPart = getMostCommonPart(localData, mcp, loops); - if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { - defaultPart = defaultPart2; - } - - List caseValues = new ArrayList<>(); - for (int i = 0; i < caseBodyParts.size(); i++) { - if (caseValuesMap.containsKey(i)) { - caseValues.add(caseValuesMap.get(i)); - } else { - continue; - } - } - - List> caseCommands = new ArrayList<>(); - GraphPart next = null; - - next = breakPart; - - GraphTargetItem ti = checkLoop(next, stopPart, loops); - currentLoop = new Loop(loops.size(), null, next); - currentLoop.phase = 1; - loops.add(currentLoop); - //switchLoc.getNextPartPath(new ArrayList()); - List valuesMapping = new ArrayList<>(); - List caseBodies = new ArrayList<>(); - for (int i = 0; i < caseValues.size(); i++) { - GraphPart cur = caseBodyParts.get(i); - if (!caseBodies.contains(cur)) { - caseBodies.add(cur); - } - valuesMapping.add(caseBodies.indexOf(cur)); - } - - if (defaultPart == breakPart) { - defaultPart = null; - } - if ((defaultPart != null) && (defaultCommands.isEmpty())) { - List stopPart2x = new ArrayList<>(stopPart); - stopPart2x.add(next); - defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); - } - - if (!defaultCommands.isEmpty()) { - if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { - BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); - if (bi.loopId == currentLoop.id) { - defaultCommands.remove(defaultCommands.size() - 1); - } - } - } - - List ignored = new ArrayList<>(); - for (Loop l : loops) { - ignored.add(l.loopContinue); - } - - for (int i = 0; i < caseBodies.size(); i++) { - List cc = new ArrayList<>(); - GraphPart nextCase = null; - nextCase = next; - if (next != null) { - if (i < caseBodies.size() - 1) { - if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = caseBodies.get(i + 1); - } - } else if (!defaultCommands.isEmpty()) { - if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { - cc.add(new BreakItem(null, currentLoop.id)); - } else { - nextCase = defaultPart; - } - } - } - List stopPart2x = new ArrayList<>(stopPart); - //stopPart2.add(nextCase); - for (GraphPart b : caseBodies) { - if (b != caseBodies.get(i)) { - stopPart2x.add(b); - } - } - if (defaultPart != null) { - stopPart2x.add(defaultPart); - } - if (breakPart != null) { - stopPart2x.add(breakPart); - } - cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); - if (cc.size() >= 2) { - if (cc.get(cc.size() - 1) instanceof BreakItem) { - if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { - cc.remove(cc.size() - 1); - } - } - } - caseCommands.add(cc); - } - ret = new ArrayList<>(); - ret.addAll(output); - SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); - ret.add(sti); - currentLoop.phase = 2; - if (next != null) { - if (ti != null) { - ret.add(ti); - } else { - ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); - } - } - } - } - return ret; - } - - @Override - protected int checkIp(int ip) { - int oldIp = ip; - //return in for..in - GraphSourceItem action = code.get(ip); - if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { - if (ip + 3 < code.size()) { - if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { - if (code.get(ip + 2) instanceof ActionNot) { - if (code.get(ip + 3) instanceof ActionIf) { - ActionIf aif = (ActionIf) code.get(ip + 3); - if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { - ip += 4; - } - } - } - } - } - } - if (oldIp != ip) { - return checkIp(ip); - } - return ip; - } -} +/* + * Copyright (C) 2010-2015 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.BaseLocalData; +import com.jpexs.decompiler.flash.FinalProcessLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.EnumerateActionItem; +import com.jpexs.decompiler.flash.action.model.FunctionActionItem; +import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem; +import com.jpexs.decompiler.flash.action.model.SetTargetActionItem; +import com.jpexs.decompiler.flash.action.model.SetTypeActionItem; +import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem; +import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem; +import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem; +import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionNot; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSource; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.Loop; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.BreakItem; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.SwitchItem; +import com.jpexs.decompiler.graph.model.WhileItem; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +/** + * + * @author JPEXS + */ +public class ActionGraph extends Graph { + + public ActionGraph(List code, HashMap registerNames, HashMap variables, HashMap functions, int version) { + super(new ActionGraphSource(code, version, registerNames, variables, functions), new ArrayList()); + //this.version = version; + /*heads = makeGraph(code, new ArrayList()); + for (GraphPart head : heads) { + fixGraph(head); + makeMulti(head, new ArrayList()); + }*/ + } + + public static List translateViaGraph(HashMap registerNames, HashMap variables, HashMap functions, List code, int version, int staticOperation, String path) throws InterruptedException { + + ActionGraph g = new ActionGraph(code, registerNames, variables, functions, version); + ActionLocalData localData = new ActionLocalData(registerNames); + g.init(localData); + return g.translate(localData, staticOperation, path); + } + + @Override + public void finalProcessStack(TranslateStack stack, List output) { + if (stack.size() > 0) { + for (int i = stack.size() - 1; i >= 0; i--) { + //System.err.println(stack.get(i)); + if (stack.get(i) instanceof FunctionActionItem) { + FunctionActionItem f = (FunctionActionItem) stack.remove(i); + if (!output.contains(f)) { + output.add(0, f); + } + } + } + } + } + + @Override + protected void finalProcess(List list, int level, FinalProcessLocalData localData) { + super.finalProcess(list, level, localData); + List ret = Action.checkClass(list); + if (ret != list) { + list.clear(); + list.addAll(ret); + } + int targetStart; + int targetEnd; + + boolean again; + do { + again = false; + targetStart = -1; + targetEnd = -1; + GraphTargetItem targetStartItem = null; + GraphTargetItem target = null; + for (int t = 0; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + if (it instanceof SetTargetActionItem) { + SetTargetActionItem st = (SetTargetActionItem) it; + if (st.target.isEmpty()) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + target = new DirectValueActionItem(null, 0, st.target, new ArrayList<>()); + targetStart = t; + targetStartItem = it; + } + } + if (it instanceof SetTarget2ActionItem) { + SetTarget2ActionItem st = (SetTarget2ActionItem) it; + if ((st.target instanceof DirectValueActionItem) && st.target.getResult().equals("")) { + if (targetStart > -1) { + targetEnd = t; + break; + } + } else { + targetStart = t; + target = st.target; + targetStartItem = it; + } + } + } + if ((targetStart > -1) && (targetEnd > -1)) { + List newlist = new ArrayList<>(); + for (int i = 0; i < targetStart; i++) { + newlist.add(list.get(i)); + } + List tellist = new ArrayList<>(); + for (int i = targetStart + 1; i < targetEnd; i++) { + tellist.add(list.get(i)); + } + newlist.add(new TellTargetActionItem(targetStartItem.src, target, tellist)); + for (int i = targetEnd + 1; i < list.size(); i++) { + newlist.add(list.get(i)); + } + list.clear(); + list.addAll(newlist); + again = true; + } + } while (again); + for (int t = 0; t < list.size(); t++) { + GraphTargetItem it = list.get(t); + + if (it instanceof WhileItem) { + WhileItem wi = (WhileItem) it; + if ((!wi.commands.isEmpty()) && (wi.commands.get(0) instanceof SetTypeActionItem)) { + SetTypeActionItem sti = (SetTypeActionItem) wi.commands.get(0); + if (wi.expression.get(wi.expression.size() - 1) instanceof NeqActionItem) { + NeqActionItem ne = (NeqActionItem) wi.expression.get(wi.expression.size() - 1); + if (ne.rightSide instanceof DirectValueActionItem) { + DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide; + if (dv.value instanceof Null) { + GraphTargetItem en = ne.leftSide; + if (en instanceof StoreRegisterActionItem) { + en = ((StoreRegisterActionItem) en).value; + } + if (en instanceof EnumerateActionItem) { + EnumerateActionItem eti = (EnumerateActionItem) en; + list.remove(t); + wi.commands.remove(0); + list.add(t, new ForInActionItem(null, wi.loop, sti.getObject(), eti.object, wi.commands)); + } + } + } + } + } + + } + } + //detectChained(list, temporaryRegisters); + } + + @Override + protected List checkPrecoNextParts(GraphPart part) { + List items = getPartItems(part); + part = makeMultiPart(part); + if (items.size() > 1) { + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + List storeRegisters = new ArrayList<>(); + for (GraphSourceItem s : items) { + if (s instanceof ActionStoreRegister) { + ActionStoreRegister sr = (ActionStoreRegister) s; + storeRegisters.add(sr.registerNumber); + } + } + if (!storeRegisters.isEmpty()) { + List caseBodies = new ArrayList<>(); + boolean proceed = false; + do { + proceed = false; + caseBodies.add(part.nextParts.get(0)); //jump + part = part.nextParts.get(1); //nojump + items = getPartItems(part); + part = makeMultiPart(part); + if (!items.isEmpty()) { + if (items.get(0) instanceof ActionPush) { + ActionPush pu = (ActionPush) items.get(0); + if (!pu.values.isEmpty()) { + if (pu.values.get(0) instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) pu.values.get(0); + if (storeRegisters.contains(rn.number)) { + storeRegisters.clear(); + storeRegisters.add(rn.number); + if (items.get(items.size() - 1) instanceof ActionIf) { + if (items.size() > 1) { + if (items.get(items.size() - 2) instanceof ActionStrictEquals) { + proceed = true; + } + } + } + } + } + } + } + } + } while (proceed); + + if (caseBodies.size() > 1) { + caseBodies.add(part); //TODO: properly detect default clause (?) + return caseBodies; + } + } + } + } + } + return null; + } + + @Override + protected List check(GraphSource code, BaseLocalData localData, List allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List loops, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + StoreRegisterActionItem str = (StoreRegisterActionItem) output.get(output.size() - 1); + if (str.value instanceof EnumerateActionItem) { + output.remove(output.size() - 1); + } + } + } + List ret = null; + if ((part.nextParts.size() == 2) && (!stack.isEmpty()) && (stack.peek() instanceof StrictEqActionItem)) { + + GraphTargetItem switchedObject = null; + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) output.get(output.size() - 1)).value; + } + } + if (switchedObject == null) { + switchedObject = new DirectValueActionItem(null, -1, new Null(), null); + } + HashMap caseValuesMap = new HashMap<>(); + + int pos = 0; + StrictEqActionItem set = (StrictEqActionItem) stack.pop(); + caseValuesMap.put(pos, set.rightSide); + if (set.leftSide instanceof StoreRegisterActionItem) { + switchedObject = ((StoreRegisterActionItem) set.leftSide).value; + } + //GraphPart switchLoc = part.nextParts.get(1).nextParts.get(0); + List caseBodyParts = new ArrayList<>(); + caseBodyParts.add(part.nextParts.get(0)); + GraphTargetItem top = null; + int cnt = 1; + while (part.nextParts.size() > 1 + && part.nextParts.get(1).getHeight() > 1 + && code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf + && ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) { + cnt++; + part = part.nextParts.get(1); + pos++; + caseBodyParts.add(part.nextParts.get(0)); + + set = (StrictEqActionItem) top; + caseValuesMap.put(pos, set.rightSide); + } + if (cnt == 1) { + stack.push(set); + } else { + part = part.nextParts.get(1); + + GraphPart defaultPart = part; //21-21 + //caseBodyParts.add(defaultPart); + + List defaultAndLastPart = new ArrayList<>(); + defaultAndLastPart.add(defaultPart); + defaultAndLastPart.add(caseBodyParts.get(caseBodyParts.size() - 1)); + + GraphPart defaultPart2 = getCommonPart(localData, defaultAndLastPart, loops);//34-37 + + List defaultCommands = new ArrayList<>(); + List stopPart2 = new ArrayList<>(stopPart); + stopPart2.add(defaultPart2); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2, loops, staticOperation, path); + + List loopContinues = new ArrayList<>(); + for (Loop l : loops) { + if (l.loopContinue != null) { + loopContinues.add(l.loopContinue); + } + } + + List breakParts = new ArrayList<>(); + /*for (int g = 0; g < caseBodyParts.size(); g++) { + if (g < caseBodyParts.size() - 1) { + if (caseBodyParts.get(g).leadsTo(code, caseBodyParts.get(g + 1), loops)) { + continue; + } + } + GraphPart nsp = caseBodyParts.get(g).getNextSuperPartPath(loopContinues); + if (nsp != null) { + breakParts.add(nsp); + } + } + Collections.sort(breakParts, new Comparator() { + @Override + public int compare(GraphPart o1, GraphPart o2) { + return o2.path.length() - o1.path.length(); + } + });*/ + + //GraphPart breakPart = breakParts.isEmpty() ? null : breakParts.get(0); + List mcp = new ArrayList<>(); + mcp.addAll(caseBodyParts); + if (defaultPart2 != null) { + mcp.add(defaultPart2); + } + GraphPart breakPart = getMostCommonPart(localData, mcp, loops); + if ((defaultPart2 != breakPart) && (defaultCommands.isEmpty())) { + defaultPart = defaultPart2; + } + + List caseValues = new ArrayList<>(); + for (int i = 0; i < caseBodyParts.size(); i++) { + if (caseValuesMap.containsKey(i)) { + caseValues.add(caseValuesMap.get(i)); + } else { + continue; + } + } + + List> caseCommands = new ArrayList<>(); + GraphPart next = null; + + next = breakPart; + + GraphTargetItem ti = checkLoop(next, stopPart, loops); + currentLoop = new Loop(loops.size(), null, next); + currentLoop.phase = 1; + loops.add(currentLoop); + //switchLoc.getNextPartPath(new ArrayList()); + List valuesMapping = new ArrayList<>(); + List caseBodies = new ArrayList<>(); + for (int i = 0; i < caseValues.size(); i++) { + GraphPart cur = caseBodyParts.get(i); + if (!caseBodies.contains(cur)) { + caseBodies.add(cur); + } + valuesMapping.add(caseBodies.indexOf(cur)); + } + + if (defaultPart == breakPart) { + defaultPart = null; + } + if ((defaultPart != null) && (defaultCommands.isEmpty())) { + List stopPart2x = new ArrayList<>(stopPart); + stopPart2x.add(next); + defaultCommands = printGraph(localData, stack, allParts, null, defaultPart, stopPart2x, loops, staticOperation, path); + } + + if (!defaultCommands.isEmpty()) { + if (defaultCommands.get(defaultCommands.size() - 1) instanceof BreakItem) { + BreakItem bi = (BreakItem) defaultCommands.get(defaultCommands.size() - 1); + if (bi.loopId == currentLoop.id) { + defaultCommands.remove(defaultCommands.size() - 1); + } + } + } + + List ignored = new ArrayList<>(); + for (Loop l : loops) { + ignored.add(l.loopContinue); + } + + for (int i = 0; i < caseBodies.size(); i++) { + List cc = new ArrayList<>(); + GraphPart nextCase = null; + nextCase = next; + if (next != null) { + if (i < caseBodies.size() - 1) { + if (!caseBodies.get(i).leadsTo(localData, this, code, caseBodies.get(i + 1), loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = caseBodies.get(i + 1); + } + } else if (!defaultCommands.isEmpty()) { + if (!caseBodies.get(i).leadsTo(localData, this, code, defaultPart, loops)) { + cc.add(new BreakItem(null, currentLoop.id)); + } else { + nextCase = defaultPart; + } + } + } + List stopPart2x = new ArrayList<>(stopPart); + //stopPart2.add(nextCase); + for (GraphPart b : caseBodies) { + if (b != caseBodies.get(i)) { + stopPart2x.add(b); + } + } + if (defaultPart != null) { + stopPart2x.add(defaultPart); + } + if (breakPart != null) { + stopPart2x.add(breakPart); + } + cc.addAll(0, printGraph(localData, stack, allParts, null, caseBodies.get(i), stopPart2x, loops, staticOperation, path)); + if (cc.size() >= 2) { + if (cc.get(cc.size() - 1) instanceof BreakItem) { + if ((cc.get(cc.size() - 2) instanceof ContinueItem) || (cc.get(cc.size() - 2) instanceof BreakItem)) { + cc.remove(cc.size() - 1); + } + } + } + caseCommands.add(cc); + } + ret = new ArrayList<>(); + ret.addAll(output); + SwitchItem sti = new SwitchItem(null, currentLoop, switchedObject, caseValues, caseCommands, defaultCommands, valuesMapping); + ret.add(sti); + currentLoop.phase = 2; + if (next != null) { + if (ti != null) { + ret.add(ti); + } else { + ret.addAll(printGraph(localData, stack, allParts, null, next, stopPart, loops, staticOperation, path)); + } + } + } + } + return ret; + } + + @Override + protected int checkIp(int ip) { + int oldIp = ip; + //return in for..in + GraphSourceItem action = code.get(ip); + if ((action instanceof ActionPush) && (((ActionPush) action).values.size() == 1) && (((ActionPush) action).values.get(0) instanceof Null)) { + if (ip + 3 < code.size()) { + if ((code.get(ip + 1) instanceof ActionEquals) || (code.get(ip + 1) instanceof ActionEquals2)) { + if (code.get(ip + 2) instanceof ActionNot) { + if (code.get(ip + 3) instanceof ActionIf) { + ActionIf aif = (ActionIf) code.get(ip + 3); + if (code.adr2pos(code.pos2adr(ip + 4) + aif.getJumpOffset()) == ip) { + ip += 4; + } + } + } + } + } + } + if (oldIp != ip) { + return checkIp(ip); + } + return ip; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 2c7bc5a5a..19d962e4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -1,1011 +1,1011 @@ -/* - * Copyright (C) 2010-2015 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.DisassemblyListener; -import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; -import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; -import com.jpexs.decompiler.flash.action.model.ConstantPool; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionNop; -import com.jpexs.decompiler.flash.action.special.ActionStore; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; -import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.NotCompileTimeItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.CancellableWorker; -import com.jpexs.helpers.Helper; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Scanner; -import java.util.TreeMap; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Class for reading data from SWF file - * - * @author JPEXS - */ -public class ActionListReader { - - private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - * @throws java.util.concurrent.TimeoutException - */ - public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { - try { - final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; - ActionList actions = CancellableWorker.call(new Callable() { - - @Override - public ActionList call() throws IOException, InterruptedException { - return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); - } - }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); - - return actions; - } catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - if (cause instanceof InterruptedException) { - throw (InterruptedException) cause; - } else if (cause instanceof InterruptedException) { - throw (IOException) cause; - } else { - logger.log(Level.SEVERE, null, ex); - } - } - return new ActionList(); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param sis - * @param version - * @param ip - * @param endIp - * @param path - * @param deobfuscationMode - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - // actionMap and nextOffsets should contain exaclty the same keys - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - Action entryAction = readActionListAtPos(listeners, null, - sis, actionMap, nextOffsets, - ip, 0, endIp, path, false, new ArrayList()); - - if (actionMap.isEmpty()) { - return new ActionList(); - } - - List addresses = new ArrayList<>(actionMap.keySet()); - - // add end action - Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); - long endAddress; - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); - endAddress = aEnd.getAddress(); - actionMap.put(aEnd.getAddress(), aEnd); - nextOffsets.put(endAddress, endAddress + 1); - } - - ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); - - // jump to the entry action when it is diffrent from the first action in the map - if (entryAction != actions.get(0)) { - ActionJump jump = new ActionDeobfuscateJump(0); - actions.addAction(0, jump); - jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); - } - - if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { - actions = fixActionList(actions, null, version); - } - - if (deobfuscationMode == 0) { - try { - actions = deobfuscateActionList(listeners, actions, version, 0, path); - updateActionLengths(actions, version); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } else if (deobfuscationMode == 1) { - try { - new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); - new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); - } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { - // keep orignal (not deobfuscated) actions - logger.log(Level.SEVERE, null, ex); - } - } - - return actions; - } - - public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - ActionList ret = new ActionList(); - - if (nextOffsets != null) { - int index = 0; - while (index != -1 && index < actions.size()) { - Action action = actions.get(index); - ret.add(action); - index++; - if (index < actions.size()) { - long nextAddress = nextOffsets.get(action.getAddress()); - if (actions.get(index).getAddress() != nextAddress) { - if (!action.isExit() && !(action instanceof ActionJump)) { - ActionJump jump = new ActionDeobfuscateJump(0); - jump.setAddress(action.getAddress()); - int size = jump.getTotalActionLength(); - jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); - ret.add(jump); - } - } - } - } - } else { - ret.addAll(actions); - } - - // Map for storing the targers of the "jump" actions - // "jump" action can be ActionIf, ActionJump and any ActionStore - Map jumps = new HashMap<>(); - getJumps(ret, jumps); - - updateActionLengths(ret, version); - updateAddresses(ret, 0); - long endAddress = ret.get(ret.size() - 1).getAddress(); - - updateJumps(ret, jumps, containerLastActions, endAddress); - updateActionStores(ret, jumps); - updateContainerSizes(ret, containerLastActions); - - return ret; - } - - public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { - // Map of the actions. Use TreeMap to sort the keys in ascending order - Map actionMap = new TreeMap<>(); - Map nextOffsets = new HashMap<>(); - readActionListAtPos(new ArrayList(), null, - sis, actionMap, nextOffsets, - startIp, startIp, endIp + 1, "", false, new ArrayList()); - - return new ArrayList<>(actionMap.values()); - } - - /** - * Reads list of actions from the stream. Reading ends with - * ActionEndFlag(=0) or end of the stream. - * - * @param listeners - * @param actions - * @param version - * @param ip - * @param path - * @return List of actions - * @throws IOException - * @throws java.lang.InterruptedException - */ - private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { - if (actions.isEmpty()) { - return actions; - } - - Action lastAction = actions.get(actions.size() - 1); - int endIp = (int) lastAction.getAddress(); - - List retMap = new ArrayList<>(endIp); - for (int i = 0; i < endIp; i++) { - retMap.add(null); - } - List actionMap = new ArrayList<>(endIp); - for (int i = 0; i <= endIp; i++) { - actionMap.add(null); - } - for (Action a : actions) { - actionMap.set((int) a.getAddress(), a); - } - - int maxRecursionLevel = 0; - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { - maxRecursionLevel++; - } - if (a instanceof ActionIf) { - ActionIf aif = (ActionIf) a; - aif.ignoreUsed = false; - aif.jumpUsed = false; - } - } - - deobfustaceActionListAtPosRecursive(listeners, - new ArrayList(), - new HashMap>(), - new ActionLocalData(), - new TranslateStack(), - new ConstantPool(), - actionMap, ip, retMap, ip, endIp, path, - new HashMap(), false, - new HashMap>(), - version, 0, maxRecursionLevel); - - ActionList ret = new ActionList(); - Action last = null; - for (Action a : retMap) { - if (a != last && a != null) { - ret.add(a); - } - last = a; - } - ret.removeNops(); - ActionList reta = new ActionList(); - for (Object o : ret) { - if (o instanceof Action) { - reta.add((Action) o); - } - } - return reta; - } - - private static long getNearAddress(ActionList actions, long address, boolean next) { - int min = 0; - int max = actions.size() - 1; - - while (max >= min) { - int mid = (min + max) / 2; - long midValue = actions.get(mid).getAddress(); - if (midValue == address) { - return address; - } else if (midValue < address) { - min = mid + 1; - } else { - max = mid - 1; - } - } - - return next - ? (min < actions.size() ? actions.get(min).getAddress() : -1) - : (max >= 0 ? actions.get(max).getAddress() : -1); - } - - private static Map actionListToMap(List actions) { - Map map = new HashMap<>(actions.size()); - for (Action a : actions) { - long address = a.getAddress(); - // There are multiple actions in the same address (2nd action is a jump for obfuscated code) - // So this check is required - if (!map.containsKey(address)) { - map.put(a.getAddress(), a); - } - } - return map; - } - - private static void getJumps(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (Action a : actions) { - long target = -1; - if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); - } else if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - int storeSize = aStore.getStoreSize(); - // skip storeSize + 1 actions (+1 is the current action) - Action targetAction = a; - for (int i = 0; i <= storeSize; i++) { - long address = targetAction.getAddress() + targetAction.getTotalActionLength(); - targetAction = actionMap.get(address); - if (targetAction == null) { - break; - } - } - jumps.put(a, targetAction); - } - if (target >= 0) { - Action targetAction = actionMap.get(target); - jumps.put(a, targetAction); - } - } - } - - public static List getContainerLastActions(ActionList actions, Action action) { - GraphSourceItemContainer container = (GraphSourceItemContainer) action; - List sizes = container.getContainerSizes(); - long endAddress = action.getAddress() + container.getHeaderSize(); - List lasts = new ArrayList<>(sizes.size()); - for (long size : sizes) { - endAddress += size; - long lastActionAddress = getNearAddress(actions, endAddress - 1, false); - Action lastAction = null; - if (lastActionAddress != -1) { - lastAction = actions.getByAddress(lastActionAddress); - } - lasts.add(lastAction); - } - return lasts; - } - - private static void getContainerLastActions(ActionList actions, Map> lastActions) { - for (Action a : actions) { - if (a instanceof GraphSourceItemContainer) { - lastActions.put(a, getContainerLastActions(actions, a)); - } - } - } - - private static long updateAddresses(List actions, long address) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - a.setAddress(address); - int length = a.getTotalActionLength(); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - // placeholder for jump action - length = new ActionDeobfuscateJump(0).getTotalActionLength(); - } - address += length; - } - return address; - } - - private static void updateActionLengths(List actions, int version) { - for (int i = 0; i < actions.size(); i++) { - actions.get(i).updateLength(version); - } - } - - private static void updateActionStores(List actions, Map jumps) { - Map actionMap = actionListToMap(actions); - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof ActionStore) { - ActionStore aStore = (ActionStore) a; - Action nextActionAfterStore = jumps.get(a); - Action a1 = a; - List store = new ArrayList<>(); - while (true) { - long address = a1.getAddress() + a1.getTotalActionLength(); - a1 = actionMap.get(address); - if (a1 == null || a1 == nextActionAfterStore) { - break; - } - store.add(a1); - } - aStore.setStore(store); - } - } - } - - private static void updateContainerSizes(List actions, Map> containerLastActions) { - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer container = (GraphSourceItemContainer) a; - List lastActions = containerLastActions.get(a); - long startAddress = a.getAddress() + container.getHeaderSize(); - for (int j = 0; j < lastActions.size(); j++) { - Action lastAction = lastActions.get(j); - int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); - container.setContainerSize(j, length); - startAddress += length; - } - } - } - } - - private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { - for (Action a : jumps.keySet()) { - if (jumps.get(a) == oldTarget) { - jumps.put(a, newTarget); - } - } - } - - private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { - for (Action a : containerLastActions.keySet()) { - List targets = containerLastActions.get(a); - for (int i = 0; i < targets.size(); i++) { - if (targets.get(i) == oldTarget) { - targets.set(i, newTarget); - } - } - } - } - - private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { - if (actions.isEmpty()) { - return; - } - - for (int i = 0; i < actions.size(); i++) { - Action a = actions.get(i); - if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { - ActionJump aJump = new ActionDeobfuscateJump(0); - aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); - aJump.setAddress(a.getAddress()); - replaceJumpTargets(jumps, a, aJump); - replaceContainerLastActions(containerLastActions, a, aJump); - a = aJump; - actions.set(i, a); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aIf.setJumpOffset((int) offset); - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - Action target = jumps.get(a); - long offset; - if (target != null) { - offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); - } else { - offset = endAddress - a.getAddress() - a.getTotalActionLength(); - } - aJump.setJumpOffset((int) offset); - } - } - } - - /** - * Removes an action from the action list, and updates all references This - * method will keep the inner actions of the container when you remove the - * container - * - * @param actions - * @param index - * @param version - * @param removeWhenLast - * @return - */ - public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { - - if (index < 0 || actions.size() <= index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - getJumps(actions, jumps); - - Action prevAction = index > 0 ? actions.get(index - 1) : null; - Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; - Action actionToRemove = actions.get(index); - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == actionToRemove) { - if (!removeWhenLast) { - return false; - } - lastActions.set(i, prevAction); - } - } - } - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == actionToRemove) { - jumps.put(a, nextAction); - } - } - if (containerLastActions.containsKey(actionToRemove)) { - containerLastActions.remove(actionToRemove); - } - if (jumps.containsKey(actionToRemove)) { - jumps.remove(actionToRemove); - } - - actions.remove(index); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - /** - * Adds an action to the action list to the specified location, and updates - * all references - * - * @param actions - * @param index - * @param action - * @param version - * @param addToContainer - * @param replaceJump - * @return - */ - public static boolean addAction(ActionList actions, int index, Action action, - int version, boolean addToContainer, boolean replaceJump) { - - if (index < 0 || actions.size() < index) { - return false; - } - - long startIp = actions.get(0).getAddress(); - Action lastAction = actions.get(actions.size() - 1); - if (!(lastAction instanceof ActionEnd)) { - Action aEnd = new ActionEnd(); - aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); - actions.add(aEnd); - lastAction = aEnd; - } - - long endAddress = lastAction.getAddress(); - - Map> containerLastActions = new HashMap<>(); - getContainerLastActions(actions, containerLastActions); - - Map jumps = new HashMap<>(); - List tempActions = new ArrayList<>(actions); - tempActions.add(action); - getJumps(tempActions, jumps); - - Action prevAction = actions.get(index); - if (addToContainer) { - for (Action a : containerLastActions.keySet()) { - List lastActions = containerLastActions.get(a); - for (int i = 0; i < lastActions.size(); i++) { - if (lastActions.get(i) == prevAction) { - lastActions.set(i, action); - } - } - } - } - - if (replaceJump) { - for (Action a : jumps.keySet()) { - Action targetAction = jumps.get(a); - if (targetAction == prevAction) { - jumps.put(a, action); - } - } - } - - actions.add(index, action); - - updateActionLengths(actions, version); - updateAddresses(actions, startIp); - updateJumps(actions, jumps, containerLastActions, endAddress); - updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); - - return true; - } - - private static Action readActionListAtPos(List listeners, ConstantPool cpool, - SWFInputStream sis, Map actions, Map nextOffsets, - long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { - - Action entryAction = null; - - if (visitedContainers.contains(ip)) { - return null; - } - visitedContainers.add(ip); - - Queue jumpQueue = new LinkedList<>(); - jumpQueue.add(ip); - while (!jumpQueue.isEmpty()) { - ip = jumpQueue.remove(); - if (ip < startIp) { - continue; - } - - while (endIp == -1 || endIp > ip) { - sis.seek((int) ip); - - Action a; - if ((a = sis.readAction()) == null) { - break; - } - - int actionLengthWithHeader = a.getTotalActionLength(); - - // unknown action, replace with jump - if (a instanceof ActionNop) { - ActionJump aJump = new ActionDeobfuscateJump(0); - int jumpLength = aJump.getTotalActionLength(); - aJump.setAddress(a.getAddress()); - aJump.setJumpOffset(actionLengthWithHeader - jumpLength); - a = aJump; - actionLengthWithHeader = a.getTotalActionLength(); - } - - if (entryAction == null) { - entryAction = a; - } - - Action existingAction = actions.get(ip); - if (existingAction != null) { - break; - } - - actions.put(ip, a); - nextOffsets.put(ip, ip + actionLengthWithHeader); - - long pos = sis.getPos(); - long length = pos + sis.available(); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressReading(pos, length); - } - - a.setAddress(ip); - - if (a instanceof ActionPush && cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } else if (a instanceof ActionConstantPool) { - cpool = new ConstantPool(((ActionConstantPool) a).constantPool); - } else if (a instanceof ActionIf) { - ActionIf aIf = (ActionIf) a; - long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - } else if (a instanceof ActionJump) { - ActionJump aJump = (ActionJump) a; - long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); - if (nIp >= 0) { - jumpQueue.add(nIp); - } - break; - } else if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - String cntName = cnt.getName(); - String newPath = path + (cntName == null ? "" : "/" + cntName); - for (long size : cnt.getContainerSizes()) { - if (size != 0) { - long ip2 = ip + actionLengthWithHeader; - long endIp2 = ip + actionLengthWithHeader + size; - readActionListAtPos(listeners, cpool, - sis, actions, nextOffsets, - ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); - actionLengthWithHeader += size; - } - } - } - - ip += actionLengthWithHeader; - - if (a.isExit()) { - break; - } - } - } - return entryAction; - } - - private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { - boolean debugMode = false; - boolean decideBranch = false; - - if (recursionLevel > maxRecursionLevel + 1) { - throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); - } - - Action a; - Scanner sc = null; - loopip: - while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - - int actionLen = a.getTotalActionLength(); - if (!visited.containsKey(ip)) { - visited.put(ip, 0); - } - int curVisited = visited.get(ip); - curVisited++; - visited.put(ip, curVisited); - for (int i = 0; i < listeners.size(); i++) { - listeners.get(i).progressDeobfuscating(ip, actions.size()); - } - int info = a.getTotalActionLength(); - - if (a instanceof ActionPush) { - if (cpool != null) { - ((ActionPush) a).constantPool = cpool.constants; - } - } - - if (debugMode) { - String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); - if (a instanceof GraphSourceItemContainer) { - atos = a.toString(); - } - System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); - System.err.print("variables: "); - for (Map.Entry v : localData.variables.entrySet()) { - System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); - } - System.err.println(); - String add = ""; - if (a instanceof ActionIf) { - add = " change: " + ((ActionIf) a).getJumpOffset(); - } - if (a instanceof ActionJump) { - add = " change: " + ((ActionJump) a).getJumpOffset(); - } - System.err.println(add); - } - - int newip = -1; - - if (a instanceof ActionConstantPool) { - if (cpool == null) { - cpool = new ConstantPool(); - } - cpool.setNew(((ActionConstantPool) a).constantPool); - } - ActionIf aif = null; - boolean goaif = false; - if (!a.isIgnored()) { - String varname = null; - if (a instanceof StoreTypeAction) { - StoreTypeAction sta = (StoreTypeAction) a; - varname = sta.getVariableName(stack, cpool); - } - - try { - if (a instanceof ActionIf) { - aif = (ActionIf) a; - - GraphTargetItem top = stack.pop(); - int nip = ip + actionLen + aif.getJumpOffset(); - - if (decideBranch) { - System.out.print("newip " + nip + ", "); - System.out.print("Action: jump(j),ignore(i),compute(c)?"); - if (sc == null) { - sc = new Scanner(System.in); - } - String next = sc.next(); - switch (next) { - case "j": - newip = nip; - break; - case "i": - break; - case "c": - goaif = true; - break; - } - } else if (top.isCompileTime() && (!top.hasSideEffect())) { - if (debugMode) { - System.err.print("is compiletime -> "); - } - if (EcmaScript.toBoolean(top.getResult())) { - newip = nip; - aif.jumpUsed = true; - if (debugMode) { - System.err.println("jump"); - } - } else { - aif.ignoreUsed = true; - if (debugMode) { - System.err.println("ignore"); - } - } - } else { - if (debugMode) { - System.err.println("goaif"); - } - goaif = true; - } - } else if (a instanceof ActionJump) { - newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); - } else if (!(a instanceof GraphSourceItemContainer)) { - //return in for..in, TODO:Handle this better way - if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); - } - if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { - stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); - } - a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); - } - } catch (RuntimeException ex) { - logger.log(Level.SEVERE, "Disassembly exception", ex); - break; - } - - HashMap vars = localData.variables; - if (varname != null) { - GraphTargetItem varval = vars.get(varname); - if (varval != null && varval.isCompileTime() && indeterminate) { - vars.put(varname, new NotCompileTimeItem(null, varval)); - } - } - } - for (int i = 0; i < actionLen; i++) { - ret.set(ip + i, a); - } - - if (a instanceof GraphSourceItemContainer) { - GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; - if (a instanceof Action) { - long endAddr = a.getAddress() + cnt.getHeaderSize(); - String cntName = cnt.getName(); - List> output2s = new ArrayList<>(); - for (long size : cnt.getContainerSizes()) { - if (size == 0) { - output2s.add(new ArrayList()); - continue; - } - ActionLocalData localData2; - List output2 = new ArrayList<>(); - if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { - localData2 = new ActionLocalData(); - } else { - localData2 = localData; - } - deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - output2s.add(output2); - endAddr += size; - } - cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); - ip = (int) endAddr; - continue; - } - } - - if (a instanceof ActionEnd) { - break; - } - if (goaif) { - aif.ignoreUsed = true; - aif.jumpUsed = true; - indeterminate = true; - - HashMap vars = localData.variables; - boolean stateChanged = false; - if (decisionStates.containsKey(ip)) { - HashMap oldstate = decisionStates.get(ip); - if (oldstate.size() != vars.size()) { - stateChanged = true; - } else { - for (String k : vars.keySet()) { - if (!oldstate.containsKey(k)) { - stateChanged = true; - break; - } - if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { - stateChanged = true; - break; - } - } - } - } - HashMap curstate = new HashMap<>(); - curstate.putAll(vars); - decisionStates.put(ip, curstate); - - if ((!stateChanged) && curVisited > 1) { - List branches = new ArrayList<>(); - branches.add(ip + actionLen + aif.getJumpOffset()); - branches.add(ip + actionLen); - for (int br : branches) { - int visc = 0; - if (visited.containsKey(br)) { - visc = visited.get(br); - } - if (visc == 0) {//(localData.regNames), - new HashMap<>(localData.variables), new HashMap<>(localData.functions)); - deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); - } - - if (newip > -1) { - ip = newip; - } else { - ip += info; - } - - if (a.isExit()) { - break; - } - } - for (DisassemblyListener listener : listeners) { - listener.progressDeobfuscating(ip, actions.size()); - } - } -} +/* + * Copyright (C) 2010-2015 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.DisassemblyListener; +import com.jpexs.decompiler.flash.SWFInputStream; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator; +import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscatorSimple; +import com.jpexs.decompiler.flash.action.model.ConstantPool; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; +import com.jpexs.decompiler.flash.action.special.ActionEnd; +import com.jpexs.decompiler.flash.action.special.ActionNop; +import com.jpexs.decompiler.flash.action.special.ActionStore; +import com.jpexs.decompiler.flash.action.swf4.ActionEquals; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSourceItemContainer; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.NotCompileTimeItem; +import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Scanner; +import java.util.TreeMap; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Class for reading data from SWF file + * + * @author JPEXS + */ +public class ActionListReader { + + private static final Logger logger = Logger.getLogger(ActionListReader.class.getName()); + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + * @throws java.util.concurrent.TimeoutException + */ + public static ActionList readActionListTimeout(final List listeners, final SWFInputStream sis, final int version, final int ip, final int endIp, final String path) throws IOException, InterruptedException, TimeoutException { + try { + final int deobfuscationMode = Configuration.autoDeobfuscate.get() ? Configuration.deobfuscationMode.get() : -1; + ActionList actions = CancellableWorker.call(new Callable() { + + @Override + public ActionList call() throws IOException, InterruptedException { + return readActionList(listeners, sis, version, ip, endIp, path, deobfuscationMode); + } + }, Configuration.decompilationTimeoutSingleMethod.get(), TimeUnit.SECONDS); + + return actions; + } catch (ExecutionException ex) { + Throwable cause = ex.getCause(); + if (cause instanceof InterruptedException) { + throw (InterruptedException) cause; + } else if (cause instanceof InterruptedException) { + throw (IOException) cause; + } else { + logger.log(Level.SEVERE, null, ex); + } + } + return new ActionList(); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param sis + * @param version + * @param ip + * @param endIp + * @param path + * @param deobfuscationMode + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + public static ActionList readActionList(List listeners, SWFInputStream sis, int version, int ip, int endIp, String path, int deobfuscationMode) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + // actionMap and nextOffsets should contain exaclty the same keys + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + Action entryAction = readActionListAtPos(listeners, null, + sis, actionMap, nextOffsets, + ip, 0, endIp, path, false, new ArrayList()); + + if (actionMap.isEmpty()) { + return new ActionList(); + } + + List addresses = new ArrayList<>(actionMap.keySet()); + + // add end action + Action lastAction = actionMap.get(addresses.get(addresses.size() - 1)); + long endAddress; + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(nextOffsets.get(lastAction.getAddress())); + endAddress = aEnd.getAddress(); + actionMap.put(aEnd.getAddress(), aEnd); + nextOffsets.put(endAddress, endAddress + 1); + } + + ActionList actions = fixActionList(new ActionList(actionMap.values()), nextOffsets, version); + + // jump to the entry action when it is diffrent from the first action in the map + if (entryAction != actions.get(0)) { + ActionJump jump = new ActionDeobfuscateJump(0); + actions.addAction(0, jump); + jump.setJumpOffset((int) (entryAction.getAddress() - jump.getTotalActionLength())); + } + + if (SWFDecompilerPlugin.fireActionListParsed(actions, sis.getSwf())) { + actions = fixActionList(actions, null, version); + } + + if (deobfuscationMode == 0) { + try { + actions = deobfuscateActionList(listeners, actions, version, 0, path); + updateActionLengths(actions, version); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } else if (deobfuscationMode == 1) { + try { + new ActionDeobfuscatorSimple().actionListParsed(actions, sis.getSwf()); + new ActionDeobfuscator().actionListParsed(actions, sis.getSwf()); + } catch (OutOfMemoryError | StackOverflowError | TranslateException ex) { + // keep orignal (not deobfuscated) actions + logger.log(Level.SEVERE, null, ex); + } + } + + return actions; + } + + public static ActionList fixActionList(ActionList actions, Map nextOffsets, int version) { + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + ActionList ret = new ActionList(); + + if (nextOffsets != null) { + int index = 0; + while (index != -1 && index < actions.size()) { + Action action = actions.get(index); + ret.add(action); + index++; + if (index < actions.size()) { + long nextAddress = nextOffsets.get(action.getAddress()); + if (actions.get(index).getAddress() != nextAddress) { + if (!action.isExit() && !(action instanceof ActionJump)) { + ActionJump jump = new ActionDeobfuscateJump(0); + jump.setAddress(action.getAddress()); + int size = jump.getTotalActionLength(); + jump.setJumpOffset((int) (nextAddress - action.getAddress() - size)); + ret.add(jump); + } + } + } + } + } else { + ret.addAll(actions); + } + + // Map for storing the targers of the "jump" actions + // "jump" action can be ActionIf, ActionJump and any ActionStore + Map jumps = new HashMap<>(); + getJumps(ret, jumps); + + updateActionLengths(ret, version); + updateAddresses(ret, 0); + long endAddress = ret.get(ret.size() - 1).getAddress(); + + updateJumps(ret, jumps, containerLastActions, endAddress); + updateActionStores(ret, jumps); + updateContainerSizes(ret, containerLastActions); + + return ret; + } + + public static List getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { + // Map of the actions. Use TreeMap to sort the keys in ascending order + Map actionMap = new TreeMap<>(); + Map nextOffsets = new HashMap<>(); + readActionListAtPos(new ArrayList(), null, + sis, actionMap, nextOffsets, + startIp, startIp, endIp + 1, "", false, new ArrayList()); + + return new ArrayList<>(actionMap.values()); + } + + /** + * Reads list of actions from the stream. Reading ends with + * ActionEndFlag(=0) or end of the stream. + * + * @param listeners + * @param actions + * @param version + * @param ip + * @param path + * @return List of actions + * @throws IOException + * @throws java.lang.InterruptedException + */ + private static ActionList deobfuscateActionList(List listeners, ActionList actions, int version, int ip, String path) throws IOException, InterruptedException { + if (actions.isEmpty()) { + return actions; + } + + Action lastAction = actions.get(actions.size() - 1); + int endIp = (int) lastAction.getAddress(); + + List retMap = new ArrayList<>(endIp); + for (int i = 0; i < endIp; i++) { + retMap.add(null); + } + List actionMap = new ArrayList<>(endIp); + for (int i = 0; i <= endIp; i++) { + actionMap.add(null); + } + for (Action a : actions) { + actionMap.set((int) a.getAddress(), a); + } + + int maxRecursionLevel = 0; + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionIf || a instanceof GraphSourceItemContainer) { + maxRecursionLevel++; + } + if (a instanceof ActionIf) { + ActionIf aif = (ActionIf) a; + aif.ignoreUsed = false; + aif.jumpUsed = false; + } + } + + deobfustaceActionListAtPosRecursive(listeners, + new ArrayList(), + new HashMap>(), + new ActionLocalData(), + new TranslateStack(), + new ConstantPool(), + actionMap, ip, retMap, ip, endIp, path, + new HashMap(), false, + new HashMap>(), + version, 0, maxRecursionLevel); + + ActionList ret = new ActionList(); + Action last = null; + for (Action a : retMap) { + if (a != last && a != null) { + ret.add(a); + } + last = a; + } + ret.removeNops(); + ActionList reta = new ActionList(); + for (Object o : ret) { + if (o instanceof Action) { + reta.add((Action) o); + } + } + return reta; + } + + private static long getNearAddress(ActionList actions, long address, boolean next) { + int min = 0; + int max = actions.size() - 1; + + while (max >= min) { + int mid = (min + max) / 2; + long midValue = actions.get(mid).getAddress(); + if (midValue == address) { + return address; + } else if (midValue < address) { + min = mid + 1; + } else { + max = mid - 1; + } + } + + return next + ? (min < actions.size() ? actions.get(min).getAddress() : -1) + : (max >= 0 ? actions.get(max).getAddress() : -1); + } + + private static Map actionListToMap(List actions) { + Map map = new HashMap<>(actions.size()); + for (Action a : actions) { + long address = a.getAddress(); + // There are multiple actions in the same address (2nd action is a jump for obfuscated code) + // So this check is required + if (!map.containsKey(address)) { + map.put(a.getAddress(), a); + } + } + return map; + } + + private static void getJumps(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (Action a : actions) { + long target = -1; + if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + target = aIf.getAddress() + a.getTotalActionLength() + aIf.getJumpOffset(); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + target = aJump.getAddress() + a.getTotalActionLength() + aJump.getJumpOffset(); + } else if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + int storeSize = aStore.getStoreSize(); + // skip storeSize + 1 actions (+1 is the current action) + Action targetAction = a; + for (int i = 0; i <= storeSize; i++) { + long address = targetAction.getAddress() + targetAction.getTotalActionLength(); + targetAction = actionMap.get(address); + if (targetAction == null) { + break; + } + } + jumps.put(a, targetAction); + } + if (target >= 0) { + Action targetAction = actionMap.get(target); + jumps.put(a, targetAction); + } + } + } + + public static List getContainerLastActions(ActionList actions, Action action) { + GraphSourceItemContainer container = (GraphSourceItemContainer) action; + List sizes = container.getContainerSizes(); + long endAddress = action.getAddress() + container.getHeaderSize(); + List lasts = new ArrayList<>(sizes.size()); + for (long size : sizes) { + endAddress += size; + long lastActionAddress = getNearAddress(actions, endAddress - 1, false); + Action lastAction = null; + if (lastActionAddress != -1) { + lastAction = actions.getByAddress(lastActionAddress); + } + lasts.add(lastAction); + } + return lasts; + } + + private static void getContainerLastActions(ActionList actions, Map> lastActions) { + for (Action a : actions) { + if (a instanceof GraphSourceItemContainer) { + lastActions.put(a, getContainerLastActions(actions, a)); + } + } + } + + private static long updateAddresses(List actions, long address) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + a.setAddress(address); + int length = a.getTotalActionLength(); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + // placeholder for jump action + length = new ActionDeobfuscateJump(0).getTotalActionLength(); + } + address += length; + } + return address; + } + + private static void updateActionLengths(List actions, int version) { + for (int i = 0; i < actions.size(); i++) { + actions.get(i).updateLength(version); + } + } + + private static void updateActionStores(List actions, Map jumps) { + Map actionMap = actionListToMap(actions); + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof ActionStore) { + ActionStore aStore = (ActionStore) a; + Action nextActionAfterStore = jumps.get(a); + Action a1 = a; + List store = new ArrayList<>(); + while (true) { + long address = a1.getAddress() + a1.getTotalActionLength(); + a1 = actionMap.get(address); + if (a1 == null || a1 == nextActionAfterStore) { + break; + } + store.add(a1); + } + aStore.setStore(store); + } + } + } + + private static void updateContainerSizes(List actions, Map> containerLastActions) { + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer container = (GraphSourceItemContainer) a; + List lastActions = containerLastActions.get(a); + long startAddress = a.getAddress() + container.getHeaderSize(); + for (int j = 0; j < lastActions.size(); j++) { + Action lastAction = lastActions.get(j); + int length = (int) (lastAction.getAddress() + lastAction.getTotalActionLength() - startAddress); + container.setContainerSize(j, length); + startAddress += length; + } + } + } + } + + private static void replaceJumpTargets(Map jumps, Action oldTarget, Action newTarget) { + for (Action a : jumps.keySet()) { + if (jumps.get(a) == oldTarget) { + jumps.put(a, newTarget); + } + } + } + + private static void replaceContainerLastActions(Map> containerLastActions, Action oldTarget, Action newTarget) { + for (Action a : containerLastActions.keySet()) { + List targets = containerLastActions.get(a); + for (int i = 0; i < targets.size(); i++) { + if (targets.get(i) == oldTarget) { + targets.set(i, newTarget); + } + } + } + } + + private static void updateJumps(List actions, Map jumps, Map> containerLastActions, long endAddress) { + if (actions.isEmpty()) { + return; + } + + for (int i = 0; i < actions.size(); i++) { + Action a = actions.get(i); + if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { + ActionJump aJump = new ActionDeobfuscateJump(0); + aJump.setJumpOffset((int) (endAddress - a.getAddress() - aJump.getTotalActionLength())); + aJump.setAddress(a.getAddress()); + replaceJumpTargets(jumps, a, aJump); + replaceContainerLastActions(containerLastActions, a, aJump); + a = aJump; + actions.set(i, a); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aIf.setJumpOffset((int) offset); + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + Action target = jumps.get(a); + long offset; + if (target != null) { + offset = target.getAddress() - a.getAddress() - a.getTotalActionLength(); + } else { + offset = endAddress - a.getAddress() - a.getTotalActionLength(); + } + aJump.setJumpOffset((int) offset); + } + } + } + + /** + * Removes an action from the action list, and updates all references This + * method will keep the inner actions of the container when you remove the + * container + * + * @param actions + * @param index + * @param version + * @param removeWhenLast + * @return + */ + public static boolean removeAction(ActionList actions, int index, int version, boolean removeWhenLast) { + + if (index < 0 || actions.size() <= index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + long endAddress = lastAction.getAddress() + lastAction.getTotalActionLength(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + getJumps(actions, jumps); + + Action prevAction = index > 0 ? actions.get(index - 1) : null; + Action nextAction = index + 1 < actions.size() ? actions.get(index + 1) : null; + Action actionToRemove = actions.get(index); + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == actionToRemove) { + if (!removeWhenLast) { + return false; + } + lastActions.set(i, prevAction); + } + } + } + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == actionToRemove) { + jumps.put(a, nextAction); + } + } + if (containerLastActions.containsKey(actionToRemove)) { + containerLastActions.remove(actionToRemove); + } + if (jumps.containsKey(actionToRemove)) { + jumps.remove(actionToRemove); + } + + actions.remove(index); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + /** + * Adds an action to the action list to the specified location, and updates + * all references + * + * @param actions + * @param index + * @param action + * @param version + * @param addToContainer + * @param replaceJump + * @return + */ + public static boolean addAction(ActionList actions, int index, Action action, + int version, boolean addToContainer, boolean replaceJump) { + + if (index < 0 || actions.size() < index) { + return false; + } + + long startIp = actions.get(0).getAddress(); + Action lastAction = actions.get(actions.size() - 1); + if (!(lastAction instanceof ActionEnd)) { + Action aEnd = new ActionEnd(); + aEnd.setAddress(lastAction.getAddress() + lastAction.getTotalActionLength()); + actions.add(aEnd); + lastAction = aEnd; + } + + long endAddress = lastAction.getAddress(); + + Map> containerLastActions = new HashMap<>(); + getContainerLastActions(actions, containerLastActions); + + Map jumps = new HashMap<>(); + List tempActions = new ArrayList<>(actions); + tempActions.add(action); + getJumps(tempActions, jumps); + + Action prevAction = actions.get(index); + if (addToContainer) { + for (Action a : containerLastActions.keySet()) { + List lastActions = containerLastActions.get(a); + for (int i = 0; i < lastActions.size(); i++) { + if (lastActions.get(i) == prevAction) { + lastActions.set(i, action); + } + } + } + } + + if (replaceJump) { + for (Action a : jumps.keySet()) { + Action targetAction = jumps.get(a); + if (targetAction == prevAction) { + jumps.put(a, action); + } + } + } + + actions.add(index, action); + + updateActionLengths(actions, version); + updateAddresses(actions, startIp); + updateJumps(actions, jumps, containerLastActions, endAddress); + updateActionStores(actions, jumps); + updateContainerSizes(actions, containerLastActions); + + return true; + } + + private static Action readActionListAtPos(List listeners, ConstantPool cpool, + SWFInputStream sis, Map actions, Map nextOffsets, + long ip, long startIp, long endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { + + Action entryAction = null; + + if (visitedContainers.contains(ip)) { + return null; + } + visitedContainers.add(ip); + + Queue jumpQueue = new LinkedList<>(); + jumpQueue.add(ip); + while (!jumpQueue.isEmpty()) { + ip = jumpQueue.remove(); + if (ip < startIp) { + continue; + } + + while (endIp == -1 || endIp > ip) { + sis.seek((int) ip); + + Action a; + if ((a = sis.readAction()) == null) { + break; + } + + int actionLengthWithHeader = a.getTotalActionLength(); + + // unknown action, replace with jump + if (a instanceof ActionNop) { + ActionJump aJump = new ActionDeobfuscateJump(0); + int jumpLength = aJump.getTotalActionLength(); + aJump.setAddress(a.getAddress()); + aJump.setJumpOffset(actionLengthWithHeader - jumpLength); + a = aJump; + actionLengthWithHeader = a.getTotalActionLength(); + } + + if (entryAction == null) { + entryAction = a; + } + + Action existingAction = actions.get(ip); + if (existingAction != null) { + break; + } + + actions.put(ip, a); + nextOffsets.put(ip, ip + actionLengthWithHeader); + + long pos = sis.getPos(); + long length = pos + sis.available(); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressReading(pos, length); + } + + a.setAddress(ip); + + if (a instanceof ActionPush && cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } else if (a instanceof ActionConstantPool) { + cpool = new ConstantPool(((ActionConstantPool) a).constantPool); + } else if (a instanceof ActionIf) { + ActionIf aIf = (ActionIf) a; + long nIp = ip + actionLengthWithHeader + aIf.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + } else if (a instanceof ActionJump) { + ActionJump aJump = (ActionJump) a; + long nIp = ip + actionLengthWithHeader + aJump.getJumpOffset(); + if (nIp >= 0) { + jumpQueue.add(nIp); + } + break; + } else if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + String cntName = cnt.getName(); + String newPath = path + (cntName == null ? "" : "/" + cntName); + for (long size : cnt.getContainerSizes()) { + if (size != 0) { + long ip2 = ip + actionLengthWithHeader; + long endIp2 = ip + actionLengthWithHeader + size; + readActionListAtPos(listeners, cpool, + sis, actions, nextOffsets, + ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); + actionLengthWithHeader += size; + } + } + } + + ip += actionLengthWithHeader; + + if (a.isExit()) { + break; + } + } + } + return entryAction; + } + + private static void deobfustaceActionListAtPosRecursive(List listeners, List output, HashMap> containers, ActionLocalData localData, TranslateStack stack, ConstantPool cpool, List actions, int ip, List ret, int startIp, int endip, String path, Map visited, boolean indeterminate, Map> decisionStates, int version, int recursionLevel, int maxRecursionLevel) throws IOException, InterruptedException { + boolean debugMode = false; + boolean decideBranch = false; + + if (recursionLevel > maxRecursionLevel + 1) { + throw new TranslateException("deobfustaceActionListAtPosRecursive max recursion level reached."); + } + + Action a; + Scanner sc = null; + loopip: + while (((endip == -1) || (endip > ip)) && (a = actions.get(ip)) != null) { + if (Thread.currentThread().isInterrupted()) { + throw new InterruptedException(); + } + + int actionLen = a.getTotalActionLength(); + if (!visited.containsKey(ip)) { + visited.put(ip, 0); + } + int curVisited = visited.get(ip); + curVisited++; + visited.put(ip, curVisited); + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).progressDeobfuscating(ip, actions.size()); + } + int info = a.getTotalActionLength(); + + if (a instanceof ActionPush) { + if (cpool != null) { + ((ActionPush) a).constantPool = cpool.constants; + } + } + + if (debugMode) { + String atos = a.getASMSource(new ActionList(), new HashSet(), ScriptExportMode.PCODE); + if (a instanceof GraphSourceItemContainer) { + atos = a.toString(); + } + System.err.println("readActionListAtPos ip: " + (ip - startIp) + " (0x" + Helper.formatAddress(ip - startIp) + ") " + " action(len " + a.actionLength + "): " + atos + (a.isIgnored() ? " (ignored)" : "") + " stack:" + Helper.stackToString(stack, LocalData.create(cpool)) + " " + Helper.byteArrToString(a.getBytes(version))); + System.err.print("variables: "); + for (Map.Entry v : localData.variables.entrySet()) { + System.err.print("'" + v + "' = " + v.getValue().toString(LocalData.create(cpool)) + ", "); + } + System.err.println(); + String add = ""; + if (a instanceof ActionIf) { + add = " change: " + ((ActionIf) a).getJumpOffset(); + } + if (a instanceof ActionJump) { + add = " change: " + ((ActionJump) a).getJumpOffset(); + } + System.err.println(add); + } + + int newip = -1; + + if (a instanceof ActionConstantPool) { + if (cpool == null) { + cpool = new ConstantPool(); + } + cpool.setNew(((ActionConstantPool) a).constantPool); + } + ActionIf aif = null; + boolean goaif = false; + if (!a.isIgnored()) { + String varname = null; + if (a instanceof StoreTypeAction) { + StoreTypeAction sta = (StoreTypeAction) a; + varname = sta.getVariableName(stack, cpool); + } + + try { + if (a instanceof ActionIf) { + aif = (ActionIf) a; + + GraphTargetItem top = stack.pop(); + int nip = ip + actionLen + aif.getJumpOffset(); + + if (decideBranch) { + System.out.print("newip " + nip + ", "); + System.out.print("Action: jump(j),ignore(i),compute(c)?"); + if (sc == null) { + sc = new Scanner(System.in); + } + String next = sc.next(); + switch (next) { + case "j": + newip = nip; + break; + case "i": + break; + case "c": + goaif = true; + break; + } + } else if (top.isCompileTime() && (!top.hasSideEffect())) { + if (debugMode) { + System.err.print("is compiletime -> "); + } + if (EcmaScript.toBoolean(top.getResult())) { + newip = nip; + aif.jumpUsed = true; + if (debugMode) { + System.err.println("jump"); + } + } else { + aif.ignoreUsed = true; + if (debugMode) { + System.err.println("ignore"); + } + } + } else { + if (debugMode) { + System.err.println("goaif"); + } + goaif = true; + } + } else if (a instanceof ActionJump) { + newip = ip + actionLen + ((ActionJump) a).getJumpOffset(); + } else if (!(a instanceof GraphSourceItemContainer)) { + //return in for..in, TODO:Handle this better way + if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueActionItem)) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); + } + if ((a instanceof ActionStoreRegister) && stack.isEmpty()) { + stack.push(new DirectValueActionItem(null, 0, new Null(), new ArrayList<>())); + } + a.translate(localData, stack, output, Graph.SOP_USE_STATIC/*Graph.SOP_SKIP_STATIC*/, path); + } + } catch (RuntimeException ex) { + logger.log(Level.SEVERE, "Disassembly exception", ex); + break; + } + + HashMap vars = localData.variables; + if (varname != null) { + GraphTargetItem varval = vars.get(varname); + if (varval != null && varval.isCompileTime() && indeterminate) { + vars.put(varname, new NotCompileTimeItem(null, varval)); + } + } + } + for (int i = 0; i < actionLen; i++) { + ret.set(ip + i, a); + } + + if (a instanceof GraphSourceItemContainer) { + GraphSourceItemContainer cnt = (GraphSourceItemContainer) a; + if (a instanceof Action) { + long endAddr = a.getAddress() + cnt.getHeaderSize(); + String cntName = cnt.getName(); + List> output2s = new ArrayList<>(); + for (long size : cnt.getContainerSizes()) { + if (size == 0) { + output2s.add(new ArrayList()); + continue; + } + ActionLocalData localData2; + List output2 = new ArrayList<>(); + if ((cnt instanceof ActionDefineFunction) || (cnt instanceof ActionDefineFunction2)) { + localData2 = new ActionLocalData(); + } else { + localData2 = localData; + } + deobfustaceActionListAtPosRecursive(listeners, output2, containers, localData2, new TranslateStack(), cpool, actions, (int) endAddr, ret, startIp, (int) (endAddr + size), path + (cntName == null ? "" : "/" + cntName), visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + output2s.add(output2); + endAddr += size; + } + cnt.translateContainer(output2s, stack, output, localData.regNames, localData.variables, localData.functions); + ip = (int) endAddr; + continue; + } + } + + if (a instanceof ActionEnd) { + break; + } + if (goaif) { + aif.ignoreUsed = true; + aif.jumpUsed = true; + indeterminate = true; + + HashMap vars = localData.variables; + boolean stateChanged = false; + if (decisionStates.containsKey(ip)) { + HashMap oldstate = decisionStates.get(ip); + if (oldstate.size() != vars.size()) { + stateChanged = true; + } else { + for (String k : vars.keySet()) { + if (!oldstate.containsKey(k)) { + stateChanged = true; + break; + } + if (!vars.get(k).isCompileTime() && oldstate.get(k).isCompileTime()) { + stateChanged = true; + break; + } + } + } + } + HashMap curstate = new HashMap<>(); + curstate.putAll(vars); + decisionStates.put(ip, curstate); + + if ((!stateChanged) && curVisited > 1) { + List branches = new ArrayList<>(); + branches.add(ip + actionLen + aif.getJumpOffset()); + branches.add(ip + actionLen); + for (int br : branches) { + int visc = 0; + if (visited.containsKey(br)) { + visc = visited.get(br); + } + if (visc == 0) {//(localData.regNames), + new HashMap<>(localData.variables), new HashMap<>(localData.functions)); + deobfustaceActionListAtPosRecursive(listeners, output, containers, subLocalData, subStack, cpool, actions, ip + actionLen + aif.getJumpOffset(), ret, startIp, endip, path, visited, indeterminate, decisionStates, version, recursionLevel + 1, maxRecursionLevel); + } + + if (newip > -1) { + ip = newip; + } else { + ip += info; + } + + if (a.isExit()) { + break; + } + } + for (DisassemblyListener listener : listeners) { + listener.progressDeobfuscating(ip, actions.size()); + } + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java index 5b4829b53..10ab11c00 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java @@ -1,339 +1,339 @@ -/* - * Copyright (C) 2010-2015 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.model; - -import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemPos; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class FunctionActionItem extends ActionItem { - - public List actions; - - public List constants; - - public String functionName; - - public List paramNames; - - public GraphTargetItem calculatedFunctionName; - - private int regStart; - - private List variables; - - public static final int REGISTER_THIS = 1; - - public static final int REGISTER_ARGUMENTS = 2; - - public static final int REGISTER_SUPER = 3; - - public static final int REGISTER_ROOT = 4; - - public static final int REGISTER_PARENT = 5; - - public static final int REGISTER_GLOBAL = 6; - - @Override - public List getAllSubItems() { - List ret = new ArrayList<>(); - ret.addAll(actions); - return ret; - } - - public FunctionActionItem() { - super(null, PRECEDENCE_PRIMARY); - } - - public FunctionActionItem(GraphSourceItem instruction, String functionName, List paramNames, List actions, List constants, int regStart, List variables) { - super(instruction, PRECEDENCE_PRIMARY); - this.actions = actions; - this.constants = constants; - this.functionName = functionName; - this.paramNames = paramNames; - this.regStart = regStart; - this.variables = variables; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - writer.append("function"); - if (calculatedFunctionName != null) { - writer.append(" "); - String fname = calculatedFunctionName.toStringNoQuotes(localData); - if (!IdentifiersDeobfuscation.isValidName(false, fname)) { - writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(fname)); - } else { - calculatedFunctionName.appendToNoQuotes(writer, localData); - } - } else if (!functionName.isEmpty()) { - writer.append(" "); - if (!IdentifiersDeobfuscation.isValidName(false, functionName)) { - writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(functionName)); - } else { - writer.append(functionName); - } - } - writer.spaceBeforeCallParenthesies(paramNames.size()); - writer.append("("); - - for (int p = 0; p < paramNames.size(); p++) { - if (p > 0) { - writer.append(", "); - } - String pname = paramNames.get(p); - if (pname == null || pname.isEmpty()) { - pname = new RegisterNumber(regStart + p).translate(); - } - if (!IdentifiersDeobfuscation.isValidName(false, pname)) { - writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(pname)); - } - writer.append(pname); - } - writer.append(")").startBlock(); - - Graph.graphToString(actions, writer, localData); - - return writer.endBlock(); - } - - @Override - public List getNeededSources() { - List ret = super.getNeededSources(); - for (GraphTargetItem ti : actions) { - ret.addAll(ti.getNeededSources()); - } - return ret; - } - - @Override - public boolean needsSemicolon() { - return false; - } - - @Override - public boolean isCompileTime(Set dependencies) { - for (GraphTargetItem a : actions) { - if (dependencies.contains(a)) { - return false; - } - dependencies.add(a); - if (!a.isCompileTime(dependencies)) { - return false; - } - } - return true; - } - - @Override - public Object getResult() { - if (!actions.isEmpty()) { - if (actions.get(actions.size() - 1) instanceof ReturnActionItem) { - ReturnActionItem r = (ReturnActionItem) actions.get(actions.size() - 1); - return r.value.getResult(); - } - } - return 0; - } - - @Override - public boolean needsNewLine() { - return true; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - - Set usedNames = new HashSet<>(); - for (VariableActionItem v : variables) { - usedNames.add(v.getVariableName()); - } - - List ret = new ArrayList<>(); - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - List paramRegs = new ArrayList<>(); - SourceGeneratorLocalData localDataCopy = Helper.deepCopy(localData); - localDataCopy.inFunction++; - boolean preloadParentFlag = false; - boolean preloadRootFlag = false; - boolean preloadSuperFlag = false; - boolean preloadArgumentsFlag = false; - boolean preloadThisFlag = false; - boolean preloadGlobalFlag = false; - - boolean suppressParentFlag = false; - boolean suppressArgumentsFlag = false; - boolean suppressThisFlag = false; - - boolean needsFun2 = false; - - List registerNames = new ArrayList<>(); - registerNames.add("***** ZERO *****"); - if (usedNames.contains("this")) { - needsFun2 = true; - preloadThisFlag = true; - registerNames.add("this"); - } else { - suppressThisFlag = true; - } - if (usedNames.contains("arguments")) { - preloadArgumentsFlag = true; - needsFun2 = true; - registerNames.add("arguments"); - } else { - suppressArgumentsFlag = true; - } - if (usedNames.contains("super")) { - preloadSuperFlag = true; - needsFun2 = true; - registerNames.add("super"); - } - if (usedNames.contains("_root")) { - preloadRootFlag = true; - needsFun2 = true; - registerNames.add("_root"); - } - if (usedNames.contains("_parent")) { - preloadParentFlag = true; - needsFun2 = true; - registerNames.add("_parent"); - } else { - suppressParentFlag = true; - } - if (usedNames.contains("_global")) { - needsFun2 = true; - preloadGlobalFlag = true; - registerNames.add("_global"); - } - - int preloadedNumber = registerNames.size(); - if (!paramNames.isEmpty()) { - needsFun2 = true; - } - if (localData.inMethod) { - needsFun2 = true; - } - if (localData.inFunction > 1) { - needsFun2 = true; - } - if (needsFun2) { - for (int i = 0; i < paramNames.size(); i++) { - paramRegs.add(registerNames.size()); - registerNames.add(paramNames.get(i)); - } - } - - int regCount = 0; - if (actions != null && !actions.isEmpty()) { - localDataCopy.inFunction++; - - for (VariableActionItem v : variables) { - String varName = v.getVariableName(); - GraphTargetItem stored = v.getStoreValue(); - if (needsFun2) { - if (v.isDefinition() && !registerNames.contains(varName)) { - registerNames.add(varName); - } - } - - if (registerNames.contains(varName)) { - if (stored != null) { - v.setBoxedValue(new StoreRegisterActionItem(null, new RegisterNumber(registerNames.indexOf(varName), varName), stored, false)); - } else { - v.setBoxedValue(new DirectValueActionItem(new RegisterNumber(registerNames.indexOf(varName), varName))); - } - } else { - if (v.isDefinition()) { - v.setBoxedValue(new DefineLocalActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored)); - } else { - if (stored != null) { - v.setBoxedValue(new SetVariableActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored)); - } else { - v.setBoxedValue(new GetVariableActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName))); - } - } - } - - } - for (int i = 1 /* zero is not preloaded*/; i < registerNames.size(); i++) { - localDataCopy.registerVars.put(registerNames.get(i), i); - } - - ret.addAll(asGenerator.toActionList(asGenerator.generate(localDataCopy, actions))); - - regCount = registerNames.size(); - - //some temporary registers can exceed variable+param count - for (GraphSourceItem a : ret) { - if (a instanceof ActionPush) { - ActionPush apu = (ActionPush) a; - for (Object o : apu.values) { - if (o instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) o; - if (rn.number >= regCount) { - regCount++; - } - } - } - } - } - } - int len = Action.actionsToBytes(asGenerator.toActionList(ret), false, SWF.DEFAULT_VERSION).length; - if (!needsFun2 && paramNames.isEmpty()) { - ret.add(0, new ActionDefineFunction(functionName, paramNames, len, SWF.DEFAULT_VERSION)); - } else { - ret.add(0, new ActionDefineFunction2(functionName, - preloadParentFlag, - preloadRootFlag, - suppressParentFlag, - preloadSuperFlag, - suppressArgumentsFlag, - preloadArgumentsFlag, - suppressThisFlag, - preloadThisFlag, - preloadGlobalFlag, - regCount, len, SWF.DEFAULT_VERSION, paramNames, paramRegs)); - } - - return ret; - } - - @Override - public boolean hasReturnValue() { - return false; //function actually returns itself, but here is false for generator to not add Pop - } -} +/* + * Copyright (C) 2010-2015 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.model; + +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; +import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.Graph; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemPos; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.LocalData; +import com.jpexs.helpers.Helper; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class FunctionActionItem extends ActionItem { + + public List actions; + + public List constants; + + public String functionName; + + public List paramNames; + + public GraphTargetItem calculatedFunctionName; + + private int regStart; + + private List variables; + + public static final int REGISTER_THIS = 1; + + public static final int REGISTER_ARGUMENTS = 2; + + public static final int REGISTER_SUPER = 3; + + public static final int REGISTER_ROOT = 4; + + public static final int REGISTER_PARENT = 5; + + public static final int REGISTER_GLOBAL = 6; + + @Override + public List getAllSubItems() { + List ret = new ArrayList<>(); + ret.addAll(actions); + return ret; + } + + public FunctionActionItem() { + super(null, PRECEDENCE_PRIMARY); + } + + public FunctionActionItem(GraphSourceItem instruction, String functionName, List paramNames, List actions, List constants, int regStart, List variables) { + super(instruction, PRECEDENCE_PRIMARY); + this.actions = actions; + this.constants = constants; + this.functionName = functionName; + this.paramNames = paramNames; + this.regStart = regStart; + this.variables = variables; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + writer.append("function"); + if (calculatedFunctionName != null) { + writer.append(" "); + String fname = calculatedFunctionName.toStringNoQuotes(localData); + if (!IdentifiersDeobfuscation.isValidName(false, fname)) { + writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(fname)); + } else { + calculatedFunctionName.appendToNoQuotes(writer, localData); + } + } else if (!functionName.isEmpty()) { + writer.append(" "); + if (!IdentifiersDeobfuscation.isValidName(false, functionName)) { + writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(functionName)); + } else { + writer.append(functionName); + } + } + writer.spaceBeforeCallParenthesies(paramNames.size()); + writer.append("("); + + for (int p = 0; p < paramNames.size(); p++) { + if (p > 0) { + writer.append(", "); + } + String pname = paramNames.get(p); + if (pname == null || pname.isEmpty()) { + pname = new RegisterNumber(regStart + p).translate(); + } + if (!IdentifiersDeobfuscation.isValidName(false, pname)) { + writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(pname)); + } + writer.append(pname); + } + writer.append(")").startBlock(); + + Graph.graphToString(actions, writer, localData); + + return writer.endBlock(); + } + + @Override + public List getNeededSources() { + List ret = super.getNeededSources(); + for (GraphTargetItem ti : actions) { + ret.addAll(ti.getNeededSources()); + } + return ret; + } + + @Override + public boolean needsSemicolon() { + return false; + } + + @Override + public boolean isCompileTime(Set dependencies) { + for (GraphTargetItem a : actions) { + if (dependencies.contains(a)) { + return false; + } + dependencies.add(a); + if (!a.isCompileTime(dependencies)) { + return false; + } + } + return true; + } + + @Override + public Object getResult() { + if (!actions.isEmpty()) { + if (actions.get(actions.size() - 1) instanceof ReturnActionItem) { + ReturnActionItem r = (ReturnActionItem) actions.get(actions.size() - 1); + return r.value.getResult(); + } + } + return 0; + } + + @Override + public boolean needsNewLine() { + return true; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + + Set usedNames = new HashSet<>(); + for (VariableActionItem v : variables) { + usedNames.add(v.getVariableName()); + } + + List ret = new ArrayList<>(); + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + List paramRegs = new ArrayList<>(); + SourceGeneratorLocalData localDataCopy = Helper.deepCopy(localData); + localDataCopy.inFunction++; + boolean preloadParentFlag = false; + boolean preloadRootFlag = false; + boolean preloadSuperFlag = false; + boolean preloadArgumentsFlag = false; + boolean preloadThisFlag = false; + boolean preloadGlobalFlag = false; + + boolean suppressParentFlag = false; + boolean suppressArgumentsFlag = false; + boolean suppressThisFlag = false; + + boolean needsFun2 = false; + + List registerNames = new ArrayList<>(); + registerNames.add("***** ZERO *****"); + if (usedNames.contains("this")) { + needsFun2 = true; + preloadThisFlag = true; + registerNames.add("this"); + } else { + suppressThisFlag = true; + } + if (usedNames.contains("arguments")) { + preloadArgumentsFlag = true; + needsFun2 = true; + registerNames.add("arguments"); + } else { + suppressArgumentsFlag = true; + } + if (usedNames.contains("super")) { + preloadSuperFlag = true; + needsFun2 = true; + registerNames.add("super"); + } + if (usedNames.contains("_root")) { + preloadRootFlag = true; + needsFun2 = true; + registerNames.add("_root"); + } + if (usedNames.contains("_parent")) { + preloadParentFlag = true; + needsFun2 = true; + registerNames.add("_parent"); + } else { + suppressParentFlag = true; + } + if (usedNames.contains("_global")) { + needsFun2 = true; + preloadGlobalFlag = true; + registerNames.add("_global"); + } + + int preloadedNumber = registerNames.size(); + if (!paramNames.isEmpty()) { + needsFun2 = true; + } + if (localData.inMethod) { + needsFun2 = true; + } + if (localData.inFunction > 1) { + needsFun2 = true; + } + if (needsFun2) { + for (int i = 0; i < paramNames.size(); i++) { + paramRegs.add(registerNames.size()); + registerNames.add(paramNames.get(i)); + } + } + + int regCount = 0; + if (actions != null && !actions.isEmpty()) { + localDataCopy.inFunction++; + + for (VariableActionItem v : variables) { + String varName = v.getVariableName(); + GraphTargetItem stored = v.getStoreValue(); + if (needsFun2) { + if (v.isDefinition() && !registerNames.contains(varName)) { + registerNames.add(varName); + } + } + + if (registerNames.contains(varName)) { + if (stored != null) { + v.setBoxedValue(new StoreRegisterActionItem(null, new RegisterNumber(registerNames.indexOf(varName), varName), stored, false)); + } else { + v.setBoxedValue(new DirectValueActionItem(new RegisterNumber(registerNames.indexOf(varName), varName))); + } + } else { + if (v.isDefinition()) { + v.setBoxedValue(new DefineLocalActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored)); + } else { + if (stored != null) { + v.setBoxedValue(new SetVariableActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName), stored)); + } else { + v.setBoxedValue(new GetVariableActionItem(null, ((ActionSourceGenerator) generator).pushConstTargetItem(varName))); + } + } + } + + } + for (int i = 1 /* zero is not preloaded*/; i < registerNames.size(); i++) { + localDataCopy.registerVars.put(registerNames.get(i), i); + } + + ret.addAll(asGenerator.toActionList(asGenerator.generate(localDataCopy, actions))); + + regCount = registerNames.size(); + + //some temporary registers can exceed variable+param count + for (GraphSourceItem a : ret) { + if (a instanceof ActionPush) { + ActionPush apu = (ActionPush) a; + for (Object o : apu.values) { + if (o instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) o; + if (rn.number >= regCount) { + regCount++; + } + } + } + } + } + } + int len = Action.actionsToBytes(asGenerator.toActionList(ret), false, SWF.DEFAULT_VERSION).length; + if (!needsFun2 && paramNames.isEmpty()) { + ret.add(0, new ActionDefineFunction(functionName, paramNames, len, SWF.DEFAULT_VERSION)); + } else { + ret.add(0, new ActionDefineFunction2(functionName, + preloadParentFlag, + preloadRootFlag, + suppressParentFlag, + preloadSuperFlag, + suppressArgumentsFlag, + preloadArgumentsFlag, + suppressThisFlag, + preloadThisFlag, + preloadGlobalFlag, + regCount, len, SWF.DEFAULT_VERSION, paramNames, paramRegs)); + } + + return ret; + } + + @Override + public boolean hasReturnValue() { + return false; //function actually returns itself, but here is false for generator to not add Pop + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java index 29e9bd47d..653e30b70 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetMemberActionItem.java @@ -1,142 +1,142 @@ -/* - * Copyright (C) 2010-2015 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.model; - -import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemPos; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.LocalData; -import java.util.ArrayList; -import java.util.List; - -public class SetMemberActionItem extends ActionItem implements SetTypeActionItem { - - public GraphTargetItem object; - - public GraphTargetItem objectName; - - //public GraphTargetItem value; - private int tempRegister = -1; - - @Override - public List getAllSubItems() { - List ret = new ArrayList<>(); - ret.add(object); - ret.add(value); - return ret; - } - - @Override - public GraphPart getFirstPart() { - return value.getFirstPart(); - } - - @Override - public void setValue(GraphTargetItem value) { - this.value = value; - } - - @Override - public int getTempRegister() { - return tempRegister; - } - - @Override - public void setTempRegister(int tempRegister) { - this.tempRegister = tempRegister; - } - - @Override - public GraphTargetItem getValue() { - return value; - } - - public SetMemberActionItem(GraphSourceItem instruction, GraphTargetItem object, GraphTargetItem objectName, GraphTargetItem value) { - super(instruction, PRECEDENCE_ASSIGMENT); - this.object = object; - this.objectName = objectName; - this.value = value; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - object.toString(writer, localData); - - if ((!(objectName instanceof DirectValueActionItem)) || (!((DirectValueActionItem) objectName).isString()) || (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) objectName).toStringNoQuotes(localData)))) { - writer.append("["); - objectName.toString(writer, localData); - writer.append("]"); - } else { - writer.append("."); - stripQuotes(objectName, localData, writer); - } - writer.append(" = "); - return value.toString(writer, localData); - - } - - @Override - public GraphTargetItem getObject() { - return new GetMemberActionItem(src, object, objectName); - } - - @Override - public List getNeededSources() { - List ret = super.getNeededSources(); - ret.addAll(object.getNeededSources()); - ret.addAll(objectName.getNeededSources()); - ret.addAll(value.getNeededSources()); - return ret; - } - - @Override - public boolean hasSideEffect() { - return true; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - int tmpReg = asGenerator.getTempRegister(localData); - try { - return toSourceMerge(localData, generator, object, objectName, value, new ActionStoreRegister(tmpReg), new ActionSetMember(), new ActionPush(new RegisterNumber(tmpReg))); - } finally { - asGenerator.releaseTempRegister(localData, tmpReg); - } - } - - @Override - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - return toSourceMerge(localData, generator, object, objectName, value, new ActionSetMember()); - } - - @Override - public boolean hasReturnValue() { - return false; - } -} +/* + * Copyright (C) 2010-2015 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.model; + +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemPos; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.LocalData; +import java.util.ArrayList; +import java.util.List; + +public class SetMemberActionItem extends ActionItem implements SetTypeActionItem { + + public GraphTargetItem object; + + public GraphTargetItem objectName; + + //public GraphTargetItem value; + private int tempRegister = -1; + + @Override + public List getAllSubItems() { + List ret = new ArrayList<>(); + ret.add(object); + ret.add(value); + return ret; + } + + @Override + public GraphPart getFirstPart() { + return value.getFirstPart(); + } + + @Override + public void setValue(GraphTargetItem value) { + this.value = value; + } + + @Override + public int getTempRegister() { + return tempRegister; + } + + @Override + public void setTempRegister(int tempRegister) { + this.tempRegister = tempRegister; + } + + @Override + public GraphTargetItem getValue() { + return value; + } + + public SetMemberActionItem(GraphSourceItem instruction, GraphTargetItem object, GraphTargetItem objectName, GraphTargetItem value) { + super(instruction, PRECEDENCE_ASSIGMENT); + this.object = object; + this.objectName = objectName; + this.value = value; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + object.toString(writer, localData); + + if ((!(objectName instanceof DirectValueActionItem)) || (!((DirectValueActionItem) objectName).isString()) || (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) objectName).toStringNoQuotes(localData)))) { + writer.append("["); + objectName.toString(writer, localData); + writer.append("]"); + } else { + writer.append("."); + stripQuotes(objectName, localData, writer); + } + writer.append(" = "); + return value.toString(writer, localData); + + } + + @Override + public GraphTargetItem getObject() { + return new GetMemberActionItem(src, object, objectName); + } + + @Override + public List getNeededSources() { + List ret = super.getNeededSources(); + ret.addAll(object.getNeededSources()); + ret.addAll(objectName.getNeededSources()); + ret.addAll(value.getNeededSources()); + return ret; + } + + @Override + public boolean hasSideEffect() { + return true; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + int tmpReg = asGenerator.getTempRegister(localData); + try { + return toSourceMerge(localData, generator, object, objectName, value, new ActionStoreRegister(tmpReg), new ActionSetMember(), new ActionPush(new RegisterNumber(tmpReg))); + } finally { + asGenerator.releaseTempRegister(localData, tmpReg); + } + } + + @Override + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return toSourceMerge(localData, generator, object, objectName, value, new ActionSetMember()); + } + + @Override + public boolean hasReturnValue() { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetPropertyActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetPropertyActionItem.java index 5aea831b5..320dc546a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetPropertyActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetPropertyActionItem.java @@ -1,126 +1,126 @@ -/* - * Copyright (C) 2010-2015 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.model; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemPos; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.LocalData; -import java.util.List; - -public class SetPropertyActionItem extends ActionItem implements SetTypeActionItem { - - public GraphTargetItem target; - - public int propertyIndex; - //public GraphTargetItem value; - - @Override - public GraphPart getFirstPart() { - return value.getFirstPart(); - } - - @Override - public void setValue(GraphTargetItem value) { - this.value = value; - } - - private int tempRegister = -1; - - @Override - public int getTempRegister() { - return tempRegister; - } - - @Override - public void setTempRegister(int tempRegister) { - this.tempRegister = tempRegister; - } - - @Override - public GraphTargetItem getValue() { - return value; - } - - public SetPropertyActionItem(GraphSourceItem instruction, GraphTargetItem target, int propertyIndex, GraphTargetItem value) { - super(instruction, PRECEDENCE_ASSIGMENT); - this.target = target; - this.propertyIndex = propertyIndex; - this.value = value; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - if (isEmptyString(target)) { - writer.append(Action.propertyNames[propertyIndex] + " = "); - return value.toString(writer, localData); - } - target.toString(writer, localData); - writer.append("." + Action.propertyNames[propertyIndex] + " = "); - return value.toString(writer, localData); - } - - @Override - public GraphTargetItem getObject() { - return new GetPropertyActionItem(src, target, propertyIndex); - } - - @Override - public List getNeededSources() { - List ret = super.getNeededSources(); - ret.addAll(target.getNeededSources()); - ret.addAll(value.getNeededSources()); - return ret; - } - - @Override - public boolean hasSideEffect() { - return true; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - int tmpReg = asGenerator.getTempRegister(localData); - try { - return toSourceMerge(localData, generator, target, new ActionPush((Long) (long) propertyIndex), value, new ActionStoreRegister(tmpReg), new ActionSetProperty(), new ActionPush(new RegisterNumber(tmpReg))); - } finally { - asGenerator.releaseTempRegister(localData, tmpReg); - } - } - - @Override - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - return toSourceMerge(localData, generator, target, new ActionPush((Long) (long) propertyIndex), value, new ActionSetProperty()); - } - - @Override - public boolean hasReturnValue() { - return false; - } -} +/* + * Copyright (C) 2010-2015 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.model; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemPos; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; + +public class SetPropertyActionItem extends ActionItem implements SetTypeActionItem { + + public GraphTargetItem target; + + public int propertyIndex; + //public GraphTargetItem value; + + @Override + public GraphPart getFirstPart() { + return value.getFirstPart(); + } + + @Override + public void setValue(GraphTargetItem value) { + this.value = value; + } + + private int tempRegister = -1; + + @Override + public int getTempRegister() { + return tempRegister; + } + + @Override + public void setTempRegister(int tempRegister) { + this.tempRegister = tempRegister; + } + + @Override + public GraphTargetItem getValue() { + return value; + } + + public SetPropertyActionItem(GraphSourceItem instruction, GraphTargetItem target, int propertyIndex, GraphTargetItem value) { + super(instruction, PRECEDENCE_ASSIGMENT); + this.target = target; + this.propertyIndex = propertyIndex; + this.value = value; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + if (isEmptyString(target)) { + writer.append(Action.propertyNames[propertyIndex] + " = "); + return value.toString(writer, localData); + } + target.toString(writer, localData); + writer.append("." + Action.propertyNames[propertyIndex] + " = "); + return value.toString(writer, localData); + } + + @Override + public GraphTargetItem getObject() { + return new GetPropertyActionItem(src, target, propertyIndex); + } + + @Override + public List getNeededSources() { + List ret = super.getNeededSources(); + ret.addAll(target.getNeededSources()); + ret.addAll(value.getNeededSources()); + return ret; + } + + @Override + public boolean hasSideEffect() { + return true; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + int tmpReg = asGenerator.getTempRegister(localData); + try { + return toSourceMerge(localData, generator, target, new ActionPush((Long) (long) propertyIndex), value, new ActionStoreRegister(tmpReg), new ActionSetProperty(), new ActionPush(new RegisterNumber(tmpReg))); + } finally { + asGenerator.releaseTempRegister(localData, tmpReg); + } + } + + @Override + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return toSourceMerge(localData, generator, target, new ActionPush((Long) (long) propertyIndex), value, new ActionSetProperty()); + } + + @Override + public boolean hasReturnValue() { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java index 7913d0582..2737e1ca8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/SetVariableActionItem.java @@ -1,142 +1,142 @@ -/* - * Copyright (C) 2010-2015 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.model; - -import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemPos; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.LocalData; -import java.util.List; -import java.util.Set; - -public class SetVariableActionItem extends ActionItem implements SetTypeActionItem { - - public GraphTargetItem name; - - //public GraphTargetItem value; - private int tempRegister = -1; - - @Override - public GraphPart getFirstPart() { - return value.getFirstPart(); - } - - @Override - public void setValue(GraphTargetItem value) { - this.value = value; - } - - @Override - public int getTempRegister() { - return tempRegister; - } - - @Override - public void setTempRegister(int tempRegister) { - this.tempRegister = tempRegister; - } - - @Override - public GraphTargetItem getValue() { - return value; - } - - public SetVariableActionItem(GraphSourceItem instruction, GraphTargetItem name, GraphTargetItem value) { - super(instruction, PRECEDENCE_ASSIGMENT); - this.name = name; - this.value = value; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) { - writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData))); - writer.append(" = "); - return value.toString(writer, localData); - } else if ((!(name instanceof DirectValueActionItem)) || (!((DirectValueActionItem) name).isString())) { - writer.append("set"); - writer.spaceBeforeCallParenthesies(2); - writer.append("("); - name.toString(writer, localData); - writer.append(","); - value.toString(writer, localData); - return writer.append(")"); - } - stripQuotes(name, localData, writer); - writer.append(" = "); - return value.toString(writer, localData); - } - - @Override - public GraphTargetItem getObject() { - return new GetVariableActionItem(src, name); - } - - @Override - public List getNeededSources() { - List ret = super.getNeededSources(); - ret.addAll(name.getNeededSources()); - ret.addAll(value.getNeededSources()); - return ret; - } - - @Override - public boolean isCompileTime(Set dependencies) { - if (dependencies.contains(value)) { - return false; - } - dependencies.add(value); - return value.isCompileTime(dependencies); - } - - @Override - public boolean hasSideEffect() { - return true; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - int tmpReg = asGenerator.getTempRegister(localData); - try { - return toSourceMerge(localData, generator, name, value, new ActionStoreRegister(tmpReg), new ActionSetVariable(), new ActionPush(new RegisterNumber(tmpReg))); - } finally { - asGenerator.releaseTempRegister(localData, tmpReg); - } - } - - @Override - public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - return toSourceMerge(localData, generator, name, value, new ActionSetVariable()); - } - - @Override - public boolean hasReturnValue() { - return false; - } -} +/* + * Copyright (C) 2010-2015 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.model; + +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphPart; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphSourceItemPos; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.LocalData; +import java.util.List; +import java.util.Set; + +public class SetVariableActionItem extends ActionItem implements SetTypeActionItem { + + public GraphTargetItem name; + + //public GraphTargetItem value; + private int tempRegister = -1; + + @Override + public GraphPart getFirstPart() { + return value.getFirstPart(); + } + + @Override + public void setValue(GraphTargetItem value) { + this.value = value; + } + + @Override + public int getTempRegister() { + return tempRegister; + } + + @Override + public void setTempRegister(int tempRegister) { + this.tempRegister = tempRegister; + } + + @Override + public GraphTargetItem getValue() { + return value; + } + + public SetVariableActionItem(GraphSourceItem instruction, GraphTargetItem name, GraphTargetItem value) { + super(instruction, PRECEDENCE_ASSIGMENT); + this.name = name; + this.value = value; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super"))) { + writer.append(IdentifiersDeobfuscation.makeObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData))); + writer.append(" = "); + return value.toString(writer, localData); + } else if ((!(name instanceof DirectValueActionItem)) || (!((DirectValueActionItem) name).isString())) { + writer.append("set"); + writer.spaceBeforeCallParenthesies(2); + writer.append("("); + name.toString(writer, localData); + writer.append(","); + value.toString(writer, localData); + return writer.append(")"); + } + stripQuotes(name, localData, writer); + writer.append(" = "); + return value.toString(writer, localData); + } + + @Override + public GraphTargetItem getObject() { + return new GetVariableActionItem(src, name); + } + + @Override + public List getNeededSources() { + List ret = super.getNeededSources(); + ret.addAll(name.getNeededSources()); + ret.addAll(value.getNeededSources()); + return ret; + } + + @Override + public boolean isCompileTime(Set dependencies) { + if (dependencies.contains(value)) { + return false; + } + dependencies.add(value); + return value.isCompileTime(dependencies); + } + + @Override + public boolean hasSideEffect() { + return true; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + int tmpReg = asGenerator.getTempRegister(localData); + try { + return toSourceMerge(localData, generator, name, value, new ActionStoreRegister(tmpReg), new ActionSetVariable(), new ActionPush(new RegisterNumber(tmpReg))); + } finally { + asGenerator.releaseTempRegister(localData, tmpReg); + } + } + + @Override + public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + return toSourceMerge(localData, generator, name, value, new ActionSetVariable()); + } + + @Override + public boolean hasReturnValue() { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java index 8f106f250..527acaa5c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java @@ -1,162 +1,162 @@ -/* - * Copyright (C) 2010-2015 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.model.clauses; - -import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.LoopWithType; -import com.jpexs.decompiler.flash.helpers.NulWriter; -import com.jpexs.decompiler.graph.Block; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.Loop; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.LocalData; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class ForInActionItem extends LoopActionItem implements Block { - - public GraphTargetItem variableName; - - public GraphTargetItem enumVariable; - - public List commands; - - private boolean labelUsed; - - @Override - public List> getSubs() { - List> ret = new ArrayList<>(); - if (commands != null) { - ret.add(commands); - } - return ret; - } - - public ForInActionItem(Action instruction, Loop loop, GraphTargetItem variableName, GraphTargetItem enumVariable, List commands) { - super(instruction, loop); - this.variableName = variableName; - this.enumVariable = enumVariable; - this.commands = commands; - } - - @Override - public boolean needsSemicolon() { - return false; - } - - @Override - public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - if (writer instanceof NulWriter) { - ((NulWriter) writer).startLoop(loop.id, LoopWithType.LOOP_TYPE_LOOP); - } - if (labelUsed) { - writer.append("loop" + loop.id + ":").newLine(); - } - writer.append("for"); - if (writer.getFormatting().spaceBeforeParenthesesForParentheses) { - writer.append(" "); - } - writer.append("("); - if ((variableName instanceof DirectValueActionItem) && (((DirectValueActionItem) variableName).value instanceof RegisterNumber)) { - writer.append("var "); - } - stripQuotes(variableName, localData, writer); - writer.append(" in "); - enumVariable.toString(writer, localData); - writer.append(")").startBlock(); - for (GraphTargetItem ti : commands) { - ti.toStringSemicoloned(writer, localData).newLine(); - } - writer.endBlock(); - if (writer instanceof NulWriter) { - LoopWithType loopOjb = ((NulWriter) writer).endLoop(loop.id); - labelUsed = loopOjb.used; - } - return writer; - } - - @Override - public List getContinues() { - List ret = new ArrayList<>(); - for (GraphTargetItem ti : commands) { - if (ti instanceof ContinueItem) { - ret.add((ContinueItem) ti); - } - if (ti instanceof Block) { - ret.addAll(((Block) ti).getContinues()); - } - } - return ret; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - List ret = new ArrayList<>(); - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - HashMap registerVars = asGenerator.getRegisterVars(localData); - ret.addAll(enumVariable.toSource(localData, generator)); - ret.add(new ActionEnumerate2()); - - List loopExpr = new ArrayList<>(); - int exprReg = asGenerator.getTempRegister(localData); - - loopExpr.add(new ActionStoreRegister(exprReg)); - loopExpr.add(new ActionPush(new Null())); - loopExpr.add(new ActionEquals2()); - ActionIf forInEndIf = new ActionIf(0); - loopExpr.add(forInEndIf); - List loopBody = new ArrayList<>(); - loopBody.add(new ActionPush(new RegisterNumber(exprReg))); - loopBody.addAll(asGenerator.toActionList(variableName.toSourceIgnoreReturnValue(localData, generator))); - int oldForIn = asGenerator.getForInLevel(localData); - asGenerator.setForInLevel(localData, oldForIn + 1); - loopBody.addAll(asGenerator.toActionList(asGenerator.generate(localData, commands))); - asGenerator.setForInLevel(localData, oldForIn); - ActionJump forinJmpBack = new ActionJump(0); - loopBody.add(forinJmpBack); - int bodyLen = Action.actionsToBytes(loopBody, false, SWF.DEFAULT_VERSION).length; - int exprLen = Action.actionsToBytes(loopExpr, false, SWF.DEFAULT_VERSION).length; - forinJmpBack.setJumpOffset(-bodyLen - exprLen); - forInEndIf.setJumpOffset(bodyLen); - ret.addAll(loopExpr); - ret.addAll(loopBody); - asGenerator.releaseTempRegister(localData, exprReg); - return ret; - } - - @Override - public boolean hasReturnValue() { - return false; - } -} +/* + * Copyright (C) 2010-2015 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.model.clauses; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.swf4.ActionIf; +import com.jpexs.decompiler.flash.action.swf4.ActionJump; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; +import com.jpexs.decompiler.flash.ecma.Null; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.LoopWithType; +import com.jpexs.decompiler.flash.helpers.NulWriter; +import com.jpexs.decompiler.graph.Block; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.Loop; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.ContinueItem; +import com.jpexs.decompiler.graph.model.LocalData; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class ForInActionItem extends LoopActionItem implements Block { + + public GraphTargetItem variableName; + + public GraphTargetItem enumVariable; + + public List commands; + + private boolean labelUsed; + + @Override + public List> getSubs() { + List> ret = new ArrayList<>(); + if (commands != null) { + ret.add(commands); + } + return ret; + } + + public ForInActionItem(Action instruction, Loop loop, GraphTargetItem variableName, GraphTargetItem enumVariable, List commands) { + super(instruction, loop); + this.variableName = variableName; + this.enumVariable = enumVariable; + this.commands = commands; + } + + @Override + public boolean needsSemicolon() { + return false; + } + + @Override + public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { + if (writer instanceof NulWriter) { + ((NulWriter) writer).startLoop(loop.id, LoopWithType.LOOP_TYPE_LOOP); + } + if (labelUsed) { + writer.append("loop" + loop.id + ":").newLine(); + } + writer.append("for"); + if (writer.getFormatting().spaceBeforeParenthesesForParentheses) { + writer.append(" "); + } + writer.append("("); + if ((variableName instanceof DirectValueActionItem) && (((DirectValueActionItem) variableName).value instanceof RegisterNumber)) { + writer.append("var "); + } + stripQuotes(variableName, localData, writer); + writer.append(" in "); + enumVariable.toString(writer, localData); + writer.append(")").startBlock(); + for (GraphTargetItem ti : commands) { + ti.toStringSemicoloned(writer, localData).newLine(); + } + writer.endBlock(); + if (writer instanceof NulWriter) { + LoopWithType loopOjb = ((NulWriter) writer).endLoop(loop.id); + labelUsed = loopOjb.used; + } + return writer; + } + + @Override + public List getContinues() { + List ret = new ArrayList<>(); + for (GraphTargetItem ti : commands) { + if (ti instanceof ContinueItem) { + ret.add((ContinueItem) ti); + } + if (ti instanceof Block) { + ret.addAll(((Block) ti).getContinues()); + } + } + return ret; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + List ret = new ArrayList<>(); + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + HashMap registerVars = asGenerator.getRegisterVars(localData); + ret.addAll(enumVariable.toSource(localData, generator)); + ret.add(new ActionEnumerate2()); + + List loopExpr = new ArrayList<>(); + int exprReg = asGenerator.getTempRegister(localData); + + loopExpr.add(new ActionStoreRegister(exprReg)); + loopExpr.add(new ActionPush(new Null())); + loopExpr.add(new ActionEquals2()); + ActionIf forInEndIf = new ActionIf(0); + loopExpr.add(forInEndIf); + List loopBody = new ArrayList<>(); + loopBody.add(new ActionPush(new RegisterNumber(exprReg))); + loopBody.addAll(asGenerator.toActionList(variableName.toSourceIgnoreReturnValue(localData, generator))); + int oldForIn = asGenerator.getForInLevel(localData); + asGenerator.setForInLevel(localData, oldForIn + 1); + loopBody.addAll(asGenerator.toActionList(asGenerator.generate(localData, commands))); + asGenerator.setForInLevel(localData, oldForIn); + ActionJump forinJmpBack = new ActionJump(0); + loopBody.add(forinJmpBack); + int bodyLen = Action.actionsToBytes(loopBody, false, SWF.DEFAULT_VERSION).length; + int exprLen = Action.actionsToBytes(loopExpr, false, SWF.DEFAULT_VERSION).length; + forinJmpBack.setJumpOffset(-bodyLen - exprLen); + forInEndIf.setJumpOffset(bodyLen); + ret.addAll(loopExpr); + ret.addAll(loopBody); + asGenerator.releaseTempRegister(localData, exprReg); + return ret; + } + + @Override + public boolean hasReturnValue() { + return false; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java index a6cae52cc..9997baa0d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreDecrementActionItem.java @@ -1,104 +1,104 @@ -/* - * Copyright (C) 2010-2015 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.model.operations; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.UnaryOpItem; -import java.util.ArrayList; -import java.util.List; - -public class PreDecrementActionItem extends UnaryOpItem { - - public PreDecrementActionItem(GraphSourceItem instruction, GraphTargetItem object) { - super(instruction, PRECEDENCE_UNARY, object, "--"); - } - - @Override - public Object getResult() { - return EcmaScript.toNumber(value.getResult()) - 1; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - List ret = new ArrayList<>(); - GraphTargetItem val = value; - if (val instanceof VariableActionItem) { - val = ((VariableActionItem) val).getBoxedValue(); - } - if (val instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) val; - ret.addAll(gv.toSource(localData, generator)); - ret.remove(ret.size() - 1); //ActionGetVariable - ret.addAll(gv.toSource(localData, generator)); - ret.add(new ActionDecrement()); - int tmpReg = asGenerator.getTempRegister(localData); - ret.add(new ActionStoreRegister(tmpReg)); - ret.add(new ActionSetVariable()); - ret.add(new ActionPush(new RegisterNumber(tmpReg))); - asGenerator.releaseTempRegister(localData, tmpReg); - } else if (val instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) val; - ret.addAll(mem.toSource(localData, generator)); - ret.remove(ret.size() - 1); //ActionGetMember - ret.addAll(mem.toSource(localData, generator)); - ret.add(new ActionDecrement()); - int tmpReg = asGenerator.getTempRegister(localData); - ret.add(new ActionStoreRegister(tmpReg)); - ret.add(new ActionSetMember()); - ret.add(new ActionPush(new RegisterNumber(tmpReg))); - asGenerator.releaseTempRegister(localData, tmpReg); - } else if ((val instanceof DirectValueActionItem) && ((DirectValueActionItem) val).value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) val).value; - ret.add(new ActionPush(new RegisterNumber(rn.number))); - ret.add(new ActionDecrement()); - ret.add(new ActionStoreRegister(rn.number)); - } else if (val instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) val; - ret.addAll(gp.toSource(localData, generator)); // old value - ret.addAll(gp.toSource(localData, generator)); - ret.remove(ret.size() - 1); - ret.addAll(gp.toSource(localData, generator)); - ret.add(new ActionDecrement()); - ret.add(new ActionSetProperty()); - } - return ret; - } - - @Override - public GraphTargetItem returnType() { - return value.returnType(); - } -} +/* + * Copyright (C) 2010-2015 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.model.operations; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.UnaryOpItem; +import java.util.ArrayList; +import java.util.List; + +public class PreDecrementActionItem extends UnaryOpItem { + + public PreDecrementActionItem(GraphSourceItem instruction, GraphTargetItem object) { + super(instruction, PRECEDENCE_UNARY, object, "--"); + } + + @Override + public Object getResult() { + return EcmaScript.toNumber(value.getResult()) - 1; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + List ret = new ArrayList<>(); + GraphTargetItem val = value; + if (val instanceof VariableActionItem) { + val = ((VariableActionItem) val).getBoxedValue(); + } + if (val instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) val; + ret.addAll(gv.toSource(localData, generator)); + ret.remove(ret.size() - 1); //ActionGetVariable + ret.addAll(gv.toSource(localData, generator)); + ret.add(new ActionDecrement()); + int tmpReg = asGenerator.getTempRegister(localData); + ret.add(new ActionStoreRegister(tmpReg)); + ret.add(new ActionSetVariable()); + ret.add(new ActionPush(new RegisterNumber(tmpReg))); + asGenerator.releaseTempRegister(localData, tmpReg); + } else if (val instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) val; + ret.addAll(mem.toSource(localData, generator)); + ret.remove(ret.size() - 1); //ActionGetMember + ret.addAll(mem.toSource(localData, generator)); + ret.add(new ActionDecrement()); + int tmpReg = asGenerator.getTempRegister(localData); + ret.add(new ActionStoreRegister(tmpReg)); + ret.add(new ActionSetMember()); + ret.add(new ActionPush(new RegisterNumber(tmpReg))); + asGenerator.releaseTempRegister(localData, tmpReg); + } else if ((val instanceof DirectValueActionItem) && ((DirectValueActionItem) val).value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) val).value; + ret.add(new ActionPush(new RegisterNumber(rn.number))); + ret.add(new ActionDecrement()); + ret.add(new ActionStoreRegister(rn.number)); + } else if (val instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) val; + ret.addAll(gp.toSource(localData, generator)); // old value + ret.addAll(gp.toSource(localData, generator)); + ret.remove(ret.size() - 1); + ret.addAll(gp.toSource(localData, generator)); + ret.add(new ActionDecrement()); + ret.add(new ActionSetProperty()); + } + return ret; + } + + @Override + public GraphTargetItem returnType() { + return value.returnType(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java index 81d0cbc30..e43762deb 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/PreIncrementActionItem.java @@ -1,105 +1,105 @@ -/* - * Copyright (C) 2010-2015 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.model.operations; - -import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; -import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; -import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; -import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; -import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; -import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.graph.CompilationException; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.SourceGenerator; -import com.jpexs.decompiler.graph.model.UnaryOpItem; -import java.util.ArrayList; -import java.util.List; - -public class PreIncrementActionItem extends UnaryOpItem { - - public PreIncrementActionItem(GraphSourceItem instruction, GraphTargetItem object) { - super(instruction, PRECEDENCE_UNARY, object, "++"); - } - - @Override - public Object getResult() { - return EcmaScript.toNumber(value.getResult()) + 1; - } - - @Override - public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; - List ret = new ArrayList<>(); - GraphTargetItem val = value; - if (val instanceof VariableActionItem) { - val = ((VariableActionItem) val).getBoxedValue(); - } - if (val instanceof GetVariableActionItem) { - GetVariableActionItem gv = (GetVariableActionItem) val; - ret.addAll(gv.toSource(localData, generator)); - ret.remove(ret.size() - 1); //ActionGetVariable - ret.addAll(gv.toSource(localData, generator)); - ret.add(new ActionIncrement()); - int tmpReg = asGenerator.getTempRegister(localData); - - ret.add(new ActionStoreRegister(tmpReg)); - ret.add(new ActionSetVariable()); - ret.add(new ActionPush(new RegisterNumber(tmpReg))); - asGenerator.releaseTempRegister(localData, tmpReg); - } else if (val instanceof GetMemberActionItem) { - GetMemberActionItem mem = (GetMemberActionItem) val; - ret.addAll(mem.toSource(localData, generator)); - ret.remove(ret.size() - 1); //ActionGetMember - ret.addAll(mem.toSource(localData, generator)); - ret.add(new ActionIncrement()); - int tmpReg = asGenerator.getTempRegister(localData); - ret.add(new ActionStoreRegister(tmpReg)); - ret.add(new ActionSetMember()); - ret.add(new ActionPush(new RegisterNumber(tmpReg))); - asGenerator.releaseTempRegister(localData, tmpReg); - } else if ((val instanceof DirectValueActionItem) && ((DirectValueActionItem) val).value instanceof RegisterNumber) { - RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) val).value; - ret.add(new ActionPush(new RegisterNumber(rn.number))); - ret.add(new ActionIncrement()); - ret.add(new ActionStoreRegister(rn.number)); - } else if (val instanceof GetPropertyActionItem) { - GetPropertyActionItem gp = (GetPropertyActionItem) val; - ret.addAll(gp.toSource(localData, generator)); // old value - ret.addAll(gp.toSource(localData, generator)); - ret.remove(ret.size() - 1); - ret.addAll(gp.toSource(localData, generator)); - ret.add(new ActionIncrement()); - ret.add(new ActionSetProperty()); - } - return ret; - } - - @Override - public GraphTargetItem returnType() { - return value.returnType(); - } -} +/* + * Copyright (C) 2010-2015 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.model.operations; + +import com.jpexs.decompiler.flash.SourceGeneratorLocalData; +import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; +import com.jpexs.decompiler.flash.action.model.GetMemberActionItem; +import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem; +import com.jpexs.decompiler.flash.action.model.GetVariableActionItem; +import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator; +import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem; +import com.jpexs.decompiler.flash.action.swf4.ActionPush; +import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; +import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; +import com.jpexs.decompiler.flash.action.swf4.RegisterNumber; +import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; +import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; +import com.jpexs.decompiler.flash.ecma.EcmaScript; +import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.GraphSourceItem; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SourceGenerator; +import com.jpexs.decompiler.graph.model.UnaryOpItem; +import java.util.ArrayList; +import java.util.List; + +public class PreIncrementActionItem extends UnaryOpItem { + + public PreIncrementActionItem(GraphSourceItem instruction, GraphTargetItem object) { + super(instruction, PRECEDENCE_UNARY, object, "++"); + } + + @Override + public Object getResult() { + return EcmaScript.toNumber(value.getResult()) + 1; + } + + @Override + public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { + ActionSourceGenerator asGenerator = (ActionSourceGenerator) generator; + List ret = new ArrayList<>(); + GraphTargetItem val = value; + if (val instanceof VariableActionItem) { + val = ((VariableActionItem) val).getBoxedValue(); + } + if (val instanceof GetVariableActionItem) { + GetVariableActionItem gv = (GetVariableActionItem) val; + ret.addAll(gv.toSource(localData, generator)); + ret.remove(ret.size() - 1); //ActionGetVariable + ret.addAll(gv.toSource(localData, generator)); + ret.add(new ActionIncrement()); + int tmpReg = asGenerator.getTempRegister(localData); + + ret.add(new ActionStoreRegister(tmpReg)); + ret.add(new ActionSetVariable()); + ret.add(new ActionPush(new RegisterNumber(tmpReg))); + asGenerator.releaseTempRegister(localData, tmpReg); + } else if (val instanceof GetMemberActionItem) { + GetMemberActionItem mem = (GetMemberActionItem) val; + ret.addAll(mem.toSource(localData, generator)); + ret.remove(ret.size() - 1); //ActionGetMember + ret.addAll(mem.toSource(localData, generator)); + ret.add(new ActionIncrement()); + int tmpReg = asGenerator.getTempRegister(localData); + ret.add(new ActionStoreRegister(tmpReg)); + ret.add(new ActionSetMember()); + ret.add(new ActionPush(new RegisterNumber(tmpReg))); + asGenerator.releaseTempRegister(localData, tmpReg); + } else if ((val instanceof DirectValueActionItem) && ((DirectValueActionItem) val).value instanceof RegisterNumber) { + RegisterNumber rn = (RegisterNumber) ((DirectValueActionItem) val).value; + ret.add(new ActionPush(new RegisterNumber(rn.number))); + ret.add(new ActionIncrement()); + ret.add(new ActionStoreRegister(rn.number)); + } else if (val instanceof GetPropertyActionItem) { + GetPropertyActionItem gp = (GetPropertyActionItem) val; + ret.addAll(gp.toSource(localData, generator)); // old value + ret.addAll(gp.toSource(localData, generator)); + ret.remove(ret.size() - 1); + ret.addAll(gp.toSource(localData, generator)); + ret.add(new ActionIncrement()); + ret.add(new ActionSetProperty()); + } + return ret; + } + + @Override + public GraphTargetItem returnType() { + return value.returnType(); + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java index 94cde5bb0..5fa5bd6ee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java @@ -1,555 +1,555 @@ -/* - * Copyright (C) 2010-2015 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.parser.pcode; - -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.flashlite.ActionFSCommand2; -import com.jpexs.decompiler.flash.action.flashlite.ActionStrictMode; -import com.jpexs.decompiler.flash.action.parser.ActionParseException; -import com.jpexs.decompiler.flash.action.special.ActionDeobfuscateJump; -import com.jpexs.decompiler.flash.action.special.ActionDeobfuscatePop; -import com.jpexs.decompiler.flash.action.special.ActionEnd; -import com.jpexs.decompiler.flash.action.special.ActionNop; -import com.jpexs.decompiler.flash.action.swf3.ActionGetURL; -import com.jpexs.decompiler.flash.action.swf3.ActionGoToLabel; -import com.jpexs.decompiler.flash.action.swf3.ActionGotoFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionNextFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionPlay; -import com.jpexs.decompiler.flash.action.swf3.ActionPrevFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionSetTarget; -import com.jpexs.decompiler.flash.action.swf3.ActionStop; -import com.jpexs.decompiler.flash.action.swf3.ActionStopSounds; -import com.jpexs.decompiler.flash.action.swf3.ActionToggleQuality; -import com.jpexs.decompiler.flash.action.swf3.ActionWaitForFrame; -import com.jpexs.decompiler.flash.action.swf4.ActionAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionAnd; -import com.jpexs.decompiler.flash.action.swf4.ActionAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionCall; -import com.jpexs.decompiler.flash.action.swf4.ActionCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionCloneSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionDivide; -import com.jpexs.decompiler.flash.action.swf4.ActionEndDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionGetTime; -import com.jpexs.decompiler.flash.action.swf4.ActionGetURL2; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionGotoFrame2; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionLess; -import com.jpexs.decompiler.flash.action.swf4.ActionMBAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionMBCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionOr; -import com.jpexs.decompiler.flash.action.swf4.ActionPop; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionRandomNumber; -import com.jpexs.decompiler.flash.action.swf4.ActionRemoveSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionSetTarget2; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionStartDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionStringAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionStringEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLess; -import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; -import com.jpexs.decompiler.flash.action.swf4.ActionToInteger; -import com.jpexs.decompiler.flash.action.swf4.ActionTrace; -import com.jpexs.decompiler.flash.action.swf4.ActionWaitForFrame2; -import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; -import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; -import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; -import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitURShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete2; -import com.jpexs.decompiler.flash.action.swf5.ActionEnumerate; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionInitArray; -import com.jpexs.decompiler.flash.action.swf5.ActionInitObject; -import com.jpexs.decompiler.flash.action.swf5.ActionLess2; -import com.jpexs.decompiler.flash.action.swf5.ActionModulo; -import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionReturn; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf5.ActionTargetPath; -import com.jpexs.decompiler.flash.action.swf5.ActionToNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionToString; -import com.jpexs.decompiler.flash.action.swf5.ActionTypeOf; -import com.jpexs.decompiler.flash.action.swf5.ActionWith; -import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; -import com.jpexs.decompiler.flash.action.swf6.ActionGreater; -import com.jpexs.decompiler.flash.action.swf6.ActionInstanceOf; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater; -import com.jpexs.decompiler.flash.action.swf7.ActionCastOp; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.action.swf7.ActionExtends; -import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; -import com.jpexs.decompiler.flash.action.swf7.ActionThrow; -import com.jpexs.decompiler.flash.action.swf7.ActionTry; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.helpers.Helper; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Stack; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class ASMParser { - - private static final Logger logger = Logger.getLogger(ASMParser.class.getName()); - - public static ActionList parse(boolean ignoreNops, List