/*
* Copyright (C) 2010-2016 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;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Runtime;
import com.jpexs.decompiler.flash.abc.avm2.AVM2RuntimeInfo;
import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
import com.jpexs.decompiler.flash.tags.Tag;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
/**
*
* @author JPEXS
*/
public class ActionScript3ExecuteTest {
private SWF swf;
private ABC abc;
@BeforeClass
public void init() throws IOException, InterruptedException {
//Main.initLogging(false);
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/run_as3/run.swf")), false);
/*try (InputStream is = new BufferedInputStream(new FileInputStream("testdata/run_as3/run.swf"))) {
swf = new SWF(is, false);
}*/
DoABC2Tag tag = null;
for (Tag t : swf.getTags()) {
if (t instanceof DoABC2Tag) {
tag = (DoABC2Tag) t;
break;
}
}
assertNotNull(tag);
this.abc = tag.getABC();
Configuration.autoDeobfuscate.set(false);
Configuration.decompile.set(true);
Configuration.registerNameFormat.set("_loc%d_");
Configuration.showMethodBodyId.set(false);
}
//@Test
public void testRun() throws IOException, InterruptedException {
MethodBody body = abc.findBodyByClassAndName("Run", "run");
Object result;
try {
result = body.getCode().execute(new HashMap<>(), abc.constants, new AVM2RuntimeInfo(AVM2Runtime.ADOBE_FLASH, 19, true));
assertEquals(result, "Test");
} catch (AVM2ExecutionException ex) {
fail();
}
}
//@Test
public void testAddMethod() throws IOException, InterruptedException {
int classId = abc.findClassByName("Run");
MethodBody runBody = abc.findBodyByClassAndName("Run", "runInstance");
runBody.max_stack = 10;
AVM2Code ccode = new AVM2Code();
List<AVM2Instruction> code = ccode.code;
code.add(new AVM2Instruction(0, AVM2Instructions.GetLocal0, null));
code.add(new AVM2Instruction(0, AVM2Instructions.PushScope, null));
code.add(new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("", true)}));
for (int testMethodId = 1; testMethodId < 10; testMethodId++) {
AVM2Code ccode2 = new AVM2Code();
List<AVM2Instruction> code2 = ccode2.code;
code2.add(new AVM2Instruction(0, AVM2Instructions.GetLocal0, null));
code2.add(new AVM2Instruction(0, AVM2Instructions.PushScope, null));
code2.add(new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId(testMethodId + ""/* + "\r\n"*/, true)}));
code2.add(new AVM2Instruction(0, AVM2Instructions.ReturnValue, null));
boolean isStatic = testMethodId % 2 == 0;
int multinameId = addMethod(classId, "test" + testMethodId, isStatic, ccode2);
if (isStatic) {
code.add(new AVM2Instruction(0, AVM2Instructions.FindPropertyStrict, new int[]{multinameId}));
} else {
code.add(new AVM2Instruction(0, AVM2Instructions.GetLocal0, null));
}
code.add(new AVM2Instruction(0, AVM2Instructions.CallProperty, new int[]{multinameId, 0}));
code.add(new AVM2Instruction(0, AVM2Instructions.Add, null));
code.add(new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("\r\n", true)}));
code.add(new AVM2Instruction(0, AVM2Instructions.Add, null));
}
code.add(new AVM2Instruction(0, AVM2Instructions.ReturnValue, null));
runBody.setCode(ccode);
runBody.markOffsets();
}
private int addMethod(int classId, String name, boolean isStatic, AVM2Code code) {
TraitMethodGetterSetter methodTrait = abc.addMethod(classId, name, isStatic);
MethodInfo methodInfo = abc.method_info.get(methodTrait.method_info);
MethodBody methodBody = abc.findBody(methodInfo);
methodBody.max_stack = 10;
methodBody.max_regs = 10;
methodBody.init_scope_depth = 3;
methodBody.max_scope_depth = 10;
methodBody.setCode(code);
methodBody.markOffsets();
return methodTrait.name_index;
}
}