dissasembly progress percent view

better text tags editing - parameters
This commit is contained in:
Jindra Petk
2013-04-30 22:45:51 +02:00
parent fd854991f8
commit f18305bb9e
24 changed files with 1035 additions and 356 deletions

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2013 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;
/**
*
* @author JPEXS
*/
public interface DisassemblyListener {
public void progress(String phase, long pos, long total);
}

View File

@@ -81,4 +81,8 @@ public class ReReadableInputStream extends InputStream {
public int available() throws IOException {
return (count + is.available()) - pos;
}
public long length() throws IOException {
return count + is.available();
}
}

View File

@@ -502,22 +502,25 @@ public class SWFInputStream extends InputStream {
return ret;
}
public List<Action> readActionList(long address, long containerSWFOffset) throws IOException {
public List<Action> readActionList(List<DisassemblyListener> listeners, long address, long containerSWFOffset) throws IOException {
ReReadableInputStream rri = new ReReadableInputStream(this);
return readActionList(address, containerSWFOffset, rri, version, 0, -1);
return readActionList(listeners, address, containerSWFOffset, rri, version, 0, -1);
}
public List<Action> readActionList(long address, long containerSWFOffset, ReReadableInputStream rri, int maxlen) throws IOException {
return readActionList(address, containerSWFOffset, rri, version, rri.getPos(), rri.getPos() + maxlen);
public List<Action> readActionList(List<DisassemblyListener> listeners, long address, long containerSWFOffset, ReReadableInputStream rri, int maxlen) throws IOException {
return readActionList(listeners, address, containerSWFOffset, rri, version, rri.getPos(), rri.getPos() + maxlen);
}
private static void getConstantPool(ConstantPool cpool, List localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, int lastIp, List<ConstantPool> constantPools, List<Integer> visited, int version, int endIp) {
private static void getConstantPool(List<DisassemblyListener> listeners, ConstantPool cpool, List localData, Stack<GraphTargetItem> stack, List<GraphTargetItem> output, ActionGraphSource code, int ip, int lastIp, List<ConstantPool> constantPools, List<Integer> visited, int version, int endIp) {
boolean debugMode = false;
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
while (((endIp == -1) || (endIp > ip)) && (ip > -1) && ip < code.size()) {
if (visited.contains(ip)) {
break;
}
for (DisassemblyListener listener : listeners) {
listener.progress("constantpool", ip + 1, code.size());
}
lastIp = ip;
GraphSourceItem ins = code.get(ip);
if (ins.isIgnored()) {
@@ -538,10 +541,12 @@ public class SWFInputStream extends InputStream {
List localData2 = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
List<GraphTargetItem> output2 = new ArrayList<GraphTargetItem>();
output2s.add(output2);
getConstantPool(cpool, localData2, new Stack<GraphTargetItem>(), output2, code, code.adr2pos(endAddr), lastIp, constantPools, visited, version, code.adr2pos(endAddr + size));
getConstantPool(listeners, cpool, localData2, new Stack<GraphTargetItem>(), output2, code, code.adr2pos(endAddr), lastIp, constantPools, visited, version, code.adr2pos(endAddr + size));
endAddr += size;
}
cnt.translateContainer(output2s, stack, output, (HashMap<Integer, String>) localData.get(0), (HashMap<String, GraphTargetItem>) localData.get(1), (HashMap<String, GraphTargetItem>) localData.get(2));
if (deobfuscate) {
cnt.translateContainer(output2s, stack, output, (HashMap<Integer, String>) localData.get(0), (HashMap<String, GraphTargetItem>) localData.get(1), (HashMap<String, GraphTargetItem>) localData.get(2));
}
ip = code.adr2pos(endAddr);
continue;
}
@@ -586,13 +591,15 @@ public class SWFInputStream extends InputStream {
}
//for..in return
if (((ins instanceof ActionEquals) || (ins instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueTreeItem)) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
}
try {
ins.translate(localData, stack, output);
} catch (Exception ex) {
Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "Error during getting constantpool", ex);
if (deobfuscate) {
if (((ins instanceof ActionEquals) || (ins instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueTreeItem)) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
}
try {
ins.translate(localData, stack, output);
} catch (Exception ex) {
Logger.getLogger(SWFInputStream.class.getName()).log(Level.SEVERE, "Error during getting constantpool", ex);
}
}
if (ins.isExit()) {
break;
@@ -600,7 +607,7 @@ public class SWFInputStream extends InputStream {
if (ins.isBranch() || ins.isJump()) {
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true) && (ins instanceof ActionIf) && !stack.isEmpty() && (stack.peek().isCompileTime() && (!stack.peek().hasSideEffect()))) {
if (deobfuscate && (ins instanceof ActionIf) && !stack.isEmpty() && (stack.peek().isCompileTime() && (!stack.peek().hasSideEffect()))) {
ActionIf aif = (ActionIf) ins;
if (aif.ignoreUsed && (!aif.jumpUsed)) {
ins.setIgnored(true);
@@ -636,9 +643,9 @@ public class SWFInputStream extends InputStream {
}
}
stack.pop();
getConstantPool(cpool, localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).getJumpOffset())) : ip + 1, ip, constantPools, visited, version, endIp);
getConstantPool(listeners, cpool, localData, stack, output, code, condition ? (code.adr2pos(((ActionIf) ins).getAddress() + ((ActionIf) ins).getBytes(code.version).length + ((ActionIf) ins).getJumpOffset())) : ip + 1, ip, constantPools, visited, version, endIp);
} else {
if (ins instanceof ActionIf) {
if (deobfuscate && ins instanceof ActionIf) {
stack.pop();
}
visited.add(ip);
@@ -646,7 +653,7 @@ public class SWFInputStream extends InputStream {
for (int b : branches) {
Stack<GraphTargetItem> brStack = (Stack<GraphTargetItem>) stack.clone();
if (b >= 0) {
getConstantPool(cpool, localData, brStack, output, code, b, ip, constantPools, visited, version, endIp);
getConstantPool(listeners, cpool, localData, brStack, output, code, b, ip, constantPools, visited, version, endIp);
} else {
if (debugMode) {
System.out.println("Negative branch:" + b);
@@ -661,13 +668,16 @@ public class SWFInputStream extends InputStream {
if (ip < 0) {
System.out.println("Visited Negative: " + ip);
}
for (DisassemblyListener listener : listeners) {
listener.progress("constantpool", ip + 1, code.size());
}
}
public static List<ConstantPool> getConstantPool(ActionGraphSource code, int addr, int version) {
public static List<ConstantPool> getConstantPool(List<DisassemblyListener> listeners, ActionGraphSource code, int addr, int version) {
List<ConstantPool> ret = new ArrayList<ConstantPool>();
List localData = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
try {
getConstantPool(null, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), 0, ret, new ArrayList<Integer>(), version, -1);
getConstantPool(listeners, null, localData, new Stack<GraphTargetItem>(), new ArrayList<GraphTargetItem>(), code, code.adr2pos(addr), 0, ret, new ArrayList<Integer>(), version, -1);
} catch (Exception ex) {
log.log(Level.SEVERE, "Error during getting constantpool", ex);
}
@@ -681,7 +691,7 @@ public class SWFInputStream extends InputStream {
* @return List of actions
* @throws IOException
*/
public static List<Action> readActionList(long address, long containerSWFOffset, ReReadableInputStream rri, int version, int ip, int endip) throws IOException {
public static List<Action> readActionList(List<DisassemblyListener> listeners, long address, long containerSWFOffset, ReReadableInputStream rri, int version, int ip, int endip) throws IOException {
List<Action> retdups = new ArrayList<Action>();
ConstantPool cpool = new ConstantPool();
@@ -699,7 +709,7 @@ public class SWFInputStream extends InputStream {
method = 2;
goesPrev = readActionListAtPos(true, localData, stack, cpool, sis, rri, ip, retdups, ip);
}*/
goesPrev = readActionListAtPos(new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, false, true, localData, stack, cpool, sis, rri, ip, retdups, ip, endip);
goesPrev = readActionListAtPos(listeners, new ArrayList<GraphTargetItem>(), new HashMap<Long, List<GraphSourceItemContainer>>(), address, containerSWFOffset, false, true, localData, stack, cpool, sis, rri, ip, retdups, ip, endip);
if (goesPrev) {
} else {
@@ -739,7 +749,7 @@ public class SWFInputStream extends InputStream {
br.append(((Action) ret.get(i)).getASMSource(new ArrayList<GraphSourceItem>(), new ArrayList<Long>(), cpool.constants, version, false));
br.append("\r\n");
}
pools = getConstantPool(new ActionGraphSource(ret, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), ip, version);
pools = getConstantPool(listeners, new ActionGraphSource(ret, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), ip, version);
if (pools.size() == 1) {
Action.setConstantPool(ret, pools.get(0));
@@ -766,9 +776,11 @@ public class SWFInputStream extends InputStream {
return reta;
}
private static boolean readActionListAtPos(List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, boolean notCompileTime, boolean enableVariables, List localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip) throws IOException {
private static boolean readActionListAtPos(List<DisassemblyListener> listeners, List<GraphTargetItem> output, HashMap<Long, List<GraphSourceItemContainer>> containers, long address, long containerSWFOffset, boolean notCompileTime, boolean enableVariables, List localData, Stack<GraphTargetItem> stack, ConstantPool cpool, SWFInputStream sis, ReReadableInputStream rri, int ip, List<Action> ret, int startIp, int endip) throws IOException {
boolean debugMode = false;
boolean decideBranch = false;
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
boolean retv = false;
rri.setPos(ip);
Action a;
@@ -776,6 +788,9 @@ public class SWFInputStream extends InputStream {
Scanner sc = new Scanner(System.in);
int prevIp = ip;
while (((endip == -1) || (endip > ip)) && (a = sis.readAction(rri)) != null) {
for (DisassemblyListener listener : listeners) {
listener.progress("Reading", rri.getCount(), rri.length());
}
if ((ip < ret.size()) && (!(ret.get(ip) instanceof ActionNop))) {
a = ret.get(ip);
if (a.getAddress() != ip) {
@@ -870,9 +885,11 @@ public class SWFInputStream extends InputStream {
try {
if (a instanceof ActionIf) {
aif = (ActionIf) a;
GraphTargetItem top = null;
top = stack.pop();
GraphTargetItem top = null;
if (deobfuscate) {
top = stack.pop();
}
int nip = rri.getPos() + aif.getJumpOffset();
if (decideBranch) {
@@ -887,7 +904,7 @@ public class SWFInputStream extends InputStream {
} else if (next.equals("c")) {
goaif = true;
}
} else if ((Boolean) Configuration.getConfig("autoDeobfuscate", true) && top.isCompileTime() && (!top.hasSideEffect()) && ((!top.isVariableComputed()) || (top.isVariableComputed() && enableVariables && (!notCompileTime)))) {
} else if (deobfuscate && top.isCompileTime() && (!top.hasSideEffect()) && ((!top.isVariableComputed()) || (top.isVariableComputed() && enableVariables && (!notCompileTime)))) {
//if(top.isCompileTime()) {
//if(false){
if (enableVariables) {
@@ -957,14 +974,16 @@ public class SWFInputStream extends InputStream {
//rri.setPos(newip);
//}
} 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 DirectValueTreeItem)) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
if (deobfuscate) {
//return in for..in, TODO:Handle this better way
if (((a instanceof ActionEquals) || (a instanceof ActionEquals2)) && (stack.size() == 1) && (stack.peek() instanceof DirectValueTreeItem)) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
}
if ((a instanceof ActionStoreRegister) && stack.isEmpty()) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
}
a.translate(localData, stack, output);
}
if ((a instanceof ActionStoreRegister) && stack.isEmpty()) {
stack.push(new DirectValueTreeItem(null, 0, new Null(), new ArrayList<String>()));
}
a.translate(localData, stack, output);
}
} catch (RuntimeException ex) {
if (!enableVariables) {
@@ -1012,11 +1031,13 @@ public class SWFInputStream extends InputStream {
}
List localData2 = Helper.toList(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>());
List<GraphTargetItem> output2 = new ArrayList<GraphTargetItem>();
readActionListAtPos(output2, containers, address, containerSWFOffset, notCompileTime, enableVariables, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size));
readActionListAtPos(listeners, output2, containers, address, containerSWFOffset, notCompileTime, enableVariables, localData2, new Stack<GraphTargetItem>(), cpool, sis, rri, (int) endAddr, ret, startIp, (int) (endAddr + size));
output2s.add(output2);
endAddr += size;
}
cnt.translateContainer(output2s, stack, output, (HashMap<Integer, String>) localData.get(0), (HashMap<String, GraphTargetItem>) localData.get(1), (HashMap<String, GraphTargetItem>) localData.get(2));
if (deobfuscate) {
cnt.translateContainer(output2s, stack, output, (HashMap<Integer, String>) localData.get(0), (HashMap<String, GraphTargetItem>) localData.get(1), (HashMap<String, GraphTargetItem>) localData.get(2));
}
ip = (int) endAddr;
prevIp = ip;
rri.setPos(ip);
@@ -1044,7 +1065,7 @@ public class SWFInputStream extends InputStream {
aif.jumpUsed = true;
int oldPos = rri.getPos();
Stack<GraphTargetItem> substack = (Stack<GraphTargetItem>) stack.clone();
if (readActionListAtPos(output, containers, address, containerSWFOffset, true, enableVariables, localData, substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip)) {
if (readActionListAtPos(listeners, output, containers, address, containerSWFOffset, true, enableVariables, localData, substack, cpool, sis, rri, rri.getPos() + aif.getJumpOffset(), ret, startIp, endip)) {
retv = true;
}
rri.setPos(oldPos);
@@ -1052,6 +1073,9 @@ public class SWFInputStream extends InputStream {
}
prevIp = ip;
}
for (DisassemblyListener listener : listeners) {
listener.progress("Reading", rri.getCount(), rri.length());
}
return retv;
}

View File

@@ -28,6 +28,9 @@ public class DivideTreeItem extends BinaryOpItem {
@Override
public double toNumber() {
if (Double.compare(rightSide.toNumber(), 0) == 0) {
return Double.NaN;
}
return leftSide.toNumber() / rightSide.toNumber();
}
}

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -364,8 +365,8 @@ public class Action implements GraphSourceItem {
* @param hex Add hexadecimal?
* @return ASM source as String
*/
public static String actionsToString(long address, List<Action> list, List<Long> importantOffsets, int version, boolean hex, long swfPos) {
return actionsToString(address, list, importantOffsets, new ArrayList<String>(), version, hex, swfPos);
public static String actionsToString(List<DisassemblyListener> listeners, long address, List<Action> list, List<Long> importantOffsets, int version, boolean hex, long swfPos) {
return actionsToString(listeners, address, list, importantOffsets, new ArrayList<String>(), version, hex, swfPos);
}
/**
@@ -378,8 +379,7 @@ public class Action implements GraphSourceItem {
* @param hex Add hexadecimal?
* @return ASM source as String
*/
public static String actionsToString(long address, List list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos) {
String ret = "";
public static String actionsToString(List<DisassemblyListener> listeners, long address, List list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos) {
long offset;
if (importantOffsets == null) {
//setActionsAddresses(list, 0, version);
@@ -391,7 +391,7 @@ public class Action implements GraphSourceItem {
srcList.add((Action) o);
}
}
List<ConstantPool> cps = SWFInputStream.getConstantPool(new ActionGraphSource(srcList, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0, version);
List<ConstantPool> cps = SWFInputStream.getConstantPool(new ArrayList<DisassemblyListener>(), new ActionGraphSource(srcList, version, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>()), 0, version);
if (!cps.isEmpty()) {
setConstantPool(list, cps.get(cps.size() - 1));
}
@@ -400,14 +400,20 @@ public class Action implements GraphSourceItem {
offset = address;
int pos = -1;
boolean lastPush = false;
StringBuilder ret = new StringBuilder();
for (GraphSourceItem s : srcList) {
for (DisassemblyListener l : listeners) {
l.progress("toString", pos + 2, srcList.size());
}
Action a = null;
if (s instanceof Action) {
a = (Action) s;
}
pos++;
if (hex) {
ret += "<ffdec:hex>" +/*"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/ Helper.bytesToHexString(a.getBytes(version)) + "</ffdec:hex>\r\n";
ret.append("<ffdec:hex>");/* +"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/;
ret.append(Helper.bytesToHexString(a.getBytes(version)));
ret.append("</ffdec:hex>\r\n");
}
offset = a.getAddress();
@@ -430,10 +436,10 @@ public class Action implements GraphSourceItem {
if (containers.containsKey(offset)) {
for (int i = 0; i < containers.get(offset).size(); i++) {
ret += "}\r\n";
ret.append("}\r\n");
GraphSourceItemContainer cnt = containers.get(offset).get(i);
int cntPos = containersPos.get(cnt);
ret += cnt.getASMSourceBetween(cntPos);
ret.append(cnt.getASMSourceBetween(cntPos));
cntPos++;
containersPos.put(cnt, cntPos);
}
@@ -441,23 +447,27 @@ public class Action implements GraphSourceItem {
if (importantOffsets.contains(offset)) {
if (lastPush) {
ret += "\r\n";
ret.append("\r\n");
lastPush = false;
}
ret += "loc" + Helper.formatAddress(offset) + ":";
ret.append("loc");
ret.append(Helper.formatAddress(offset));
ret.append(":");
}
if (a.replaceWith != null) {
if (lastPush) {
ret += "\r\n";
ret.append("\r\n");
lastPush = false;
}
ret += Highlighting.hilighOffset("", offset) + a.replaceWith.getASMSource(list, importantOffsets, constantPool, version, hex) + "\r\n";
ret.append(Highlighting.hilighOffset("", offset));
ret.append(a.replaceWith.getASMSource(list, importantOffsets, constantPool, version, hex));
ret.append("\r\n");
} else if (a.ignored) {
if (lastPush) {
ret += "\r\n";
ret.append("\r\n");
lastPush = false;
}
int len = 0;
@@ -467,11 +477,12 @@ public class Action implements GraphSourceItem {
len = a.getBytes(version).length;
}
for (int i = 0; i < len; i++) {
ret += "Nop\r\n";
ret.append("Nop\r\n");
}
} else {
if (a.beforeInsert != null) {
ret += a.beforeInsert.getASMSource(list, importantOffsets, constantPool, version, hex) + "\r\n";
ret.append(a.beforeInsert.getASMSource(list, importantOffsets, constantPool, version, hex));
ret.append("\r\n");
}
//if (!(a instanceof ActionNop)) {
String add = "";
@@ -484,12 +495,17 @@ public class Action implements GraphSourceItem {
add = "; ofs" + Helper.formatAddress(offset) + add;
add = "";
if ((a instanceof ActionPush) && lastPush) {
ret += " " + ((ActionPush) a).paramsToStringReplaced(list, importantOffsets, constantPool, version, hex);
ret.append(" ");
ret.append(((ActionPush) a).paramsToStringReplaced(list, importantOffsets, constantPool, version, hex));
} else {
if (lastPush) {
ret += "\r\n";
ret.append("\r\n");
}
ret += Highlighting.hilighOffset("", offset) + a.getASMSourceReplaced(list, importantOffsets, constantPool, version, hex) + (a.ignored ? "; ignored" : "") + add + ((a instanceof ActionPush) ? "" : "\r\n");
ret.append(Highlighting.hilighOffset("", offset));
ret.append(a.getASMSourceReplaced(list, importantOffsets, constantPool, version, hex));
ret.append(a.ignored ? "; ignored" : "");
ret.append(add);
ret.append((a instanceof ActionPush) ? "" : "\r\n");
}
if (a instanceof ActionPush) {
lastPush = true;
@@ -498,28 +514,31 @@ public class Action implements GraphSourceItem {
}
//}
if (a.afterInsert != null) {
ret += a.afterInsert.getASMSource(list, importantOffsets, constantPool, version, hex) + "\r\n";
ret.append(a.afterInsert.getASMSource(list, importantOffsets, constantPool, version, hex));
ret.append("\r\n");
}
}
offset += a.getBytes(version).length;
}
if (lastPush) {
ret += "\r\n";
ret.append("\r\n");
}
if (containers.containsKey(offset)) {
for (int i = 0; i < containers.get(offset).size(); i++) {
ret += "}\r\n";
ret.append("}\r\n");
GraphSourceItemContainer cnt = containers.get(offset).get(i);
int cntPos = containersPos.get(cnt);
ret += cnt.getASMSourceBetween(cntPos);
ret.append(cnt.getASMSourceBetween(cntPos));
cntPos++;
containersPos.put(cnt, cntPos);
}
}
if (importantOffsets.contains(offset)) {
ret += "loc" + Helper.formatAddress(offset) + ":\r\n";
ret.append("loc");
ret.append(Helper.formatAddress(offset));
ret.append(":\r\n");
}
return ret;
return ret.toString();
}
/**
@@ -1216,7 +1235,7 @@ public class Action implements GraphSourceItem {
}
String s = null;
try {
s = Highlighting.stripHilights(Action.actionsToString(address, ret, null, version, false, swfPos));
s = Highlighting.stripHilights(Action.actionsToString(new ArrayList<DisassemblyListener>(), address, ret, null, version, false, swfPos));
ret = ASMParser.parse(address, swfPos, true, new ByteArrayInputStream(s.getBytes()), SWF.DEFAULT_VERSION);
} catch (Exception ex) {

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.action.gui;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.Main;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.gui.LineMarkedEditorPane;
@@ -93,8 +94,15 @@ public class ActionPanel extends JPanel implements ActionListener {
lastH = h;
}
long offset = lastH.offset;
editor.setText("; Getting hilights...");
disassembledHilights = Highlighting.getInstrHighlights(text);
editor.setText(Highlighting.stripHilights(text));
String stripped = Highlighting.stripHilights(text);
/*if(stripped.length()>30000){
editor.setContentType("text/plain");
}else{
editor.setContentType("text/flasm");
}*/
editor.setText(stripped);
for (Highlighting h : disassembledHilights) {
if (h.offset == offset) {
editor.setCaretPosition(h.startPos);
@@ -117,13 +125,35 @@ public class ActionPanel extends JPanel implements ActionListener {
public void run() {
editor.setText("; Disassembling...");
if (Main.DO_DECOMPILE) {
decompiledEditor.setText("//Decompiling...");
decompiledEditor.setText("//Waiting for dissasembly...");
}
DisassemblyListener listener = new DisassemblyListener() {
int percent = 0;
String phase = "";
@Override
public void progress(String phase, long pos, long total) {
if (total < 1) {
return;
}
int newpercent = (int) (pos * 100 / total);
if (((newpercent > percent) || (!this.phase.equals(phase))) && newpercent <= 100) {
percent = newpercent;
this.phase = phase;
editor.setText("; Disassembling - " + phase + " " + percent + "%...");
}
}
};
asm.addDisassemblyListener(listener);
lastDisasm = asm.getASMSource(SWF.DEFAULT_VERSION, true);
asm.removeDisassemblyListener(listener);
editor.setText("; Disassembled");
srcWithHex = Helper.hexToComments(lastDisasm);
srcNoHex = Helper.stripComments(lastDisasm);
editor.setText("; Disassembling - setting");
setHex(hexButton.isSelected());
if (Main.DO_DECOMPILE) {
decompiledEditor.setText("//Decompiling...");
List<com.jpexs.decompiler.flash.action.Action> as = asm.getActions(SWF.DEFAULT_VERSION);
lastCode = as;
//com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION);
@@ -138,13 +168,19 @@ public class ActionPanel extends JPanel implements ActionListener {
} catch (IOException ex) {
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
}*/
decompiledEditor.setText(lastDecompiled = stripped);
lastDecompiled = stripped;
/*if(lastDecompiled.length()>30000){
decompiledEditor.setContentType("text/plain");
}else{
decompiledEditor.setContentType("text/actionscript");
}*/
decompiledEditor.setText(lastDecompiled);
if (debugRecompile) {
try {
ActionScriptParser ps = new ActionScriptParser();
recompiledEditor.setText(Highlighting.stripHilights(com.jpexs.decompiler.flash.action.Action.actionsToString(0, ps.parse(stripped), null, SWF.DEFAULT_VERSION, false, 0)));
recompiledEditor.setText(Highlighting.stripHilights(com.jpexs.decompiler.flash.action.Action.actionsToString(new ArrayList<DisassemblyListener>(), 0, ps.parse(stripped), null, SWF.DEFAULT_VERSION, false, 0)));
} catch (ParseException ex) {
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {

View File

@@ -28,6 +28,9 @@ public class ModuloTreeItem extends BinaryOpItem {
@Override
public double toNumber() {
if (Double.compare(rightSide.toNumber(), 0) == 0) {
return Double.NaN;
}
return ((int) leftSide.toNumber()) % ((int) rightSide.toNumber());
}
}

View File

@@ -489,10 +489,24 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
List<Object> list2 = new ArrayList<Object>();
list2.addAll(swf.tags);
parseCharacters(list2);
JPanel textPanel = new JPanel(new BorderLayout());
textPanel.add(textValue, BorderLayout.CENTER);
JPanel textTopPanel = new JPanel(new BorderLayout());
textTopPanel.add(textValue, BorderLayout.CENTER);
textValue.setEditable(false);
/*JPanel textBottomPanel = new JPanel();
textBottomPanel.setLayout(new BoxLayout(textBottomPanel, BoxLayout.X_AXIS));
textBottomPanel.add(new JLabel("Xmin:"));
textBottomPanel.add(textRectXmin);
textBottomPanel.add(new JLabel("Ymin:"));
textBottomPanel.add(textRectYmin);
textBottomPanel.add(new JLabel("Xmax:"));
textBottomPanel.add(textRectXmax);
textBottomPanel.add(new JLabel("Ymax:"));
textBottomPanel.add(textRectYmax);*/
JPanel buttonsPanel = new JPanel();
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
@@ -519,9 +533,16 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
textSaveButton.setVisible(false);
textCancelButton.setVisible(false);
textPanel.add(buttonsPanel, BorderLayout.EAST);
textTopPanel.add(buttonsPanel, BorderLayout.EAST);
displayWithPreview = new JPanel(new CardLayout());
JPanel textPanel = new JPanel();
textPanel.setLayout(new BoxLayout(textPanel, BoxLayout.Y_AXIS));
textPanel.add(textTopPanel);
//textPanel.add(textBottomPanel);
displayWithPreview.add(textPanel, CARDTEXTPANEL);
displayWithPreview.setVisible(false);

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.Main;
import com.jpexs.decompiler.flash.ReReadableInputStream;
import com.jpexs.decompiler.flash.SWFInputStream;
@@ -119,7 +121,7 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT
*/
@Override
public String getASMSource(int version, boolean hex) {
return Action.actionsToString(0, getActions(version), null, version, hex, getPos() + hdrSize);
return Action.actionsToString(listeners, 0, getActions(version), null, version, hex, getPos() + hdrSize);
}
/**
@@ -151,7 +153,13 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT
baos.write(actionBytes);
ReReadableInputStream rri = new ReReadableInputStream(new ByteArrayInputStream(baos.toByteArray()));
rri.setPos(prevLength);
return Action.removeNops(0, SWFInputStream.readActionList(0, getPos() + hdrSize - prevLength, rri, version, prevLength, -1), version, getPos() + hdrSize);
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
List<Action> list = SWFInputStream.readActionList(listeners, 0, getPos() + hdrSize - prevLength, rri, version, prevLength, -1);
if (deobfuscate) {
list = Action.removeNops(0, list, version, getPos() + hdrSize);
}
return list;
} catch (Exception ex) {
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ArrayList<Action>();
@@ -197,4 +205,15 @@ public class DefineButtonTag extends CharacterTag implements ASMSource, BoundedT
}
return rect;
}
List<DisassemblyListener> listeners = new ArrayList<DisassemblyListener>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
}

View File

@@ -22,16 +22,23 @@ import com.jpexs.decompiler.flash.tags.base.BoundedTag;
import com.jpexs.decompiler.flash.tags.base.CharacterTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.tags.text.ParsedSymbol;
import com.jpexs.decompiler.flash.tags.text.TextLexer;
import com.jpexs.decompiler.flash.types.RECT;
import com.jpexs.decompiler.flash.types.RGBA;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
@@ -71,6 +78,16 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
public String variableName;
public String initialText;
@Override
public RECT getBounds() {
return bounds;
}
@Override
public void setBounds(RECT r) {
bounds = r;
}
private String stripTags(String inp) {
boolean intag = false;
String outp = "";
@@ -110,16 +127,247 @@ public class DefineEditTextTag extends CharacterTag implements BoundedTag, TextT
@Override
public String getFormattedText(List<Tag> tags) {
String ret = "";
ret += "[";
String[] alignValues = {"left", "right", "center", "justify"};
ret += "xmin " + bounds.Xmin + " ymin " + bounds.Ymin + " xmax " + bounds.Xmax + " ymax " + bounds.Ymax + " ";
ret += (wordWrap ? "wordwrap 1 " : "") + (multiline ? "multiline 1 " : "")
+ (password ? "password 1 " : "") + (readOnly ? "readonly 1 " : "")
+ (autoSize ? "autosize 1 " : "") + (noSelect ? "noselect 1 " : "")
+ (border ? "border 1 " : "") + (wasStatic ? "wasstatic 1 " : "")
+ (html ? "html 1 " : "") + (useOutlines ? "useoutlines 1 " : "")
+ (hasFont ? "font " + fontId + " " : "") + (hasTextColor ? "color " + textColor.toHexARGB() + " " : "")
+ (hasFontClass ? "fontclass " + fontClass + " " : "") + (hasMaxLength ? "maxlength " + maxLength + " " : "")
+ "align " + alignValues[align] + " "
+ (hasLayout ? "leftmargin " + leftMargin + " rightmargin " + rightMargin + " indent " + indent + " leading " + leading + " " : "")
+ (!variableName.equals("") ? "variablename " + variableName + " " : "");
ret = ret.trim() + "]";
if (hasText) {
return initialText;
ret += initialText.replace("\\", "\\\\").replace("[", "\\[").replace("]", "\\]");
}
return "";
return ret;
}
@Override
public void setFormattedText(List<Tag> tags, String text) throws ParseException {
initialText = text;
hasText = true;
try {
TextLexer lexer = new TextLexer(new InputStreamReader(new ByteArrayInputStream(text.getBytes("UTF-8")), "UTF-8"));
ParsedSymbol s = null;
text = "";
RECT bounds = new RECT(this.bounds);
boolean wordWrap = false;
boolean multiline = false;
boolean password = false;
boolean readOnly = false;
boolean autoSize = false;
boolean noSelect = false;
boolean border = false;
boolean wasStatic = false;
boolean html = false;
boolean useOutlines = false;
int fontId = -1;
int fontHeight = -1;
String fontClass = null;
RGBA textColor = null;
int maxLength = -1;
int align = -1;
int leftMargin = -1;
int rightMargin = -1;
int indent = -1;
int leading = -1;
String variableName = null;
while ((s = lexer.yylex()) != null) {
switch (s.type) {
case PARAMETER:
String paramName = (String) s.values[0];
String paramValue = (String) s.values[1];
if (paramName.equals("xmin")) {
try {
bounds.Xmin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmin value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("ymin")) {
try {
bounds.Ymin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymin value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("xmax")) {
try {
bounds.Xmax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmax value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("ymax")) {
try {
bounds.Ymax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymax value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("wordwrap")) {
if (paramValue.equals("1")) {
wordWrap = true;
}
} else if (paramName.equals("multiline")) {
if (paramValue.equals("1")) {
multiline = true;
}
} else if (paramName.equals("password")) {
if (paramValue.equals("1")) {
password = true;
}
} else if (paramName.equals("readonly")) {
if (paramValue.equals("1")) {
readOnly = true;
}
} else if (paramName.equals("autosize")) {
if (paramValue.equals("1")) {
autoSize = true;
}
} else if (paramName.equals("noselect")) {
if (paramValue.equals("1")) {
noSelect = true;
}
} else if (paramName.equals("border")) {
if (paramValue.equals("1")) {
border = true;
}
} else if (paramName.equals("wasstatic")) {
if (paramValue.equals("1")) {
wasStatic = true;
}
} else if (paramName.equals("html")) {
if (paramValue.equals("1")) {
html = true;
}
} else if (paramName.equals("useoutlines")) {
if (paramValue.equals("1")) {
useOutlines = true;
}
} else if (paramName.equals("font")) {
try {
fontId = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid font value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("fontclass")) {
fontClass = paramValue;
} else if (paramName.equals("height")) {
try {
fontHeight = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid height value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("color")) {
Matcher m = Pattern.compile("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])").matcher(paramValue);
if (m.matches()) {
textColor = new RGBA(Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16), Integer.parseInt(m.group(4), 16), Integer.parseInt(m.group(1), 16));
} else {
throw new ParseException("Invalid color. Valid format is #aarrggbb.", lexer.yyline());
}
} else if (paramName.equals("maxlength")) {
try {
maxLength = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid maxLength value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("align")) {
if (paramValue.equals("left")) {
align = 0;
} else if (paramValue.equals("right")) {
align = 1;
} else if (paramValue.equals("center")) {
align = 2;
} else if (paramValue.equals("justify")) {
align = 3;
} else {
throw new ParseException("Invalid align value. Expected one of: left,right,center or justify.", lexer.yyline());
}
} else if (paramName.equals("leftmargin")) {
try {
leftMargin = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid leftmargin value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("rightmargin")) {
try {
rightMargin = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid rightmargin value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("indent")) {
try {
indent = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid indent value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("leading")) {
try {
leading = Integer.parseInt(paramValue);
} catch (NumberFormatException ne) {
throw new ParseException("Invalid leading value. Number expected.", lexer.yyline());
}
} else if (paramName.equals("variablename")) {
variableName = paramValue;
} else {
throw new ParseException("Unrecognized parameter name", lexer.yyline());
}
break;
case TEXT:
text += (String) s.values[0];
break;
}
}
if (text.length() > 0) {
initialText = text;
this.hasText = true;
} else {
this.hasText = false;
}
this.wordWrap = wordWrap;
this.multiline = multiline;
this.password = password;
this.readOnly = readOnly;
if (textColor != null) {
hasTextColor = true;
this.textColor = textColor;
}
if (maxLength > -1) {
this.maxLength = maxLength;
hasMaxLength = true;
}
if (fontId > -1) {
this.fontId = fontId;
}
if (fontClass != null) {
this.fontClass = fontClass;
hasFontClass = true;
}
this.autoSize = autoSize;
if ((leftMargin > -1)
|| (rightMargin > -1)
|| (indent > -1)
|| (leading > -1)) {
this.leftMargin = leftMargin;
this.rightMargin = rightMargin;
this.indent = indent;
this.leading = leading;
hasLayout = true;
}
if (variableName == null) {
variableName = "";
}
this.variableName = variableName;
} catch (IOException ex) {
Logger.getLogger(DefineEditTextTag.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override

View File

@@ -69,7 +69,7 @@ public class DefineFont2Tag extends CharacterTag implements FontTag {
if (fontFlagsHasLayout) {
return fontAdvanceTable[glyphIndex];
} else {
return glyphShapeTable[glyphIndex].getBounds().getWidth();
return getGlyphWidth(glyphIndex) + 20;
}
}

View File

@@ -67,7 +67,7 @@ public class DefineFont3Tag extends CharacterTag implements FontTag {
if (fontFlagsHasLayout) {
return fontAdvanceTable[glyphIndex] / 20;
} else {
return glyphShapeTable[glyphIndex].getBounds().getWidth();
return getGlyphWidth(glyphIndex) + 20;
}
}

View File

@@ -26,11 +26,6 @@ import com.jpexs.decompiler.flash.tags.base.FontTag;
import com.jpexs.decompiler.flash.tags.base.TextTag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.tags.text.ParsedSymbol;
import static com.jpexs.decompiler.flash.tags.text.SymbolType.COLOR;
import static com.jpexs.decompiler.flash.tags.text.SymbolType.FONT;
import static com.jpexs.decompiler.flash.tags.text.SymbolType.TEXT;
import static com.jpexs.decompiler.flash.tags.text.SymbolType.X;
import static com.jpexs.decompiler.flash.tags.text.SymbolType.Y;
import com.jpexs.decompiler.flash.tags.text.TextLexer;
import com.jpexs.decompiler.flash.types.GLYPHENTRY;
import com.jpexs.decompiler.flash.types.MATRIX;
@@ -67,6 +62,16 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
public int advanceBits;
public List<TEXTRECORD> textRecords;
@Override
public RECT getBounds() {
return textBounds;
}
@Override
public void setBounds(RECT r) {
textBounds = r;
}
@Override
public String getText(List<Tag> tags) {
FontTag fnt = null;
@@ -91,7 +96,24 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
public String getFormattedText(List<Tag> tags) {
FontTag fnt = null;
String ret = "";
ret += "[xmin " + textBounds.Xmin + " ymin " + textBounds.Ymin + " xmax " + textBounds.Xmax + " ymax " + textBounds.Ymax;
if (textMatrix.translateX != 0) {
ret += " translatex " + textMatrix.translateX;
}
if (textMatrix.translateY != 0) {
ret += " translatey " + textMatrix.translateY;
}
if (textMatrix.hasScale) {
ret += " scalex " + textMatrix.scaleX;
ret += " scaley " + textMatrix.scaleY;
}
if (textMatrix.hasRotate) {
ret += " rotateskew0 " + textMatrix.rotateSkew0;
ret += " rotateskew1 " + textMatrix.rotateSkew1;
}
ret += "]";
for (TEXTRECORD rec : textRecords) {
String params = "";
if (rec.styleFlagsHasFont) {
for (Tag t : tags) {
if (t instanceof FontTag) {
@@ -101,16 +123,19 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
}
}
}
ret += "[font " + rec.fontId + " height " + rec.textHeight + "]";
params += " font " + rec.fontId + " height " + rec.textHeight;
}
if (rec.styleFlagsHasColor) {
ret += "[color " + rec.textColorA.toHexARGB() + "]";
params += " color " + rec.textColorA.toHexARGB();
}
if (rec.styleFlagsHasXOffset) {
ret += "[x " + rec.xOffset + "]";
params += " x " + rec.xOffset;
}
if (rec.styleFlagsHasYOffset) {
ret += "[y " + rec.yOffset + "]";
params += " y " + rec.yOffset;
}
if (params.length() > 0) {
ret += "[" + params.trim() + "]";
}
ret += Helper.escapeString(rec.getText(tags, fnt)).replace("[", "\\[").replace("]", "\\]");
}
@@ -135,39 +160,128 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
int advanceBits = 0;
int maxX = Integer.MIN_VALUE;
int minX = Integer.MAX_VALUE;
MATRIX textMatrix = new MATRIX();
textMatrix.hasRotate = false;
textMatrix.hasScale = false;
RECT textBounds = new RECT();
while ((s = lexer.yylex()) != null) {
switch (s.type) {
case COLOR:
Matcher m = Pattern.compile("([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])").matcher(s.values[0].toString());
if (m.matches()) {
colorA = new RGBA(Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16), Integer.parseInt(m.group(4), 16), Integer.parseInt(m.group(1), 16));
}
break;
case FONT:
fontId = (Integer) s.values[0];
textHeight = (Integer) s.values[1];
for (Tag t : tags) {
if (t instanceof FontTag) {
if (((FontTag) t).getFontId() == fontId) {
font = (FontTag) t;
break;
}
case PARAMETER:
String paramName = (String) s.values[0];
String paramValue = (String) s.values[1];
if (paramName.equals("color")) {
Matcher m = Pattern.compile("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])").matcher(s.values[0].toString());
if (m.matches()) {
colorA = new RGBA(Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16), Integer.parseInt(m.group(4), 16), Integer.parseInt(m.group(1), 16));
} else {
throw new ParseException("Invalid color. Valid format is #aarrggbb.", lexer.yyline());
}
}
break;
case X:
x = (Integer) s.values[0];
currentX = x;
if (currentX < minX) {
minX = currentX;
if (paramName.equals("font")) {
try {
fontId = Integer.parseInt(paramValue);
for (Tag t : tags) {
if (t instanceof FontTag) {
if (((FontTag) t).getFontId() == fontId) {
font = (FontTag) t;
break;
}
}
}
if (font == null) {
throw new ParseException("Font not found", lexer.yyline());
}
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid font id - number expected.", lexer.yyline());
}
} else if (paramName.equals("height")) {
try {
textHeight = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid font height - number expected.", lexer.yyline());
}
} else if (paramName.equals("x")) {
try {
x = Integer.parseInt(paramValue);
currentX = x;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid x position - number expected.", lexer.yyline());
}
} else if (paramName.equals("y")) {
try {
y = Integer.parseInt(paramValue);
currentY = y;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid y position - number expected.", lexer.yyline());
}
} else if (paramName.equals("xmin")) {
try {
textBounds.Xmin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmin position - number expected.", lexer.yyline());
}
} else if (paramName.equals("xmax")) {
try {
textBounds.Xmax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmax position - number expected.", lexer.yyline());
}
} else if (paramName.equals("ymin")) {
try {
textBounds.Ymin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymin position - number expected.", lexer.yyline());
}
} else if (paramName.equals("ymax")) {
try {
textBounds.Ymax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymax position - number expected.", lexer.yyline());
}
} else if (paramName.equals("scalex")) {
try {
textMatrix.scaleX = Integer.parseInt(paramValue);
textMatrix.hasScale = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid scalex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("scaley")) {
try {
textMatrix.scaleY = Integer.parseInt(paramValue);
textMatrix.hasScale = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid scalex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("rotateskew0")) {
try {
textMatrix.rotateSkew0 = Integer.parseInt(paramValue);
textMatrix.hasRotate = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid rotateskew0 value - number expected.", lexer.yyline());
}
} else if (paramName.equals("rotateskew1")) {
try {
textMatrix.rotateSkew1 = Integer.parseInt(paramValue);
textMatrix.hasRotate = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid rotateskew1 value - number expected.", lexer.yyline());
}
} else if (paramName.equals("translatex")) {
try {
textMatrix.translateX = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid translatex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("translatey")) {
try {
textMatrix.translateY = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid translatey value - number expected.", lexer.yyline());
}
}
if (currentX > maxX) {
maxX = currentX;
}
break;
case Y:
y = (Integer) s.values[0];
currentY = y;
break;
case TEXT:
if (font == null) {
@@ -215,8 +329,8 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
} else {
currentX += tr.glyphEntries[i].glyphAdvance;
}
if (SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphIndex) > glyphBits) {
glyphBits = SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphIndex);
if (SWFOutputStream.getNeededBitsU(tr.glyphEntries[i].glyphIndex) > glyphBits) {
glyphBits = SWFOutputStream.getNeededBitsU(tr.glyphEntries[i].glyphIndex);
}
if (SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphAdvance) > advanceBits) {
advanceBits = SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphAdvance);
@@ -237,8 +351,9 @@ public class DefineText2Tag extends CharacterTag implements BoundedTag, TextTag
this.advanceBits = advanceBits;
this.glyphBits = glyphBits;
this.textRecords = textRecords;
this.textBounds.Xmin = minX;
this.textBounds.Xmax = maxX;
this.textBounds = textBounds;
//this.textBounds.Xmin = minX;
//this.textBounds.Xmax = maxX;
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {

View File

@@ -62,6 +62,16 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
public int advanceBits;
public List<TEXTRECORD> textRecords;
@Override
public RECT getBounds() {
return textBounds;
}
@Override
public void setBounds(RECT r) {
textBounds = r;
}
@Override
public String getText(List<Tag> tags) {
FontTag fnt = null;
@@ -86,7 +96,24 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
public String getFormattedText(List<Tag> tags) {
FontTag fnt = null;
String ret = "";
ret += "[xmin " + textBounds.Xmin + " ymin " + textBounds.Ymin + " xmax " + textBounds.Xmax + " ymax " + textBounds.Ymax;
if (textMatrix.translateX != 0) {
ret += " translatex " + textMatrix.translateX;
}
if (textMatrix.translateY != 0) {
ret += " translatey " + textMatrix.translateY;
}
if (textMatrix.hasScale) {
ret += " scalex " + textMatrix.scaleX;
ret += " scaley " + textMatrix.scaleY;
}
if (textMatrix.hasRotate) {
ret += " rotateskew0 " + textMatrix.rotateSkew0;
ret += " rotateskew1 " + textMatrix.rotateSkew1;
}
ret += "]";
for (TEXTRECORD rec : textRecords) {
String params = "";
if (rec.styleFlagsHasFont) {
for (Tag t : tags) {
if (t instanceof FontTag) {
@@ -96,16 +123,19 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
}
}
}
ret += "[font " + rec.fontId + " height " + rec.textHeight + "]";
params += " font " + rec.fontId + " height " + rec.textHeight;
}
if (rec.styleFlagsHasColor) {
ret += "[color " + rec.textColor.toHexRGB() + "]";
params += " color " + rec.textColor.toHexRGB();
}
if (rec.styleFlagsHasXOffset) {
ret += "[x " + rec.xOffset + "]";
params += " x " + rec.xOffset;
}
if (rec.styleFlagsHasYOffset) {
ret += "[y " + rec.yOffset + "]";
params += " y " + rec.yOffset;
}
if (params.length() > 0) {
ret += "[" + params.trim() + "]";
}
ret += Helper.escapeString(rec.getText(tags, fnt)).replace("[", "\\[").replace("]", "\\]");
}
@@ -130,40 +160,128 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
int advanceBits = 0;
int maxX = Integer.MIN_VALUE;
int minX = Integer.MAX_VALUE;
MATRIX textMatrix = new MATRIX();
textMatrix.hasRotate = false;
textMatrix.hasScale = false;
RECT textBounds = new RECT();
while ((s = lexer.yylex()) != null) {
switch (s.type) {
case COLOR:
Matcher m = Pattern.compile("([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])").matcher(s.values[0].toString());
if (m.matches()) {
color = new RGB(Integer.parseInt(m.group(1), 16), Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16));
}
break;
case FONT:
fontId = (Integer) s.values[0];
textHeight = (Integer) s.values[1];
for (Tag t : tags) {
if (t instanceof FontTag) {
if (((FontTag) t).getFontId() == fontId) {
font = (FontTag) t;
break;
case PARAMETER:
String paramName = (String) s.values[0];
String paramValue = (String) s.values[1];
if (paramName.equals("color")) {
Matcher m = Pattern.compile("#([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])([0-9a-f][0-9a-f])").matcher(paramValue);
if (m.matches()) {
color = new RGB(Integer.parseInt(m.group(1), 16), Integer.parseInt(m.group(2), 16), Integer.parseInt(m.group(3), 16));
} else {
throw new ParseException("Invalid color. Valid format is #rrggbb.", lexer.yyline());
}
} else if (paramName.equals("font")) {
try {
fontId = Integer.parseInt(paramValue);
for (Tag t : tags) {
if (t instanceof FontTag) {
if (((FontTag) t).getFontId() == fontId) {
font = (FontTag) t;
break;
}
}
}
if (font == null) {
throw new ParseException("Font not found", lexer.yyline());
}
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid font id - number expected.", lexer.yyline());
}
} else if (paramName.equals("height")) {
try {
textHeight = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid font height - number expected.", lexer.yyline());
}
} else if (paramName.equals("x")) {
try {
x = Integer.parseInt(paramValue);
currentX = x;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid x position - number expected.", lexer.yyline());
}
} else if (paramName.equals("y")) {
try {
y = Integer.parseInt(paramValue);
currentY = y;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid y position - number expected.", lexer.yyline());
}
} else if (paramName.equals("xmin")) {
try {
textBounds.Xmin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmin position - number expected.", lexer.yyline());
}
} else if (paramName.equals("xmax")) {
try {
textBounds.Xmax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid xmax position - number expected.", lexer.yyline());
}
} else if (paramName.equals("ymin")) {
try {
textBounds.Ymin = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymin position - number expected.", lexer.yyline());
}
} else if (paramName.equals("ymax")) {
try {
textBounds.Ymax = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid ymax position - number expected.", lexer.yyline());
}
} else if (paramName.equals("scalex")) {
try {
textMatrix.scaleX = Integer.parseInt(paramValue);
textMatrix.hasScale = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid scalex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("scaley")) {
try {
textMatrix.scaleY = Integer.parseInt(paramValue);
textMatrix.hasScale = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid scalex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("rotateskew0")) {
try {
textMatrix.rotateSkew0 = Integer.parseInt(paramValue);
textMatrix.hasRotate = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid rotateskew0 value - number expected.", lexer.yyline());
}
} else if (paramName.equals("rotateskew1")) {
try {
textMatrix.rotateSkew1 = Integer.parseInt(paramValue);
textMatrix.hasRotate = true;
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid rotateskew1 value - number expected.", lexer.yyline());
}
} else if (paramName.equals("translatex")) {
try {
textMatrix.translateX = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid translatex value - number expected.", lexer.yyline());
}
} else if (paramName.equals("translatey")) {
try {
textMatrix.translateY = Integer.parseInt(paramValue);
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid translatey value - number expected.", lexer.yyline());
}
}
break;
case X:
x = (Integer) s.values[0];
currentX = x;
if (currentX < minX) {
minX = currentX;
}
if (currentX > maxX) {
maxX = currentX;
}
break;
case Y:
y = (Integer) s.values[0];
currentY = y;
break;
case TEXT:
if (font == null) {
throw new ParseException("Font not defined", lexer.yyline());
@@ -210,8 +328,8 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
} else {
currentX += tr.glyphEntries[i].glyphAdvance;
}
if (SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphIndex) > glyphBits) {
glyphBits = SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphIndex);
if (SWFOutputStream.getNeededBitsU(tr.glyphEntries[i].glyphIndex) > glyphBits) {
glyphBits = SWFOutputStream.getNeededBitsU(tr.glyphEntries[i].glyphIndex);
}
if (SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphAdvance) > advanceBits) {
advanceBits = SWFOutputStream.getNeededBitsS(tr.glyphEntries[i].glyphAdvance);
@@ -232,8 +350,10 @@ public class DefineTextTag extends CharacterTag implements BoundedTag, TextTag {
this.advanceBits = advanceBits;
this.glyphBits = glyphBits;
this.textRecords = textRecords;
this.textBounds.Xmin = minX;
this.textBounds.Xmax = maxX;
this.textMatrix = textMatrix;
this.textBounds = textBounds;
//this.textBounds.Xmin = minX;
//this.textBounds.Xmax = maxX;
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.ReReadableInputStream;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -72,7 +74,7 @@ public class DoActionTag extends Tag implements ASMSource {
*/
@Override
public String getASMSource(int version, boolean hex) {
return Action.actionsToString(0, getActions(version), null, version, hex, getPos());
return Action.actionsToString(listeners, 0, getActions(version), null, version, hex, getPos());
}
/**
@@ -111,7 +113,12 @@ public class DoActionTag extends Tag implements ASMSource {
baos.write(actionBytes);
ReReadableInputStream rri = new ReReadableInputStream(new ByteArrayInputStream(baos.toByteArray()));
rri.setPos(prevLength);
return Action.removeNops(0, SWFInputStream.readActionList(0, getPos() - prevLength, rri, version, prevLength, -1), version, getPos());
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
List<Action> list = SWFInputStream.readActionList(listeners, 0, getPos() - prevLength, rri, version, prevLength, -1);
if (deobfuscate) {
list = Action.removeNops(0, list, version, getPos());
}
return list;
} catch (Exception ex) {
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ArrayList<Action>();
@@ -132,4 +139,15 @@ public class DoActionTag extends Tag implements ASMSource {
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = actionBytes;
}
List<DisassemblyListener> listeners = new ArrayList<DisassemblyListener>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.tags;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.ReReadableInputStream;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.SWFOutputStream;
@@ -95,7 +97,7 @@ public class DoInitActionTag extends CharacterTag implements ASMSource {
*/
@Override
public String getASMSource(int version, boolean hex) {
return Action.actionsToString(0, getActions(version), null, version, hex, getPos() + 2);
return Action.actionsToString(listeners, 0, getActions(version), null, version, hex, getPos() + 2);
}
@Override
@@ -117,7 +119,12 @@ public class DoInitActionTag extends CharacterTag implements ASMSource {
baos.write(actionBytes);
ReReadableInputStream rri = new ReReadableInputStream(new ByteArrayInputStream(baos.toByteArray()));
rri.setPos(prevLength);
return Action.removeNops(0, SWFInputStream.readActionList(0, getPos() + 2 - prevLength, rri, version, prevLength, -1), version, getPos() + 2);
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
List<Action> list = SWFInputStream.readActionList(listeners, 0, getPos() + 2 - prevLength, rri, version, prevLength, -1);
if (deobfuscate) {
list = Action.removeNops(0, list, version, getPos() + 2);
}
return list;
} catch (Exception ex) {
Logger.getLogger(DoActionTag.class.getName()).log(Level.SEVERE, null, ex);
return new ArrayList<Action>();
@@ -143,4 +150,15 @@ public class DoInitActionTag extends CharacterTag implements ASMSource {
public int getCharacterID() {
return spriteId;
}
List<DisassemblyListener> listeners = new ArrayList<DisassemblyListener>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
}

View File

@@ -16,6 +16,7 @@
*/
package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.action.Action;
import java.util.List;
@@ -63,4 +64,8 @@ public interface ASMSource {
public void setActionBytes(byte actionBytes[]);
public long getPos();
public void addDisassemblyListener(DisassemblyListener listener);
public void removeDisassemblyListener(DisassemblyListener listener);
}

View File

@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.tags.base;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.text.ParseException;
import com.jpexs.decompiler.flash.types.RECT;
import java.util.List;
/**
@@ -33,4 +34,8 @@ public interface TextTag {
public void setFormattedText(List<Tag> tags, String text) throws ParseException;
public int getCharacterID();
public RECT getBounds();
public void setBounds(RECT r);
}

View File

@@ -23,8 +23,5 @@ package com.jpexs.decompiler.flash.tags.text;
public enum SymbolType {
TEXT,
FONT,
COLOR,
X,
Y
PARAMETER
}

View File

@@ -1,13 +1,26 @@
/* The following code was generated by JFlex 1.4.3 on 28.4.13 11:46 */
/* The following code was generated by JFlex 1.4.3 on 30.4.13 19:25 */
/* Flash assembler language lexer specification */
/*
* Copyright (C) 2013 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.tags.text;
import java.util.regex.*;
/**
* This class is a scanner generated by
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3 on 28.4.13 11:46 from the
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3 on 30.4.13 19:25 from the
* specification file
* <tt>D:/Dokumenty/Programovani/JavaSE/FFDec/trunk/src/com/jpexs/decompiler/flash/tags/text/text.flex</tt>
*/
@@ -25,23 +38,23 @@ public final class TextLexer {
* lexical states
*/
public static final int YYINITIAL = 0;
public static final int VALUE = 4;
public static final int PARAMETER = 2;
/**
* ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
* ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
* beginning of a line l is of the form l = 2*k, k a non negative integer
*/
private static final int ZZ_LEXSTATE[] = {
0, 0
0, 0, 1, 1, 2, 2
};
/**
* Translates characters to character classes
*/
private static final String ZZ_CMAP_PACKED =
"\12\0\1\32\25\0\1\12\1\0\1\30\1\23\3\0\1\31\5\0"
+ "\1\3\2\0\1\1\11\2\41\0\1\5\1\26\1\17\3\0\1\4"
+ "\1\27\1\20\1\4\1\14\1\6\1\16\1\13\1\15\2\0\1\21"
+ "\1\0\1\10\1\7\2\0\1\22\1\0\1\11\3\0\1\24\1\25"
+ "\uff86\0";
"\12\0\1\15\25\0\1\2\1\0\1\13\4\0\1\14\10\0\12\1"
+ "\41\0\1\3\1\4\1\5\1\0\1\1\1\0\1\1\1\6\3\1"
+ "\1\11\7\1\1\10\3\1\1\12\1\1\1\7\6\1\uff85\0";
/**
* Translates characters to character classes
*/
@@ -51,12 +64,12 @@ public final class TextLexer {
*/
private static final int[] ZZ_ACTION = zzUnpackAction();
private static final String ZZ_ACTION_PACKED_0 =
"\1\0\3\1\1\2\4\0\1\3\1\4\1\5\1\6"
+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\16\0"
+ "\1\16\1\17\25\0\1\20\3\0\1\21";
"\3\0\1\1\1\2\1\1\1\3\1\4\1\5\1\6"
+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\1\16"
+ "\1\17\1\20\1\21";
private static int[] zzUnpackAction() {
int[] result = new int[62];
int[] result = new int[21];
int offset = 0;
offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
return result;
@@ -80,17 +93,12 @@ public final class TextLexer {
*/
private static final int[] ZZ_ROWMAP = zzUnpackRowMap();
private static final String ZZ_ROWMAP_PACKED_0 =
"\0\0\0\33\0\66\0\121\0\33\0\154\0\207\0\242"
+ "\0\275\0\33\0\33\0\33\0\33\0\33\0\33\0\33"
+ "\0\33\0\33\0\33\0\33\0\330\0\363\0\u010e\0\u0129"
+ "\0\u0144\0\u015f\0\u017a\0\u0195\0\u01b0\0\u01cb\0\u01e6\0\u0201"
+ "\0\u021c\0\u0237\0\33\0\33\0\u0252\0\u026d\0\u0288\0\u02a3"
+ "\0\u02be\0\u02d9\0\u02f4\0\u030f\0\u032a\0\u0345\0\u0360\0\u037b"
+ "\0\u0396\0\u03b1\0\u03cc\0\u03e7\0\u0402\0\u041d\0\u0438\0\u0453"
+ "\0\u046e\0\33\0\u0489\0\u04a4\0\u04bf\0\33";
"\0\0\0\16\0\34\0\52\0\52\0\70\0\52\0\106"
+ "\0\52\0\124\0\52\0\52\0\52\0\52\0\52\0\52"
+ "\0\52\0\52\0\52\0\52\0\52";
private static int[] zzUnpackRowMap() {
int[] result = new int[62];
int[] result = new int[21];
int offset = 0;
offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
return result;
@@ -111,36 +119,14 @@ public final class TextLexer {
*/
private static final int[] ZZ_TRANS = zzUnpackTrans();
private static final String ZZ_TRANS_PACKED_0 =
"\5\2\1\3\20\2\1\4\3\2\1\5\41\0\1\6"
+ "\11\0\1\7\3\0\1\10\1\11\5\0\5\12\1\13"
+ "\1\14\1\12\1\15\1\16\5\12\1\17\2\12\1\20"
+ "\3\12\1\21\1\22\1\23\1\24\10\0\1\25\32\0"
+ "\1\26\35\0\1\27\32\0\1\30\30\0\1\31\43\0"
+ "\1\32\12\0\1\33\1\34\1\35\30\0\1\36\1\37"
+ "\1\40\40\0\1\41\30\0\1\42\42\0\1\43\14\0"
+ "\2\34\14\0\1\43\14\0\1\33\1\34\47\0\1\44"
+ "\14\0\2\37\14\0\1\44\14\0\1\36\1\37\42\0"
+ "\1\45\42\0\1\46\11\0\1\47\1\50\42\0\1\51"
+ "\32\0\1\52\21\0\2\50\7\0\1\52\43\0\1\53"
+ "\22\0\1\54\20\0\2\55\1\0\1\55\1\0\1\55"
+ "\5\0\1\55\3\0\1\55\6\0\1\55\17\0\1\56"
+ "\17\0\2\57\1\0\1\57\1\0\1\57\5\0\1\57"
+ "\3\0\1\57\6\0\1\57\20\0\1\60\16\0\2\61"
+ "\1\0\1\61\1\0\1\61\5\0\1\61\3\0\1\61"
+ "\6\0\1\61\21\0\1\62\15\0\2\63\1\0\1\63"
+ "\1\0\1\63\5\0\1\63\3\0\1\63\6\0\1\63"
+ "\16\0\1\64\20\0\2\65\1\0\1\65\1\0\1\65"
+ "\5\0\1\65\3\0\1\65\6\0\1\65\14\0\1\66"
+ "\22\0\2\67\1\0\1\67\1\0\1\67\5\0\1\67"
+ "\3\0\1\67\6\0\1\67\15\0\1\70\21\0\2\71"
+ "\1\0\1\71\1\0\1\71\5\0\1\71\2\0\1\72"
+ "\1\71\6\0\1\71\4\0\1\73\1\74\31\0\2\75"
+ "\1\0\1\75\1\0\1\75\5\0\1\75\3\0\1\75"
+ "\6\0\1\75\22\0\1\76\14\0\2\74\14\0\1\76"
+ "\32\0\1\72\13\0";
"\3\4\1\5\1\6\10\4\2\7\1\10\3\7\1\11"
+ "\5\10\3\7\2\12\1\7\2\12\1\11\10\12\16\0"
+ "\3\13\1\14\1\15\1\16\1\17\1\20\1\21\1\22"
+ "\1\23\1\24\1\25\2\0\1\10\4\0\5\10\3\0"
+ "\2\12\1\0\2\12\1\0\10\12";
private static int[] zzUnpackTrans() {
int[] result = new int[1242];
int[] result = new int[98];
int offset = 0;
offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result);
return result;
@@ -177,11 +163,10 @@ public final class TextLexer {
*/
private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute();
private static final String ZZ_ATTRIBUTE_PACKED_0 =
"\1\0\1\11\2\1\1\11\4\0\13\11\16\0\2\11"
+ "\25\0\1\11\3\0\1\11";
"\3\0\2\11\1\1\1\11\1\1\1\11\1\1\13\11";
private static int[] zzUnpackAttribute() {
int[] result = new int[62];
int[] result = new int[21];
int offset = 0;
offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
return result;
@@ -263,6 +248,7 @@ public final class TextLexer {
/* user code: */
StringBuffer string = null;
boolean finish = false;
String parameterName = null;
/**
* Create an empty lexer, yyrset will be called later to reset and assign
@@ -309,7 +295,7 @@ public final class TextLexer {
char[] map = new char[0x10000];
int i = 0; /* index in packed string */
int j = 0; /* index in unpacked array */
while (i < 82) {
while (i < 58) {
int count = packed.charAt(i++);
char value = packed.charAt(i++);
do {
@@ -633,12 +619,12 @@ public final class TextLexer {
}
case 18:
break;
case 3: {
case 7: {
throw new ParseException("Illegal escape sequence \"" + yytext() + "\"", yyline + 1);
}
case 19:
break;
case 6: {
case 13: {
if (string == null) {
string = new StringBuffer();
}
@@ -646,31 +632,25 @@ public final class TextLexer {
}
case 20:
break;
case 2: {
yybegin(PARAMETER);
if (string != null) {
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT, ret.toString());
}
}
case 21:
break;
case 11: {
if (string == null) {
string = new StringBuffer();
}
string.append('\b');
}
case 21:
break;
case 17: {
if (string == null) {
Pattern pat = Pattern.compile("\\[font ([0-9]+) height ([0-9]+)\\]");
Matcher m = pat.matcher(yytext());
if (m.matches()) {
return new ParsedSymbol(SymbolType.FONT, Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)));
}
} else {
yypushback(yylength());
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT, ret.toString());
}
}
case 22:
break;
case 13: {
case 17: {
if (string == null) {
string = new StringBuffer();
}
@@ -678,99 +658,80 @@ public final class TextLexer {
}
case 23:
break;
case 16: {
if (string == null) {
return new ParsedSymbol(SymbolType.COLOR, yytext().substring(8, yytext().length() - 1));
} else {
yypushback(yylength());
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT, ret.toString());
}
case 4: {
parameterName = yytext();
yybegin(VALUE);
}
case 24:
break;
case 8: {
if (string == null) {
string = new StringBuffer();
}
string.append(']');
case 6: {
yybegin(PARAMETER);
return new ParsedSymbol(SymbolType.PARAMETER, new Object[]{parameterName, yytext()});
}
case 25:
break;
case 15: {
if (string == null) {
return new ParsedSymbol(SymbolType.Y, Integer.parseInt(yytext().substring(3, yytext().length() - 1)));
} else {
yypushback(yylength());
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT, ret.toString());
}
}
case 26:
break;
case 14: {
if (string == null) {
return new ParsedSymbol(SymbolType.X, Integer.parseInt(yytext().substring(3, yytext().length() - 1)));
} else {
yypushback(yylength());
String ret = string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT, ret.toString());
}
}
case 27:
break;
case 7: {
if (string == null) {
string = new StringBuffer();
}
string.append('\t');
}
case 28:
break;
case 4: {
if (string == null) {
string = new StringBuffer();
}
string.append('[');
}
case 29:
break;
case 10: {
if (string == null) {
string = new StringBuffer();
}
string.append('\\');
string.append(']');
}
case 30:
case 26:
break;
case 12: {
if (string == null) {
string = new StringBuffer();
}
string.append('\"');
string.append('\t');
}
case 31:
case 27:
break;
case 8: {
if (string == null) {
string = new StringBuffer();
}
string.append('[');
}
case 28:
break;
case 9: {
if (string == null) {
string = new StringBuffer();
}
string.append('\\');
}
case 29:
break;
case 16: {
if (string == null) {
string = new StringBuffer();
}
string.append('\"');
}
case 30:
break;
case 15: {
if (string == null) {
string = new StringBuffer();
}
string.append('\r');
}
case 32:
case 31:
break;
case 5: {
case 14: {
if (string == null) {
string = new StringBuffer();
}
string.append('\f');
}
case 32:
break;
case 5: {
yybegin(YYINITIAL);
}
case 33:
break;
case 2: {
case 3: {
}
case 34:
break;
@@ -786,7 +747,7 @@ public final class TextLexer {
return new ParsedSymbol(SymbolType.TEXT, string.toString());
}
}
case 63:
case 22:
break;
default: {
return null;

View File

@@ -1,8 +1,21 @@
/* Flash assembler language lexer specification */
/*
* Copyright (C) 2013 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.tags.text;
import java.util.regex.*;
%%
@@ -20,6 +33,7 @@ import java.util.regex.*;
StringBuffer string = null;
boolean finish=false;
String parameterName=null;
/**
@@ -40,60 +54,17 @@ import java.util.regex.*;
%}
PositiveNumber = 0 | [1-9][0-9]*
NegativeNumber = - {PositiveNumber}
Number = {PositiveNumber}|{NegativeNumber}
Hex = [0-9a-f][0-9a-f]
Font = "[font " {PositiveNumber} " height " {PositiveNumber} "]"
Color = "[color #" {Hex}{Hex}{Hex} "]"
ColorA = "[color #" {Hex}{Hex}{Hex}{Hex} "]"
X = "[x " {Number} "]"
Y = "[y " {Number} "]"
Parameter = [a-z0-9_]+
Value = [^ \]]+
%state PARAMETER,VALUE
%%
<YYINITIAL> {
{Font} {
if(string==null){
Pattern pat = Pattern.compile("\\[font ([0-9]+) height ([0-9]+)\\]");
Matcher m=pat.matcher(yytext());
if(m.matches()){
return new ParsedSymbol(SymbolType.FONT,Integer.parseInt(m.group(1)),Integer.parseInt(m.group(2)));
}
}else{
yypushback(yylength());
String ret=string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT,ret.toString());
}
}
{Color}|{ColorA} {
if(string==null){
return new ParsedSymbol(SymbolType.COLOR,yytext().substring(8,yytext().length()-1));
}else{
yypushback(yylength());
String ret=string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT,ret.toString());
}
}
{X} {
if(string==null){
return new ParsedSymbol(SymbolType.X,Integer.parseInt(yytext().substring(3,yytext().length()-1)));
}else{
yypushback(yylength());
String ret=string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT,ret.toString());
}
}
{Y} {
if(string==null){
return new ParsedSymbol(SymbolType.Y,Integer.parseInt(yytext().substring(3,yytext().length()-1)));
}else{
yypushback(yylength());
"[" {
yybegin(PARAMETER);
if(string!=null){
String ret=string.toString();
string = null;
return new ParsedSymbol(SymbolType.TEXT,ret.toString());
@@ -117,6 +88,28 @@ Y = "[y " {Number} "]"
<<EOF>> { if(finish){return null;}else{finish=true; return new ParsedSymbol(SymbolType.TEXT,string.toString());}}
}
<PARAMETER> {
" " {}
{Parameter} {
parameterName = yytext();
yybegin(VALUE);
}
"]" {
yybegin(YYINITIAL);
}
}
<VALUE> {
" " {}
{Value} {
yybegin(PARAMETER);
return new ParsedSymbol(SymbolType.PARAMETER,new Object[]{parameterName,yytext()});
}
"]" {
yybegin(YYINITIAL);
}
}
/* error fallback */
.|\n { }
<<EOF>> { return null; }

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.ReReadableInputStream;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.action.Action;
@@ -142,7 +144,7 @@ public class BUTTONCONDACTION implements ASMSource {
*/
@Override
public String getASMSource(int version, boolean hex) {
return Action.actionsToString(0, getActions(version), null, version, hex, getPos() + 4);
return Action.actionsToString(listeners, 0, getActions(version), null, version, hex, getPos() + 4);
}
/**
@@ -164,7 +166,13 @@ public class BUTTONCONDACTION implements ASMSource {
@Override
public List<Action> getActions(int version) {
try {
return Action.removeNops(0, SWFInputStream.readActionList(0, getPos() + 4, new ReReadableInputStream(new ByteArrayInputStream(actionBytes)), version, 0, -1), version, getPos() + 4);
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
List<Action> list = SWFInputStream.readActionList(listeners, 0, getPos() + 4, new ReReadableInputStream(new ByteArrayInputStream(actionBytes)), version, 0, -1);
if (deobfuscate) {
list = Action.removeNops(0, list, version, getPos() + 4);
}
return list;
} catch (Exception ex) {
Logger.getLogger(BUTTONCONDACTION.class.getName()).log(Level.SEVERE, null, ex);
return new ArrayList<Action>();
@@ -185,4 +193,15 @@ public class BUTTONCONDACTION implements ASMSource {
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = actionBytes;
}
List<DisassemblyListener> listeners = new ArrayList<DisassemblyListener>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
}

View File

@@ -16,6 +16,8 @@
*/
package com.jpexs.decompiler.flash.types;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.ReReadableInputStream;
import com.jpexs.decompiler.flash.SWFInputStream;
import com.jpexs.decompiler.flash.action.Action;
@@ -105,7 +107,7 @@ public class CLIPACTIONRECORD implements ASMSource {
*/
@Override
public String getASMSource(int version, boolean hex) {
return Action.actionsToString(0, getActions(version), null, version, hex, getPos() + hdrPos);
return Action.actionsToString(listeners, 0, getActions(version), null, version, hex, getPos() + hdrPos);
}
/**
@@ -121,7 +123,12 @@ public class CLIPACTIONRECORD implements ASMSource {
@Override
public List<Action> getActions(int version) {
try {
return Action.removeNops(0, SWFInputStream.readActionList(0, getPos() + hdrPos, new ReReadableInputStream(new ByteArrayInputStream(actionBytes)), version, 0, -1), version, getPos() + hdrPos);
boolean deobfuscate = (Boolean) Configuration.getConfig("autoDeobfuscate", true);
List<Action> list = SWFInputStream.readActionList(listeners, 0, getPos() + hdrPos, new ReReadableInputStream(new ByteArrayInputStream(actionBytes)), version, 0, -1);
if (deobfuscate) {
list = Action.removeNops(0, list, version, getPos() + hdrPos);
}
return list;
} catch (Exception ex) {
Logger.getLogger(BUTTONCONDACTION.class.getName()).log(Level.SEVERE, null, ex);
return new ArrayList<Action>();
@@ -142,4 +149,15 @@ public class CLIPACTIONRECORD implements ASMSource {
public void setActionBytes(byte[] actionBytes) {
this.actionBytes = actionBytes;
}
List<DisassemblyListener> listeners = new ArrayList<DisassemblyListener>();
@Override
public void addDisassemblyListener(DisassemblyListener listener) {
listeners.add(listener);
}
@Override
public void removeDisassemblyListener(DisassemblyListener listener) {
listeners.remove(listener);
}
}

View File

@@ -51,6 +51,13 @@ public class RECT {
public RECT() {
}
public RECT(RECT r) {
Xmin = r.Xmin;
Xmax = r.Xmax;
Ymin = r.Ymin;
Ymax = r.Ymax;
}
@Override
public String toString() {
return "[RECT x=" + Xmin + " to " + Xmax + ", y=" + Ymin + " to " + Ymax + "]";