trunk contents moved to root

This commit is contained in:
Jindra Petřík
2014-05-10 20:50:57 +02:00
parent 1b851e66a8
commit 199a4d0c2b
2296 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.ABCInputStream;
import com.jpexs.decompiler.flash.abc.ABCOutputStream;
import com.jpexs.decompiler.flash.gui.Main;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ABCStreamTest {
@BeforeClass
public void init(){
Main.initLogging(false);
}
@Test
public void testU30() {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ABCOutputStream aos = new ABCOutputStream(baos);) {
long number = 1531;
aos.writeU30(number);
aos.close();
try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ABCInputStream ais = new ABCInputStream(bais);) {
assertEquals(number, ais.readU30());
assertEquals(0, bais.available());
}
} catch (IOException ex) {
fail();
}
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ActionScript2AssemblerTest extends ActionStript2TestBase {
@BeforeClass
public void init() throws IOException, InterruptedException {
Main.initLogging(false);
Configuration.autoDeobfuscate.set(false);
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false);
}
@Test
public void testModifiedConstantPools() {
String actionsString = "ConstantPool \"ok\"\n"
+ "Jump loc001f\n"
+ "loc000d:Push \"ok\" false\n"
+ "SetVariable\n"
+ "Jump loc002f\n"
+ "loc001f:ConstantPool \"wrong\"\n"
+ "Jump loc000d\n"
+ "loc002f:";
try {
List<Action> actions = ASMParser.parse(0, 0, true, actionsString, swf.version, false);
DoActionTag doa = getFirstActionTag();
doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version));
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(doa, doa.getActions(), "", writer);
String actualResult = writer.toString();
writer = new HilightedTextWriter(new CodeFormatting(), false);
doa.getASMSource(ScriptExportMode.PCODE, writer, null);
String decompiled = writer.toString();
assertEquals(actualResult.trim(), "ok = false;");
assertTrue(decompiled.contains("Push \"ok\" false"));
} catch (IOException | ParseException | InterruptedException ex) {
fail();
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ActionScript2DeobfuscatorTest extends ActionStript2TestBase {
@BeforeClass
public void init() throws IOException, InterruptedException {
Main.initLogging(false);
Configuration.autoDeobfuscate.set(true);
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false);
}
@Test
public void testRemoveJumpsToTheNextAction() {
String actionsString = "ConstantPool \"a\" \"b\" \"c\"\n"
+ "Push false register1\n"
+ "StoreRegister 2\n"
+ "Pop\n"
+ "Push register2\n"
+ "StoreRegister 0\n"
+ "Push \"a\"\n"
+ "StrictEquals\n"
+ "If loc005a\n"
+ "Push register0 \"b\"\n"
+ "StrictEquals\n"
+ "If loc0068\n"
+ "Jump loc0048;\n"
+ "loc0048:Push register0 \"c\"\n"
+ "StrictEquals\n"
+ "If loc0076\n"
+ "Jump loc0084\n"
+ "loc005a:Push 1\n"
+ "Trace\n"
+ "Jump loc0084\n"
+ "loc0068:Push 2\n"
+ "Trace\n"
+ "Jump loc0084\n"
+ "loc0076:Push 3\n"
+ "Trace\n"
+ "Jump loc0084\n"
+ "loc0084:";
try {
List<Action> actions = ASMParser.parse(0, 0, true, actionsString, swf.version, false);
DoActionTag doa = getFirstActionTag();
doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version));
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(doa, doa.getActions(), "", writer);
String actualResult = writer.toString();
assertTrue(actualResult.contains("case \"c\":"));
} catch (IOException | ParseException | InterruptedException ex) {
fail();
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.graph.CompilationException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ActionScript2ParserTest extends ActionStript2TestBase {
@BeforeClass
public void init() throws IOException, InterruptedException {
Main.initLogging(false);
Configuration.autoDeobfuscate.set(false);
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false);
}
private void parseAS2(String script) {
DoActionTag asm = getFirstActionTag();
try {
ActionScriptParser par = new ActionScriptParser();
asm.setActions(par.actionsFromString(script));
} catch (IOException | CompilationException | ParseException ex) {
fail("Unable to parse: " + script);
}
}
@Test
private void testAS2Parse1() {
parseAS2(
"var x = true;\n"
+ "while(x) { }");
}
@Test
private void testAS2Parse2() {
parseAS2(
"function test(a, b, c)\n"
+ "{\n"
+ " return a != 0?b * 2:c;\n"
+ "}");
}
@Test
private void testAS2Parse3() {
parseAS2(
"for(;i < 10;i++) { }");
}
@Test
private void testAS2Parse4() {
parseAS2(
"class cl1\n"
+ "{\n"
+ " function stop()\n"
+ " {\n"
+ " }\n"
+ "}");
}
@Test
private void testAS2Parse5() {
parseAS2(
"if(!test.T1)\n"
+ "{\n"
+ " test.T1 = function()\n"
+ " {\n"
+ " super();\n"
+ " }.Initialize = function(obj)\n"
+ " {\n"
+ " var x = 1;\n"
+ " };\n"
+ "}");
}
}

View File

@@ -0,0 +1,808 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ActionScript2Test extends ActionStript2TestBase {
@BeforeClass
public void init() throws IOException, InterruptedException {
Main.initLogging(false);
Configuration.autoDeobfuscate.set(false);
Configuration.decompile.set(true);
Configuration.registerNameFormat.set("_loc%d_");
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false);
}
private void compareSrc(int frame, String expectedResult) {
DoActionTag doa = getFrameSource(frame);
assertNotNull(doa);
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
try {
Action.actionsToSource(doa, doa.getActions(), "", writer);
} catch (InterruptedException ex) {
fail();
}
String actualResult = writer.toString().replaceAll("[ \r\n]", "");
expectedResult = expectedResult.replaceAll("[ \r\n]", "");
assertEquals(actualResult, expectedResult);
}
private DoActionTag getFrameSource(int frame) {
int f = 0;
DoActionTag lastDoa = null;
for (Tag t : swf.tags) {
if (t instanceof DoActionTag) {
lastDoa = (DoActionTag) t;
}
if (t instanceof ShowFrameTag) {
f++;
if (f == frame) {
return lastDoa;
}
lastDoa = null;
}
}
return null;
}
@Test
public void frame23_Test() {
compareSrc(23, "stop();\r\n"
);
}
@Test
public void frame24_unicodeTest() {
compareSrc(24, "trace(\"unicodeTest\");\r\n"
+ "var k = \"היפופוטמי, או א\";\r\n"
+ "trace(k);\r\n"
);
}
@Test
public void frame25_ifWithElseTest() {
compareSrc(25, "trace(\"ifWithElseTest\");\r\n"
+ "var i = 5;\r\n"
+ "if(i == 258)\r\n"
+ "{\r\n"
+ "trace(\"onTrue\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"onFalse\" + i);\r\n"
+ "}\r\n"
);
}
@Test
public void frame26_forTest() {
compareSrc(26, "trace(\"forTest\");\r\n"
+ "var i = 0;\r\n"
+ "while(i < 10)\r\n"
+ "{\r\n"
+ "trace(\"hello:\" + i);\r\n"
+ "i++;\r\n"
+ "}\r\n"
);
}
@Test
public void frame27_whileTest() {
compareSrc(27, "trace(\"whileTest\");\r\n"
+ "var i = 0;\r\n"
+ "while(i < 10)\r\n"
+ "{\r\n"
+ "trace(\"hello:\" + i);\r\n"
+ "i++;\r\n"
+ "}\r\n"
);
}
@Test
public void frame28_forWithContinueTest() {
compareSrc(28, "trace(\"forWithContinueTest\");\r\n"
+ "var i = 0;\r\n"
+ "for(;i < 10;i++)\r\n"
+ "{\r\n"
+ "trace(\"hello:\" + i);\r\n"
+ "if(i == 5)\r\n"
+ "{\r\n"
+ "trace(\"i==5\");\r\n"
+ "if(i == 7)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"hawk\");\r\n"
+ "}\r\n"
+ "trace(\"end of the loop\");\r\n"
+ "}\r\n"
);
}
@Test
public void frame29_doWhileTest() {
compareSrc(29, "trace(\"doWhileTest\");\r\n"
+ "var i = 0;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "trace(\"i=\" + i);\r\n"
+ "i++;\r\n"
+ "}\r\n"
+ "while(i < 10);\r\n"
+ "trace(\"end\");\r\n"
);
}
@Test
public void frame30_switchTest() {
compareSrc(30, "trace(\"switchTest\");\r\n"
+ "var i = 5;\r\n"
+ "switch(i)\r\n"
+ "{\r\n"
+ "case 0:\r\n"
+ "case 1:\r\n"
+ "trace(\"one\");\r\n"
+ "break;\r\n"
+ "case 2:\r\n"
+ "trace(\"two\");\r\n"
+ "case 3:\r\n"
+ "trace(\"three\");\r\n"
+ "break;\r\n"
+ "case 4:\r\n"
+ "trace(\"four\");\r\n"
+ "break;\r\n"
+ "default:\r\n"
+ "trace(\"default clause\");\r\n"
+ "}\r\n"
+ "trace(\"scriptend\");\r\n"
);
}
@Test
public void frame31_strictEqualsTest() {
compareSrc(31, "trace(\"strictEqualsTest\");\r\n"
+ "var i = 5;\r\n"
+ "if(i === 5)\r\n"
+ "{\r\n"
+ "trace(\"equals strict\");\r\n"
+ "}\r\n"
+ "if(!(i === 5))\r\n"
+ "{\r\n"
+ "trace(\"not equals strict\");\r\n"
+ "}\r\n"
);
}
@Test
public void frame32_switchForTest() {
compareSrc(32, "trace(\"switchForTest\");\r\n"
+ "var i = 0;\r\n"
+ "for(;i < 10;i++)\r\n"
+ "{\r\n"
+ "switch(i)\r\n"
+ "{\r\n"
+ "case 0:\r\n"
+ "trace(\"zero\");\r\n"
+ "continue;\r\n"
+ "case 5:\r\n"
+ "trace(\"five\");\r\n"
+ "break;\r\n"
+ "case 10:\r\n"
+ "trace(\"ten\");\r\n"
+ "break;\r\n"
+ "case 1:\r\n"
+ "if(i == 7)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"one\");\r\n"
+ "default:\r\n"
+ "trace(\"def\");\r\n"
+ "}\r\n"
+ "trace(\"before loop end\");\r\n"
+ "}\r\n"
);
}
@Test
public void frame33_functionTest() {
compareSrc(33, "function hello(what, second)\r\n"
+ "{\r\n"
+ "trace(\"hello \" + what + \"! \" + second);\r\n"
+ "}\r\n"
+ "trace(\"functionTest\");\r\n"
+ "hello(\"friend\",7);\r\n"
);
}
@Test
public void frame34_multipleConditionsTest() {
compareSrc(34, "trace(\"multipleConditionsTest\");\r\n"
+ "var k = 5;\r\n"
+ "if(k == 7 && k == 8)\r\n"
+ "{\r\n"
+ "trace(\"first\");\r\n"
+ "}\r\n"
+ "if(k == 9)\r\n"
+ "{\r\n"
+ "trace(\"second\");\r\n"
+ "}\r\n"
+ "trace(\"finish\");\r\n"
);
}
@Test
public void frame35_multipleConditions2Test() {
compareSrc(35, "trace(\"multipleConditions2Test\");\r\n"
+ "var k = 5;\r\n"
+ "if(k == 7 && k == 8)\r\n"
+ "{\r\n"
+ "trace(\"first\");\r\n"
+ "}\r\n"
+ "if(k == 9 || k == 6)\r\n"
+ "{\r\n"
+ "trace(\"second\");\r\n"
+ "}\r\n"
+ "trace(\"finish\");\r\n"
);
}
@Test
public void frame36_chainedAssignmentsTest() {
compareSrc(36, "trace(\"chainedAssignmentsTest\");\r\n"
+ "var a = 7;\r\n"
+ "var b = 8;\r\n"
+ "var c = 9;\r\n"
+ "var d = c = b = a = 10;\r\n"
+ "trace(d);\r\n"
);
}
@Test
public void frame37_objectsTest() {
compareSrc(37, "trace(\"objectsTest\");\r\n"
+ "var flashBox = new Box(box1);\r\n"
+ "_root.onEnterFrame = function()\r\n"
+ "{\r\n"
+ "flashBox.moveUp();\r\n"
+ "};\r\n"
+ "var ship = new Ship(200);\r\n"
+ "var enemy = new Enemy(56);\r\n"
+ "ship.moveDown(0.5);\r\n"
+ "ship.moveUp(0.2);\r\n"
+ "enemy.moveRight(230);\r\n"
+ "enemy.moveLeft(100);\r\n"
+ "var mt = new com.jpexs.MyTest();\r\n"
+ "mt.test();\r\n"
+ "var c = new Cox(box1);\r\n"
);
}
@Test
public void frame38_doWhile2Test() {
compareSrc(38, "trace(\"doWhile2Test\");\r\n"
+ "var k = 5;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "k++;\r\n"
+ "if(k == 7)\r\n"
+ "{\r\n"
+ "k = 5 * k;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "k = 5 + k;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "while(k < 9);\r\n"
);
}
@Test
public void frame39_whileAndTest() {
compareSrc(39, "trace(\"whileAndTest\");\r\n"
+ "var a = 5;\r\n"
+ "var b = 10;\r\n"
+ "while(a < 10 && b > 1)\r\n"
+ "{\r\n"
+ "a++;\r\n"
+ "b--;\r\n"
+ "}\r\n"
+ "a = 7;\r\n"
+ "b = 9;\r\n"
);
}
@Test
public void frame40_forInTest() {
compareSrc(40, "function testForIn()\r\n"
+ "{\r\n"
+ "var _loc1_ = [];\r\n"
+ "for(var _loc2_ in _loc1_)\r\n"
+ "{\r\n"
+ "if(_loc2_ > 3)\r\n"
+ "{\r\n"
+ "if(_loc2_ == 5)\r\n"
+ "{\r\n"
+ "return 7;\r\n"
+ "}\r\n"
+ "return 8;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"forInTest\");\r\n"
+ "trace(testForIn());\r\n"
+ "var arr = [];\r\n"
+ "for(var a in arr)\r\n"
+ "{\r\n"
+ "trace(a);\r\n"
+ "}\r\n"
);
}
@Test
public void frame41_tryTest() {
compareSrc(41, "trace(\"tryTest\");\r\n"
+ "var k = 5;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "k = Infinity;\r\n"
+ "}\r\n"
+ "catch(e)\r\n"
+ "{\r\n"
+ "trace(\"bug \" + e);\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"huu\");\r\n"
+ "}\r\n"
+ "trace(\"next\");\r\n"
+ "try\r\n"
+ "{\r\n"
+ "k = 6;\r\n"
+ "}\r\n"
+ "catch(e)\r\n"
+ "{\r\n"
+ "trace(\"bug2 \" + e);\r\n"
+ "}\r\n"
+ "trace(\"next2\");\r\n"
+ "var k = 5;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "k = Infinity;\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"final\");\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n"
);
}
@Test
public void frame42_indicesTest() {
compareSrc(42, "trace(\"indicesTest\");\r\n"
+ "var k = [1,2,3];\r\n"
+ "var b = k[1];\r\n"
+ "trace(b);\r\n"
);
}
@Test
public void frame43_incDecTest() {
compareSrc(43, "function tst()\r\n"
+ "{\r\n"
+ "return 1;\r\n"
+ "}\r\n"
+ "trace(\"incDecTest\");\r\n"
+ "var i = 5;\r\n"
+ "var b = i++;\r\n"
+ "var c = --i + 5;\r\n"
+ "trace(\"a:\" + a + \" b:\" + b + \" c:\" + c);\r\n"
+ "var arr = [1,2,3];\r\n"
+ "arr[tst()]++;\r\n"
+ "var d = arr[tst()];\r\n"
+ "trace(d);\r\n"
);
}
@Test
public void frame44_chainedAssignments2Test() {
compareSrc(44, "trace(\"chainedAssignments2Test\");\r\n"
+ "var a = 5;\r\n"
+ "var b = 6;\r\n"
+ "var c = 7;\r\n"
+ "var d = c = b = a = 4;\r\n"
+ "if((d = c = b = a = 7) > 2)\r\n"
+ "{\r\n"
+ "trace(d);\r\n"
+ "}\r\n"
+ "trace(d + 1);\r\n"
+ "var i = 0;\r\n"
+ "while(i < 5)\r\n"
+ "{\r\n"
+ "if(i == 7)\r\n"
+ "{\r\n"
+ "}\r\n"
+ "i++;\r\n"
+ "}\r\n"
);
}
@Test
public void frame45_function2Test() {
compareSrc(45, "function a()\r\n"
+ "{\r\n"
+ "trace(\"hi\");\r\n"
+ "var _loc1_ = 5;\r\n"
+ "if(_loc1_ == 7)\r\n"
+ "{\r\n"
+ "return undefined;\r\n"
+ "}\r\n"
+ "_loc1_ = _loc1_ * 9;\r\n"
+ "trace(_loc1_);\r\n"
+ "}\r\n"
+ "trace(\"function2Test\");\r\n"
);
}
@Test
public void frame46_tryFunctionTest() {
compareSrc(46, "function testtry()\r\n"
+ "{\r\n"
+ "var _loc1_ = 5;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "if(_loc1_ == 3)\r\n"
+ "{\r\n"
+ "return undefined;\r\n"
+ "}\r\n"
+ "if(_loc1_ == 4)\r\n"
+ "{\r\n"
+ "throw new Error();\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "_loc1_ = 7;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "catch(e)\r\n"
+ "{\r\n"
+ "trace(\"error\");\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"finally\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"tryFunctionTest\");\r\n"
);
}
@Test
public void frame47_ternarTest() {
compareSrc(47, "trace(\"ternarTest\");\r\n"
+ "var a = 5;\r\n"
+ "var b = a != 4?3:2;\r\n"
+ "trace(b);\r\n"
);
}
@Test
public void frame48_forInInTest() {
compareSrc(48, "function tst()\r\n"
+ "{\r\n"
+ "var _loc2_ = [];\r\n"
+ "_loc2_[0] = [];\r\n"
+ "for(var _loc3_ in _loc2_)\r\n"
+ "{\r\n"
+ "for(var _loc1_ in _loc3_)\r\n"
+ "{\r\n"
+ "if(_loc1_ == 5)\r\n"
+ "{\r\n"
+ "return 5;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "if(_loc3_ == 8)\r\n"
+ "{\r\n"
+ "return 3;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "return 8;\r\n"
+ "}\r\n"
+ "trace(\"forInInTest\");\r\n"
+ "tst();\r\n"
);
}
@Test
public void frame49_registersFuncTest() {
compareSrc(49, "function tst(px)\r\n"
+ "{\r\n"
+ "var _loc1_ = 57;\r\n"
+ "_loc1_ = _loc1_ * 27;\r\n"
+ "}\r\n"
+ "trace(\"registersFuncTest\");\r\n"
+ "tst(5);\r\n"
+ "var s = String(5);\r\n"
);
}
@Test
public void frame50_ifFrameLoadedTest() {
compareSrc(50, "trace(\"ifFrameLoadedTest\");\r\n"
+ "ifFrameLoaded(9)\r\n"
+ "{\r\n"
+ "trace(\"loaded\");\r\n"
+ "}\r\n"
);
}
@Test
public void frame51_function3Test() {
compareSrc(51, "function tst()\r\n"
+ "{\r\n"
+ "var _loc1_ = 5;\r\n"
+ "c = _loc1_ = 8;\r\n"
+ "trace(\"hi\");\r\n"
+ "trace(_loc1_);\r\n"
+ "if((e = d = f = c = 9) > 5)\r\n"
+ "{\r\n"
+ "trace(\"dd\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"function3Test\");\r\n"
+ "var c = 7;\r\n"
+ "var d = 7;\r\n"
+ "var e = 8;\r\n"
+ "tst();\r\n"
);
}
@Test
public void frame52_commaOperatorTest() {
compareSrc(52, "trace(\"commaOperatorTest\");\r\n"
+ "var a = 0;\r\n"
+ "var b = 0;\r\n"
+ "var c = 0;\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "a++;\r\n"
+ "b = b + 2;\r\n"
+ "if(c < 10)\r\n"
+ "{\r\n"
+ "trace(c);\r\n"
+ "c++;\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"konec\");\r\n"
);
}
@Test
public void frame53_commaOperator2Test() {
compareSrc(53, "trace(\"commaOperator2Test\");\r\n"
+ "var k = 8;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "if(k == 9)\r\n"
+ "{\r\n"
+ "trace(\"h\");\r\n"
+ "if(k == 9)\r\n"
+ "{\r\n"
+ "trace(\"f\");\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"b\");\r\n"
+ "}\r\n"
+ "trace(\"gg\");\r\n"
+ "}\r\n"
+ "while(k++, k < 10);\r\n"
+ "trace(\"ss\");\r\n"
);
}
@Test
public void frame54_function4Test() {
compareSrc(54, "function tst()\r\n"
+ "{\r\n"
+ "var _loc1_ = 5;\r\n"
+ "while(_loc1_ < 10)\r\n"
+ "{\r\n"
+ "if(_loc1_ == 5)\r\n"
+ "{\r\n"
+ "if(_loc1_ == 6)\r\n"
+ "{\r\n"
+ "return true;\r\n"
+ "}\r\n"
+ "_loc1_ = _loc1_ + 1;\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "return false;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"function4Test\");\r\n"
+ "tst();\r\n"
);
}
@Test
public void frame55_pushTest() {
compareSrc(55, "trace(\"pushTest\");\r\n"
);
}
@Test
public void frame56_commaOperator3Test() {
compareSrc(56, "trace(\"commaOperator3Test\");\r\n"
+ "var k = 1;\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "k++;\r\n"
+ "if(k < 10)\r\n"
+ "{\r\n"
+ "k = k * 5;\r\n"
+ "trace(k);\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n"
);
}
@Test
public void frame57_commaOperator4Test() {
compareSrc(57, "trace(\"commaOperator4Test\");\r\n"
+ "var k = 0;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "trace(k);\r\n"
+ "if(k == 8)\r\n"
+ "{\r\n"
+ "trace(\"a\");\r\n"
+ "if(k == 9)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"d\");\r\n"
+ "trace(\"b\");\r\n"
+ "}\r\n"
+ "k++;\r\n"
+ "}\r\n"
+ "while(k = k + 5, k < 20);\r\n"
+ "trace(\"end\");\r\n"
);
}
@Test
public void frame58_globalFunctionsTest() {
compareSrc(58, "function tst(p1)\r\n"
+ "{\r\n"
+ "trace(\"test\");\r\n"
+ "}\r\n"
+ "trace(\"globalFunctionsTest\");\r\n"
+ "var k = Array(1,2,3);\r\n"
+ "var a = 1;\r\n"
+ "var b = Boolean(a);\r\n"
+ "call(5);\r\n"
+ "var c = \"A\";\r\n"
+ "clearInterval(5);\r\n"
+ "clearTimeout(4);\r\n"
+ "var mc;\r\n"
+ "duplicateMovieClip(mc,\"copy\",16389);\r\n"
+ "a = escape(\"how\");\r\n"
+ "var f = a;\r\n"
+ "fscommand(\"alert(\\\"hi\\\");\");\r\n"
+ "a = mc._alpha;\r\n"
+ "a = getTimer();\r\n"
+ "getURL(\"http://localhost/\",\"wnd\",\"POST\");\r\n"
+ "a = getVersion();\r\n"
+ "gotoAndPlay(5);\r\n"
+ "gotoAndStop(8);\r\n"
+ "ifFrameLoaded(4)\r\n"
+ "{\r\n"
+ "trace(\"loaded\");\r\n"
+ "}\r\n"
+ "a = int(f);\r\n"
+ "a = isFinite(f);\r\n"
+ "a = isNaN(f);\r\n"
+ "a = length(f);\r\n"
+ "loadMovie(\"http://localhost/test.swf\",a,\"GET\");\r\n"
+ "loadMovieNum(\"http://localhost/test.swf\",5,\"GET\");\r\n"
+ "loadVariables(\"http://localhost/vars.txt\",a,\"GET\");\r\n"
+ "loadVariablesNum(\"http://localhost/vars.txt\",4,\"GET\");\r\n"
+ "a = mbchr(f);\r\n"
+ "a = mblength(f);\r\n"
+ "a = mbord(f);\r\n"
+ "a = mbsubstring(\"aaaa\",5,4);\r\n"
+ "MMExecute(\"destroyPC\");\r\n"
+ "nextFrame();\r\n"
+ "gotoAndStop(1);\r\n"
+ "a = Number(f);\r\n"
+ "a = Object(f);\r\n"
+ "a = ord(f);\r\n"
+ "a = parseFloat(f);\r\n"
+ "a = parseInt(f,16);\r\n"
+ "play();\r\n"
+ "prevFrame();\r\n"
+ "gotoAndStop(1);\r\n"
+ "print(mc,\"bframe\");\r\n"
+ "printAsBitmap(mc,\"bframe\");\r\n"
+ "printAsBitmapNum(5,\"bframe\");\r\n"
+ "printNum(4,\"bframe\");\r\n"
+ "a = random(10);\r\n"
+ "removeMovieClip(mc);\r\n"
+ "setInterval(tst,5,f);\r\n"
+ "mc._alpha = 25;\r\n"
+ "setTimeout(tst,5,f);\r\n"
+ "showRedrawRegions(false,0);\r\n"
+ "startDrag(mc,1,5,5,6,6);\r\n"
+ "stop();\r\n"
+ "stopAllSounds();\r\n"
+ "stopDrag();\r\n"
+ "a = String(f);\r\n"
+ "a = \"aa\";\r\n"
+ "targetPath(f);\r\n"
+ "tellTarget(mc)\r\n"
+ "{\r\n"
+ "trace(\"told\")\r\n"
+ "};\r\n"
+ "toggleHighQuality();\r\n"
+ "a = unescape(f);\r\n"
+ "unloadMovie(mc);\r\n"
+ "unloadMovieNum(4);\r\n"
+ "updateAfterEvent();\r\n"
);
}
@Test
public void frame59_unaryOpTest() {
compareSrc(59, "trace(\"unaryOpTest\");\r\n"
+ "var a = 5;\r\n"
+ "var c = ~a;\r\n"
+ "var d = ~(a + c);\r\n"
+ "var e = - c;\r\n"
);
}
}

View File

@@ -0,0 +1,913 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
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.gui.Main;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.DoABCDefineTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Stack;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ActionScript3Test {
private SWF swf;
private int clsIndex;
private ABC abc;
@BeforeClass
public void init() throws IOException, InterruptedException {
Main.initLogging(false);
swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false);
DoABCDefineTag tag = null;
for (Tag t : swf.tags) {
if (t instanceof DoABCDefineTag) {
tag = (DoABCDefineTag) t;
break;
}
}
assertNotNull(tag);
clsIndex = tag.getABC().findClassByName("classes.Test");
assertTrue(clsIndex > -1);
this.abc = tag.getABC();
Configuration.autoDeobfuscate.set(false);
Configuration.decompile.set(true);
Configuration.registerNameFormat.set("_loc%d_");
}
private void decompileMethod(String methodName, String expectedResult, boolean isStatic) {
int bodyIndex = abc.findMethodBodyByName(clsIndex, methodName);
assertTrue(bodyIndex > -1);
HilightedTextWriter writer = null;
try {
abc.bodies.get(bodyIndex).convert(methodName, ScriptExportMode.AS, isStatic, -1/*FIX?*/, clsIndex, abc, null, abc.constants, abc.method_info, new Stack<GraphTargetItem>(), false, new NulWriter(), new ArrayList<String>(), abc.instance_info.get(clsIndex).instance_traits, true);
writer = new HilightedTextWriter(new CodeFormatting(), false);
abc.bodies.get(bodyIndex).toString(methodName, ScriptExportMode.AS, isStatic, -1/*FIX?*/, clsIndex, abc, null, abc.constants, abc.method_info, new Stack<GraphTargetItem>(), false, writer, new ArrayList<String>(), abc.instance_info.get(clsIndex).instance_traits);
} catch (InterruptedException ex) {
fail();
}
String actualResult = writer.toString().replaceAll("[ \r\n]", "");
expectedResult = expectedResult.replaceAll("[ \r\n]", "");
assertEquals(actualResult, expectedResult);
}
@Test
public void testHello() {
decompileMethod("testHello", "trace(\"hello\");\r\n", false);
}
@Test
public void testIncDec() {
decompileMethod("testIncDec", "var a:* = 5;\r\n"
+ "var b:* = 0;\r\n"
+ "trace(\"++var\");\r\n"
+ "b = ++a;\r\n"
+ "trace(\"var++\");\r\n"
+ "b = a++;\r\n"
+ "trace(\"--var\");\r\n"
+ "b = --a;\r\n"
+ "trace(\"var--\");\r\n"
+ "b = a--;\r\n"
+ "var c:* = [1,2,3,4,5];\r\n"
+ "trace(\"++arr\");\r\n"
+ "b = ++c[2];\r\n"
+ "trace(\"arr++\");\r\n"
+ "b = c[2]++;\r\n"
+ "trace(\"--arr\");\r\n"
+ "b = --c[2];\r\n"
+ "trace(\"arr--\");\r\n"
+ "b = c[2]--;\r\n"
+ "var d:* = new TestClass1();\r\n"
+ "trace(\"++property\");\r\n"
+ "trace(++d.attrib);\r\n"
+ "trace(\"property++\");\r\n"
+ "trace(d.attrib++);\r\n"
+ "trace(\"--property\");\r\n"
+ "trace(--d.attrib);\r\n"
+ "trace(\"property--\");\r\n"
+ "trace(d.attrib--);\r\n"
+ "trace(\"arr[e++]\");\r\n"
+ "var chars:Array = new Array(36);\r\n"
+ "var index:uint = 0;\r\n"
+ "chars[index++] = 5;\r\n"
+ "trace(\"arr[++e]\");\r\n"
+ "chars[++index] = 5;\r\n", false);
}
@Test
public void testDoWhile() {
decompileMethod("testDoWhile", "var a:* = 8;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "trace(\"a=\" + a);\r\n"
+ "a++;\r\n"
+ "}\r\n"
+ "while(a < 20);\r\n"
+ "\r\n", false);
}
@Test
public void testInnerTry() {
decompileMethod("testInnerTry", "try\r\n"
+ "{\r\n"
+ "try\r\n"
+ "{\r\n"
+ "trace(\"try body 1\");\r\n"
+ "}\r\n"
+ "catch(e:DefinitionError)\r\n"
+ "{\r\n"
+ "trace(\"catched DefinitionError\");\r\n"
+ "}\r\n"
+ "trace(\"after try 1\");\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "trace(\"catched Error\");\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"finally block\");\r\n"
+ "}\r\n", false);
}
@Test
public void testWhileContinue() {
decompileMethod("testWhileContinue", "var a:* = 5;\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "if(a == 9)\r\n"
+ "{\r\n"
+ "if(a == 8)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "if(a == 9)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"hello 1\");\r\n"
+ "}\r\n"
+ "trace(\"hello2\");\r\n"
+ "}\r\n", false);
}
@Test
public void testPrecedence() {
decompileMethod("testPrecedence", "var a:* = 0;\r\n"
+ "a = (5 + 6) * 7;\r\n"
+ "a = 5 * (2 + 3);\r\n"
+ "a = 5 + 6 * 7;\r\n"
+ "a = 5 * 2 + 2;\r\n"
+ "a = 5 * (25 % 3);\r\n"
+ "a = 5 % (24 * 307);\r\n"
+ "a = 1 / (2 / 3);\r\n"
+ "a = 1 / (2 * 3);\r\n"
+ "a = 1 * 2 * 3;\r\n"
+ "a = 1 * 2 / 3;\r\n"
+ "trace(\"a=\" + a);\r\n", false);
}
@Test
public void testStrings() {
decompileMethod("testStrings", "trace(\"hello\");\r\n"
+ "trace(\"quotes:\\\"hello!\\\"\");\r\n"
+ "trace(\"backslash: \\\\ \");\r\n"
+ "trace(\"single quotes: \\'hello!\\'\");\r\n"
+ "trace(\"new line \\r\\n hello!\");\r\n", false);
}
@Test
public void testContinueLevels() {
decompileMethod("testContinueLevels", "var b:* = undefined;\r\n"
+ "var c:* = undefined;\r\n"
+ "var d:* = undefined;\r\n"
+ "var e:* = undefined;\r\n"
+ "var a:* = 5;\r\n"
+ "loop3:\r\n"
+ "switch(a)\r\n"
+ "{\r\n"
+ "case 57 * a:\r\n"
+ "trace(\"fiftyseven multiply a\");\r\n"
+ "b = 0;\r\n"
+ "while(b < 50)\r\n"
+ "{\r\n"
+ "if(b == 10)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "if(b == 15)\r\n"
+ "{\r\n"
+ "break loop3;\r\n"
+ "}\r\n"
+ "b = b + 1;\r\n"
+ "}\r\n"
+ "break;\r\n"
+ "case 13:\r\n"
+ "trace(\"thirteen\");\r\n"
+ "case 14:\r\n"
+ "trace(\"fourteen\");\r\n"
+ "break;\r\n"
+ "case 89:\r\n"
+ "trace(\"eightynine\");\r\n"
+ "break;\r\n"
+ "default:\r\n"
+ "trace(\"default clause\");\r\n"
+ "}\r\n"
+ "c = 0;\r\n"
+ "loop1:\r\n"
+ "for(;c < 8;c = c + 1)\r\n"
+ "{\r\n"
+ "d = 0;\r\n"
+ "while(d < 25)\r\n"
+ "{\r\n"
+ "e = 0;\r\n"
+ "if(e < 50)\r\n"
+ "{\r\n"
+ "if(e == 9)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "if(e == 20)\r\n"
+ "{\r\n"
+ "continue loop1;\r\n"
+ "}\r\n"
+ "if(e != 8)\r\n"
+ "{\r\n"
+ "break loop1;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "d++;\r\n"
+ "}\r\n"
+ "trace(\"hello\");\r\n"
+ "}\r\n", false);
}
@Test
public void testSwitchDefault() {
decompileMethod("testSwitchDefault", "var a:* = 5;\r\n"
+ "switch(a)\r\n"
+ "{\r\n"
+ "case 57 * a:\r\n"
+ "trace(\"fiftyseven multiply a\");\r\n"
+ "break;\r\n"
+ "case 13:\r\n"
+ "trace(\"thirteen\");\r\n"
+ "case 14:\r\n"
+ "trace(\"fourteen\");\r\n"
+ "break;\r\n"
+ "case 89:\r\n"
+ "trace(\"eightynine\");\r\n"
+ "break;\r\n"
+ "default:\r\n"
+ "trace(\"default clause\");\r\n"
+ "}\r\n", false);
}
@Test
public void testMultipleCondition() {
decompileMethod("testMultipleCondition", "var a:* = 5;\r\n"
+ "var b:* = 8;\r\n"
+ "var c:* = 9;\r\n"
+ "if((a <= 4 || b <= 8) && c == 7)\r\n"
+ "{\r\n"
+ "trace(\"onTrue\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"onFalse\");\r\n"
+ "}\r\n", false);
}
@Test
public void testForBreak() {
decompileMethod("testForBreak", "var a:* = 0;\r\n"
+ "while(a < 10)\r\n"
+ "{\r\n"
+ "if(a == 5)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"hello:\" + a);\r\n"
+ "a++;\r\n"
+ "}\r\n", false);
}
@Test
public void testIf() {
decompileMethod("testIf", "var a:* = 5;\r\n"
+ "if(a == 7)\r\n"
+ "{\r\n"
+ "trace(\"onTrue\");\r\n"
+ "}\r\n", false);
}
@Test
public void testIfElse() {
decompileMethod("testIfElse", "var a:* = 5;\r\n"
+ "if(a == 7)\r\n"
+ "{\r\n"
+ "trace(\"onTrue\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"onFalse\");\r\n"
+ "}\r\n", false);
}
@Test
public void testFor() {
decompileMethod("testFor", "var a:* = 0;\r\n"
+ "while(a < 10)\r\n"
+ "{\r\n"
+ "trace(\"a=\" + a);\r\n"
+ "a++;\r\n"
+ "}\r\n", false);
}
@Test
public void testForContinue() {
decompileMethod("testForContinue", "var a:* = 0;\r\n"
+ "for(;a < 10;a = a + 1)\r\n"
+ "{\r\n"
+ "if(a == 9)\r\n"
+ "{\r\n"
+ "if(a == 5)\r\n"
+ "{\r\n"
+ "trace(\"part1\");\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"a=\" + a);\r\n"
+ "if(a == 7)\r\n"
+ "{\r\n"
+ "trace(\"part2\");\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"part3\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"part4\");\r\n"
+ "}\r\n"
+ "trace(\"part5\");\r\n"
+ "}\r\n", false);
}
@Test
public void testTry() {
decompileMethod("testTry", "var i:int = 0;\r\n"
+ "i = 7;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "trace(\"try body\");\r\n"
+ "}\r\n"
+ "catch(e:DefinitionError)\r\n"
+ "{\r\n"
+ "trace(\"catched DefinitionError\");\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "trace(\"Error message:\" + e.message);\r\n"
+ "trace(\"Stacktrace:\" + e.getStackTrace());\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"Finally part\");\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n", false);
}
@Test
public void testSwitch() {
decompileMethod("testSwitch", "var a:* = 5;\r\n"
+ "switch(a)\r\n"
+ "{\r\n"
+ "case 57 * a:\r\n"
+ "trace(\"fiftyseven multiply a\");\r\n"
+ "break;\r\n"
+ "case 13:\r\n"
+ "trace(\"thirteen\");\r\n"
+ "case 14:\r\n"
+ "trace(\"fourteen\");\r\n"
+ "break;\r\n"
+ "case 89:\r\n"
+ "trace(\"eightynine\");\r\n"
+ "break;\r\n"
+ "}\r\n", false);
}
@Test
public void testTernarOperator() {
decompileMethod("testTernarOperator", "var a:* = 5;\r\n"
+ "var b:* = 4;\r\n"
+ "var c:* = 4;\r\n"
+ "var d:* = 78;\r\n"
+ "var e:* = a == b?c == d?1:7:3;\r\n"
+ "trace(\"e=\" + e);\r\n", false);
}
@Test
public void testInnerIf() {
decompileMethod("testInnerIf", "var a:* = 5;\r\n"
+ "var b:* = 4;\r\n"
+ "if(a == 5)\r\n"
+ "{\r\n"
+ "if(b == 6)\r\n"
+ "{\r\n"
+ "trace(\"b==6\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"b!=6\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "else if(b == 7)\r\n"
+ "{\r\n"
+ "trace(\"b==7\");\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "trace(\"b!=7\");\r\n"
+ "}\r\n"
+ "\r\n"
+ "trace(\"end\");\r\n", false);
}
@Test
public void testVector() {
decompileMethod("testVector", "var v:Vector.<String> = new Vector.<String>();\r\n"
+ "v.push(\"hello\");\r\n"
+ "v[0] = \"hi\";\r\n"
+ "v[5 * 8 - 39] = \"hi2\";\r\n"
+ "trace(v[0]);\r\n", false);
}
@Test
public void testProperty() {
decompileMethod("testProperty", "var d:* = new TestClass1();\r\n"
+ "var k:* = 7 + 8;\r\n"
+ "if(k == 15)\r\n"
+ "{\r\n"
+ "d.method(d.attrib * 5);\r\n"
+ "}\r\n", false);
}
@Test
public void testRest() {
decompileMethod("testRest", "trace(\"firstRest:\" + restval[0]);\r\n"
+ "return firstp;\r\n", false);
}
@Test
public void testParamNames() {
decompileMethod("testParamNames", "return firstp + secondp + thirdp;\r\n", false);
}
@Test
public void testForEach() {
decompileMethod("testForEach", "var list:Array = null;\r\n"
+ "var item:* = undefined;\r\n"
+ "list = new Array();\r\n"
+ "list[0] = \"first\";\r\n"
+ "list[1] = \"second\";\r\n"
+ "list[2] = \"third\";\r\n"
+ "for each(item in list)\r\n"
+ "{\r\n"
+ "trace(\"item #\" + item);\r\n"
+ "}\r\n", false);
}
@Test
public void testForEachObjectArray() {
decompileMethod("testForEachObjectArray", "var list:Array = null;\r\n"
+ "var test:Array = null;\r\n"
+ "list = new Array();\r\n"
+ "list[0] = \"first\";\r\n"
+ "list[1] = \"second\";\r\n"
+ "list[2] = \"third\";\r\n"
+ "test = new Array();\r\n"
+ "test[0] = 0;\r\n"
+ "for each(test[0] in list)\r\n"
+ "{\r\n"
+ "trace(\"item #\" + test[0]);\r\n"
+ "}\r\n", false);
}
@Test
public void testForEachObjectAttribute() {
decompileMethod("testForEachObjectAttribute", "var list:Array = null;\r\n"
+ "list = new Array();\r\n"
+ "list[0] = \"first\";\r\n"
+ "list[1] = \"second\";\r\n"
+ "list[2] = \"third\";\r\n"
+ "for each(this.testPriv in list)\r\n"
+ "{\r\n"
+ "trace(\"item #\" + this.testPriv);\r\n"
+ "}\r\n", false);
}
@Test
public void testParamsCount() {
decompileMethod("testParamsCount", "return firstp;\r\n", false);
}
@Test
public void testInlineFunctions() {
decompileMethod("testInlineFunctions", "var first:String = null;\r\n"
+ "first = \"value1\";\r\n"
+ "var traceParameter:Function = function(aParam:String):String\r\n"
+ "{\r\n"
+ "var second:String = null;\r\n"
+ "second = \"value2\";\r\n"
+ "second = second + \"cc\";\r\n"
+ "var traceParam2:Function = function(bParam:String):String\r\n"
+ "{\r\n"
+ "trace(bParam + \",\" + aParam);\r\n"
+ "return first + second + aParam + bParam;\r\n"
+ "};\r\n"
+ "trace(second);\r\n"
+ "traceParam2(aParam);\r\n"
+ "return first;\r\n"
+ "};\r\n"
+ "traceParameter(\"hello\");\r\n", false);
}
@Test
public void testMissingDefault() {
decompileMethod("testMissingDefault", "var jj:* = 1;\r\n"
+ "switch(jj)\r\n"
+ "{\r\n"
+ "case 1:\r\n"
+ "jj = 1;\r\n"
+ "break;\r\n"
+ "case 2:\r\n"
+ "jj = 2;\r\n"
+ "break;\r\n"
+ "default:\r\n"
+ "jj = 3;\r\n"
+ "}\r\n", false);
}
@Test
public void testChainedAssignments() {
decompileMethod("testChainedAssignments", "var a:* = 0;\r\n"
+ "var b:* = 0;\r\n"
+ "var c:* = 0;\r\n"
+ "var d:* = 0;\r\n"
+ "d = c = b = a = 5;\r\n"
+ "var e:TestClass2 = TestClass2.createMe(\"test\");\r\n"
+ "e.attrib1 = e.attrib2 = e.attrib3 = this.getCounter();\r\n"
+ "this.traceIt(e.toString());\r\n", false);
}
@Test
public void testFinallyZeroJump() {
decompileMethod("testFinallyZeroJump", "var str:String = param1;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "trace(\"error is :\" + e.message);\r\n"
+ "}\r\n"
+ "finally\r\n"
+ "{\r\n"
+ "trace(\"hi \");\r\n"
+ "if(5 == 4)\r\n"
+ "{\r\n"
+ "return str;\r\n"
+ "}\r\n"
+ "return \"hu\" + str;\r\n"
+ "}\r\n", false);
}
@Test
public void testInnerFunctions() {
decompileMethod("testInnerFunctions", "var s:int = 0;\r\n"
+ "var innerFunc:Function = function(b:String):*\r\n"
+ "{\r\n"
+ "trace(b);\r\n"
+ "};\r\n"
+ "var k:int = 5;\r\n"
+ "if(k == 6)\r\n"
+ "{\r\n"
+ "s = 8;\r\n"
+ "}\r\n"
+ "innerFunc(a);\r\n", false);
}
@Test
public void testDeclarations() {
decompileMethod("testDeclarations", "var vall:* = undefined;\r\n"
+ "var vstr:String = null;\r\n"
+ "var vint:* = 0;\r\n"
+ "var vuint:uint = 0;\r\n"
+ "var vclass:TestClass1 = null;\r\n"
+ "var vnumber:* = NaN;\r\n"
+ "var vobject:Object = null;\r\n"
+ "vall = 6;\r\n"
+ "vstr = \"hello\";\r\n"
+ "vuint = 7;\r\n"
+ "vint = -4;\r\n"
+ "vclass = new TestClass1();\r\n"
+ "vnumber = 0.5;\r\n"
+ "vnumber = 6;\r\n"
+ "vobject = vclass;\r\n", false);
}
@Test
public void testForIn() {
decompileMethod("testForIn", "var dic:Dictionary = null;\r\n"
+ "var item:Object = null;\r\n"
+ "for(item in dic)\r\n"
+ "{\r\n"
+ "trace(item);\r\n"
+ "}\r\n"
+ "for each(item in dic)\r\n"
+ "{\r\n"
+ "trace(item);\r\n"
+ "}\r\n", false);
}
@Test
public void testNames() {
decompileMethod("testNames", "var ns:* = this.getNamespace();\r\n"
+ "var name:* = this.getName();\r\n"
+ "var a:* = ns::unnamespacedFunc();\r\n"
+ "var b:* = ns::[name];\r\n"
+ "trace(b.c);\r\n"
+ "var c:* = myInternal::neco;\r\n", false);
}
@Test
public void testComplexExpressions() {
decompileMethod("testComplexExpressions", "var i:* = 0;\r\n"
+ "var j:* = 0;\r\n"
+ "j = i = i + (i = i + i++);\r\n", false);
}
@Test
public void testExpressions() {
decompileMethod("testExpressions", "var arr:Array = null;\r\n"
+ "var i:* = 5;\r\n"
+ "var j:* = 5;\r\n"
+ "if((i = i = i / 2) == 1 || i == 2)\r\n"
+ "{\r\n"
+ "arguments.concat(i);\r\n"
+ "}\r\n"
+ "else if(i == 0)\r\n"
+ "{\r\n"
+ "i = j++;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "arr[0]();\r\n"
+ "}\r\n"
+ "\r\n"
+ "return i == 0;\r\n", false);
}
@Test
public void testArguments() {
decompileMethod("testArguments", "return arguments[0];\r\n", false);
}
@Test
public void testLogicalComputing() {
decompileMethod("testLogicalComputing", "var b:* = false;\r\n"
+ "var i:* = 5;\r\n"
+ "var j:* = 7;\r\n"
+ "if(i > j)\r\n"
+ "{\r\n"
+ "j = 9;\r\n"
+ "b = true;\r\n"
+ "}\r\n"
+ "b = (i == 0 || i == 1) && j == 0;\r\n", false);
}
@Test
public void testInc2() {
decompileMethod("testInc2", "var a:* = [1];\r\n"
+ "a[this.getInt()]++;\r\n"
+ "var d:* = a[this.getInt()]++;\r\n"
+ "var e:* = ++a[this.getInt()];\r\n"
+ "var b:* = 1;\r\n"
+ "b++;\r\n"
+ "var c:* = 1;\r\n"
+ "b = c++;\r\n", false);
}
@Test
public void testDecl2() {
decompileMethod("testDecl2", "var k:* = 0;\r\n"
+ "var i:* = 5;\r\n"
+ "i = i + 7;\r\n"
+ "if(i == 5)\r\n"
+ "{\r\n"
+ "if(i < 8)\r\n"
+ "{\r\n"
+ "k = 6;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "k = 7;\r\n", false);
}
@Test
public void testChain2() {
decompileMethod("testChain2", "var g:Array = null;\r\n"
+ "var h:* = false;\r\n"
+ "var extraLine:* = false;\r\n"
+ "var r:* = 7;\r\n"
+ "var t:* = 0;\r\n"
+ "t = this.getInt();\r\n"
+ "if(t + 1 < g.length)\r\n"
+ "{\r\n"
+ "t++;\r\n"
+ "h = true;\r\n"
+ "}\r\n"
+ "if(t >= 0)\r\n"
+ "{\r\n"
+ "trace(\"ch\");\r\n"
+ "}\r\n", false);
}
@Test
public void testDoWhile2() {
decompileMethod("testDoWhile2", "var k:* = 5;\r\n"
+ "do\r\n"
+ "{\r\n"
+ "k++;\r\n"
+ "if(k == 7)\r\n"
+ "{\r\n"
+ "k = 5 * k;\r\n"
+ "}\r\n"
+ "else\r\n"
+ "{\r\n"
+ "k = 5 - k;\r\n"
+ "}\r\n"
+ "k--;\r\n"
+ "}\r\n"
+ "while(k < 9);\r\n"
+ "\r\n"
+ "return 2;\r\n", false);
}
@Test
public void testWhileAnd() {
decompileMethod("testWhileAnd", "var a:* = 5;\r\n"
+ "var b:* = 10;\r\n"
+ "while(a < 10 && b > 1)\r\n"
+ "{\r\n"
+ "a++;\r\n"
+ "b--;\r\n"
+ "}\r\n"
+ "a = 7;\r\n"
+ "b = 9;\r\n", false);
}
@Test
public void testNamedAnonFunctions() {
decompileMethod("testNamedAnonFunctions", "var test:* = new function testFunc(param1:*, param2:int, param3:Array):Boolean\r\n"
+ "{\r\n"
+ "return (param1 as TestClass2).attrib1 == 5;\r\n"
+ "};\r\n", false);
}
@Test
public void testStringConcat() {
decompileMethod("testStringConcat", "var k:* = 8;\r\n"
+ "this.traceIt(\"hello\" + 5 * 6);\r\n"
+ "this.traceIt(\"hello\" + (k - 1));\r\n"
+ "this.traceIt(\"hello\" + 5 + 6);\r\n", false);
}
@Test
public void testWhileTry() {
decompileMethod("testWhileTry", "while(true)\r\n"
+ "{\r\n"
+ "try\r\n"
+ "{\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "trace(\"a\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "catch(e:EOFError)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "}\r\n", false);
}
@Test
public void testWhileTry2() {
decompileMethod("testWhileTry2", "var j:* = undefined;\r\n"
+ "var i:* = 0;\r\n"
+ "for(;i < 100;i++)\r\n"
+ "{\r\n"
+ "try\r\n"
+ "{\r\n"
+ "j = 0;\r\n"
+ "while(j < 20)\r\n"
+ "{\r\n"
+ "trace(\"a\");\r\n"
+ "j++;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "catch(e:EOFError)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "continue;\r\n"
+ "}\r\n"
+ "trace(\"after_try\");\r\n"
+ "}\r\n"
+ "trace(\"end\");\r\n", false);
}
@Test
public void testTryReturn() {
decompileMethod("testTryReturn", "var i:int = 0;\r\n"
+ "var b:Boolean = false;\r\n"
+ "try\r\n"
+ "{\r\n"
+ "i = 0;\r\n"
+ "b = true;\r\n"
+ "if(i > 0)\r\n"
+ "{\r\n"
+ "while(this.testDoWhile2())\r\n"
+ "{\r\n"
+ "if(b)\r\n"
+ "{\r\n"
+ "return 5;\r\n"
+ "}\r\n"
+ "}\r\n"
+ "}\r\n"
+ "i++;\r\n"
+ "return 2;\r\n"
+ "}\r\n"
+ "catch(e:Error)\r\n"
+ "{\r\n"
+ "}\r\n"
+ "return 4;\r\n", false);
}
@Test
public void testVector2() {
decompileMethod("testVector2", "var a:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();\r\n"
+ "var b:Vector.<int> = new <int>[10,20,30];\r\n", false);
}
@Test
public void testOptionalParameters() {
String methodName = "testOptionalParameters";
int methodInfo = abc.findMethodInfoByName(clsIndex, methodName);
int bodyIndex = abc.findMethodBodyByName(clsIndex, methodName);
assertTrue(methodInfo > -1);
assertTrue(bodyIndex > -1);
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
abc.method_info.get(methodInfo).getParamStr(writer, abc.constants, abc.bodies.get(bodyIndex), abc, new ArrayList<String>());
String actualResult = writer.toString().replaceAll("[ \r\n]", "");
String expectedResult = "p1:Event=null,p2:Number=1,p3:Number=-1,p4:Number=-1.1,p5:Number=-1.1,p6:String=\"a\"";
expectedResult = expectedResult.replaceAll("[ \r\n]", "");
assertEquals(actualResult, expectedResult);
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.Tag;
/**
*
* @author JPEXS
*/
public class ActionStript2TestBase {
protected SWF swf;
protected DoActionTag getFirstActionTag() {
for (Tag t : swf.tags) {
if (t instanceof DoActionTag) {
return (DoActionTag) t;
}
}
return null;
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.Main;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class ExportTest {
@BeforeClass
public void init(){
Main.initLogging(false);
}
public static final String TESTDATADIR = "testdata/decompile";
@BeforeClass
public void addLogger() {
Configuration.autoDeobfuscate.set(true);
Logger logger = Logger.getLogger("");
logger.addHandler(new Handler() {
@Override
public void publish(LogRecord record) {
if (record.getLevel() == Level.SEVERE) {
fail("Error during decompilation", record.getThrown());
}
}
@Override
public void flush() {
}
@Override
public void close() throws SecurityException {
}
});
}
@DataProvider(name = "swfFiles")
public Object[][] createData() {
File dir = new File(TESTDATADIR);
if (!dir.exists()) {
return new Object[0][0];
}
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".swf");
}
});
Object[][] ret = new Object[files.length][1];
for (int i = 0; i < files.length; i++) {
ret[i][0] = files[i];
}
return ret;
}
@Test(dataProvider = "swfFiles")
public void testDecompileAS(File f) {
testDecompile(f, ScriptExportMode.AS);
}
@Test(dataProvider = "swfFiles")
public void testDecompilePcode(File f) {
testDecompile(f, ScriptExportMode.PCODE);
}
public void testDecompile(File f, ScriptExportMode exportMode) {
try {
SWF swf = new SWF(new FileInputStream(f), false);
Configuration.debugCopy.set(true);
String folderName = exportMode == ScriptExportMode.AS ? "output" : "outputp";
File fdir = new File(TESTDATADIR + File.separator + folderName + File.separator + f.getName());
fdir.mkdirs();
swf.exportActionScript(new AbortRetryIgnoreHandler() {
@Override
public int handle(Throwable thrown) {
return AbortRetryIgnoreHandler.ABORT;
}
@Override
public AbortRetryIgnoreHandler getNewInstance() {
return this;
}
}, fdir.getAbsolutePath(), exportMode, false);
} catch (Exception ex) {
fail();
}
}
}

View File

@@ -0,0 +1,184 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.ClassPath;
import com.jpexs.decompiler.flash.abc.NotSameException;
import com.jpexs.decompiler.flash.abc.ScriptPack;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.parser.ParseException;
import com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.flash.tags.base.ContainerItem;
import com.jpexs.decompiler.flash.treeitems.TreeItem;
import com.jpexs.decompiler.flash.treenodes.TagNode;
import com.jpexs.decompiler.flash.treenodes.TreeNode;
import com.jpexs.decompiler.graph.CompilationException;
import com.jpexs.decompiler.graph.TranslateException;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.testng.Assert.fail;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class RecompileTest {
@BeforeClass
public void init() {
Main.initLogging(false);
}
public static final String TESTDATADIR = "testdata/recompile";
@Test(dataProvider = "provideFiles")
public void testRecompile(String filename) {
try {
SWF swf = new SWF(new BufferedInputStream(new FileInputStream(TESTDATADIR + File.separator + filename)), false);
Configuration.debugCopy.set(true);
swf.saveTo(new ByteArrayOutputStream());
} catch (IOException | InterruptedException ex) {
fail();
} catch (NotSameException ex) {
fail("File is different after recompiling: " + filename);
}
}
private void testAS2DirectEditingOneRecursive(List<TreeNode> nodeList) {
for (TreeNode node : nodeList) {
if (node.subNodes.isEmpty()) {
TreeItem item = node.getItem();
if ((item instanceof ASMSource) && (node.export)) {
try {
ASMSource asm = ((ASMSource) item);
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(asm, asm.getActions(), asm.toString()/*FIXME?*/, writer);
String as = writer.toString();
as = asm.removePrefixAndSuffix(as);
ActionScriptParser par = new ActionScriptParser();
try {
asm.setActions(par.actionsFromString(as));
} catch (ParseException | CompilationException ex) {
fail("Unable to parse: " + item.getSwf().getShortFileName() + "/" + item.toString());
}
writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(asm, asm.getActions(), asm.toString()/*FIXME?*/, writer);
String as2 = writer.toString();
as2 = asm.removePrefixAndSuffix(as2);
try {
asm.setActions(par.actionsFromString(as2));
} catch (ParseException | CompilationException ex) {
fail("Unable to parse: " + item.getSwf().getShortFileName() + "/" + item.toString());
}
writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(asm, asm.getActions(), asm.toString()/*FIXME?*/, writer);
String as3 = writer.toString();
as3 = asm.removePrefixAndSuffix(as3);
if (!as3.equals(as2)) {
fail("ActionScript is different: " + item.getSwf().getShortFileName() + "/" + item.toString());
}
} catch (InterruptedException | IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) {
}
}
} else {
testAS2DirectEditingOneRecursive(node.subNodes);
}
}
}
@Test(dataProvider = "provideFiles")
public void testDirectEditing(String filename) throws IOException, InterruptedException, com.jpexs.decompiler.flash.abc.avm2.parser.ParseException, CompilationException {
Configuration.autoDeobfuscate.set(false);
try{SWF swf = new SWF(new BufferedInputStream(new FileInputStream(TESTDATADIR + File.separator + filename)), false);
if (swf.fileAttributes.actionScript3) {
boolean dotest=false;
List<ABC> allAbcs = new ArrayList<>();
for (ABCContainerTag ct : swf.abcList) {
allAbcs.add(ct.getABC());
}
for (ABC abc : allAbcs) {
for (int s = 0; s < abc.script_info.size(); s++) {
String startAfter=null;
HilightedTextWriter htw = new HilightedTextWriter(new CodeFormatting(), false);
MyEntry<ClassPath, ScriptPack> en = abc.script_info.get(s).getPacks(abc, s).get(0);
if(startAfter==null || en.key.toString().equals(startAfter)){
dotest = true;
}
if(!dotest){
System.out.println("Skipped:"+en.key.toString());
continue;
}
System.out.println("Recompiling:"+en.key.toString()+"...");
en.value.toSource(htw, swf.abcList, abc.script_info.get(s).traits.traits, ScriptExportMode.AS, false);
String original = htw.toString();
ABC nabc = new ABC(swf);
com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser.compile(original, nabc,allAbcs, false, en.key.className + ".as");
}
}
} else {
List<ContainerItem> list2 = new ArrayList<>();
list2.addAll(swf.tags);
List<TreeNode> list = SWF.createASTagList(list2, null);
TagNode.setExport(list, true);
testAS2DirectEditingOneRecursive(list);
}
}catch(Exception ex){
System.out.println("FAIL");
throw ex;
}
}
@DataProvider(name = "provideFiles")
public Object[][] provideFiles() {
File dir = new File(TESTDATADIR);
if (!dir.exists()) {
return new Object[0][];
}
File[] files = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".swf");
}
});
Object[][] ret = new Object[files.length][1];
for (int f = 0; f < files.length; f++) {
ret[f][0] = files[f].getName();
}
return ret;
}
}

View File

@@ -0,0 +1,185 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.types.RECT;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
*
* @author JPEXS
*/
public class SWFStreamTest {
@BeforeClass
public void init(){
Main.initLogging(false);
}
@Test
public void testNeededBits() {
assertEquals(SWFOutputStream.getNeededBitsU(3), 2);
assertEquals(SWFOutputStream.getNeededBitsU(255), 8);
assertEquals(SWFOutputStream.getNeededBitsS(3), 3);
assertEquals(SWFOutputStream.getNeededBitsS(255), 9);
assertEquals(SWFOutputStream.getNeededBitsS(-2), 3);
assertEquals(SWFOutputStream.getNeededBitsS(-597), 11);
assertEquals(SWFOutputStream.getNeededBitsF(15.5f), 21);
assertEquals(SWFOutputStream.getNeededBitsF(0.1f), 17);
assertEquals(SWFOutputStream.getNeededBitsF(-2.8891602f), 19);
}
@Test
public void testFB() throws IOException {
double f = 5.25;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) {
sos.writeFB(20, f);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (SWFInputStream sis = new SWFInputStream(bais, 10)) {
assertTrue(Double.compare(f, sis.readFB(20)) == 0);
}
}
@Test
public void testUB() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) {
sos.writeUB(5, 1);
sos.writeUB(6, 2);
sos.writeUB(7, 3);
sos.writeUB(8, 4);
sos.writeUB(9, 5);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (SWFInputStream sis = new SWFInputStream(bais, 10)) {
assertEquals(1, sis.readUB(5));
assertEquals(2, sis.readUB(6));
assertEquals(3, sis.readUB(7));
assertEquals(4, sis.readUB(8));
assertEquals(5, sis.readUB(9));
}
}
@Test
public void testSB() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) {
sos.writeSB(5, -1);
sos.writeSB(6, 2);
sos.writeSB(7, -3);
sos.writeSB(8, 4);
sos.writeSB(9, -5);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (SWFInputStream sis = new SWFInputStream(bais, 10)) {
assertEquals(-1, sis.readSB(5));
assertEquals(2, sis.readSB(6));
assertEquals(-3, sis.readSB(7));
assertEquals(4, sis.readSB(8));
assertEquals(-5, sis.readSB(9));
}
}
@Test
public void testFLOATAndDouble() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, 10);
float f = 5.25f;
sos.writeFLOAT(f);
sos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
SWFInputStream sis = new SWFInputStream(bais, 10);
assertEquals(f, sis.readFLOAT());
sis.close();
baos = new ByteArrayOutputStream();
sos = new SWFOutputStream(baos, 10);
f = 5.25f;
sos.writeFLOAT16(f);
sos.close();
bais = new ByteArrayInputStream(baos.toByteArray());
sis = new SWFInputStream(bais, 10);
assertEquals(f, sis.readFLOAT16());
sis.close();
baos = new ByteArrayOutputStream();
sos = new SWFOutputStream(baos, 10);
double d = 5.25;
sos.writeDOUBLE(d);
sos.close();
bais = new ByteArrayInputStream(baos.toByteArray());
sis = new SWFInputStream(bais, 10);
assertEquals(d, sis.readDOUBLE());
sis.close();
}
@Test
public void testFIXEDandFIXED8() throws IOException {
//example from specification
ByteArrayInputStream bais = new ByteArrayInputStream(new byte[]{(byte) 0x00, (byte) 0x80, (byte) 0x07, (byte) 0x00});
SWFInputStream sis = new SWFInputStream(bais, 10);
assertTrue(Double.compare(7.5, sis.readFIXED()) == 0);
sis.close();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
SWFOutputStream sos = new SWFOutputStream(baos, 10);
double dd = 5.25;
sos.writeFIXED(dd);
sos.close();
bais = new ByteArrayInputStream(baos.toByteArray());
sis = new SWFInputStream(bais, 10);
assertTrue(Double.compare(dd, sis.readFIXED()) == 0);
sis.close();
baos = new ByteArrayOutputStream();
sos = new SWFOutputStream(baos, 10);
float ff = 5.25f;
sos.writeFIXED8(ff);
sos.close();
bais = new ByteArrayInputStream(baos.toByteArray());
sis = new SWFInputStream(bais, 10);
assertEquals(ff, sis.readFIXED8());
sis.close();
}
@Test
public void testRECT() throws IOException {
RECT rect;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (SWFOutputStream sos = new SWFOutputStream(baos, 10)) {
rect = new RECT(-0x80000000, 0x7FFFFFFF, -0x80000000, 0x7FFFFFFF);
sos.writeRECT(rect);
}
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
try (SWFInputStream sis = new SWFInputStream(bais, 10)) {
RECT readRECT = sis.readRECT();
assertEquals(readRECT.Xmin, -0x3FFFFFFF);
assertEquals(readRECT.Xmax, 0x3FFFFFFF);
assertEquals(readRECT.Ymin, -0x3FFFFFFF);
assertEquals(readRECT.Ymax, 0x3FFFFFFF);
}
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.generators;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.tags.DoABCDefineTag;
import com.jpexs.decompiler.flash.tags.DoActionTag;
import com.jpexs.decompiler.flash.tags.ShowFrameTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
/**
*
* Generates stub for ActionScript2Test
*
* @author JPEXS
*/
public class AS2Generator {
public static void main(String[] args) throws Exception {
Configuration.autoDeobfuscate.set(false);
SWF swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false);
DoABCDefineTag tag = null;
DoActionTag doa = null;
int frame = 0;
StringBuilder s = new StringBuilder();
for (Tag t : swf.tags) {
if (t instanceof DoActionTag) {
doa = (DoActionTag) t;
}
if (t instanceof ShowFrameTag) {
frame++;
if (doa == null) {
continue;
}
HilightedTextWriter writer = new HilightedTextWriter(new CodeFormatting(), false);
Action.actionsToSource(doa, doa.getActions(), "", writer);
String src = writer.toString();
if (src.trim().isEmpty()) {
doa = null;
continue;
}
String[] srcs = src.split("[\r\n]+");
String testName = "frame" + frame + "_Test";
String pref = "trace(\"";
for (String p : srcs) {
if (p.trim().matches("trace\\(\"(.*)Test\"\\);")) {
testName = "frame" + frame + "_" + p.substring(pref.length(), p.length() - 3/* "); */);
}
}
s.append("@Test\r\npublic void ");
s.append(testName);
s.append("(){\r\ncompareSrc(");
s.append(frame);
s.append(",");
for (int i = 0; i < srcs.length; i++) {
String ss = srcs[i];
s.append("\"");
s.append(ss.trim().replace("\\", "\\\\").replace("\"", "\\\""));
s.append("\\r\\n\"");
if (i < srcs.length - 1) {
s.append("+");
}
s.append("\r\n");
}
s.append(");");
s.append("}");
doa = null;
}
/*try (PrintWriter pw = new PrintWriter("as2_teststub.java")) {
pw.println(s.toString());
}*/
try (FileOutputStream fos = new FileOutputStream("as2_teststub.java")) {
fos.write(Utf8Helper.getBytes(s.toString()));
}
}
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2010-2014 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.jpexs.decompiler.flash.generators;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.HilightedTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.tags.DoABCDefineTag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.graph.GraphTargetItem;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Stack;
/**
*
* Generates stub for ActionScript3Test
*
* @author JPEXS
*/
public class AS3Generator {
public static void main(String[] args) throws Exception {
Configuration.autoDeobfuscate.set(false);
SWF swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as3/as3.swf")), false);
DoABCDefineTag tag = null;
for (Tag t : swf.tags) {
if (t instanceof DoABCDefineTag) {
tag = (DoABCDefineTag) t;
break;
}
}
ABC abc = tag.getABC();
int classId = abc.findClassByName("classes.Test");
StringBuilder s = new StringBuilder();
for (Trait t : abc.instance_info.get(classId).instance_traits.traits) {
if (t instanceof TraitMethodGetterSetter) {
String name = t.getName(abc).getName(abc.constants, new ArrayList<String>());
if (name.startsWith("test")) {
s.append("@Test\r\npublic void ");
s.append(name);
s.append("(){\r\ndecompileMethod(\"");
s.append(name);
s.append("\", ");
HilightedTextWriter src = new HilightedTextWriter(new CodeFormatting(), false);
MethodBody b = abc.findBody(((TraitMethodGetterSetter) t).method_info);
b.convert("", ScriptExportMode.AS, false, -1/*FIX?*/, classId, abc, null, abc.constants, abc.method_info, new Stack<GraphTargetItem>(), false, new NulWriter(), new ArrayList<String>(), abc.instance_info.get(classId).instance_traits, true);
b.toString("", ScriptExportMode.AS, false, -1/*FIX?*/, classId, abc, null, abc.constants, abc.method_info, new Stack<GraphTargetItem>(), false, src, new ArrayList<String>(), abc.instance_info.get(classId).instance_traits);
String[] srcs = src.toString().split("[\r\n]+");
for (int i = 0; i < srcs.length; i++) {
String ss = srcs[i];
s.append("\"");
s.append(ss.trim().replace("\\", "\\\\").replace("\"", "\\\""));
s.append("\\r\\n\"");
if (i < srcs.length - 1) {
s.append("+");
}
s.append("\r\n");
}
s.append(", false);");
s.append("}");
}
}
try (PrintWriter pw = new PrintWriter("as3_teststub.java")) {
pw.println(s.toString());
}
}
}
}