mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-27 00:11:22 +00:00
More documentation.
This commit is contained in:
@@ -16,24 +16,10 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppResources;
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.*;
|
||||
import com.jpexs.decompiler.flash.action.as2.Trait;
|
||||
import com.jpexs.decompiler.flash.action.deobfuscation.ActionDeobfuscator;
|
||||
import com.jpexs.decompiler.flash.action.model.ActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.*;
|
||||
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer;
|
||||
@@ -41,12 +27,7 @@ import com.jpexs.decompiler.flash.action.parser.script.VariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionEnd;
|
||||
import com.jpexs.decompiler.flash.action.special.ActionStore;
|
||||
import com.jpexs.decompiler.flash.action.swf3.ActionSetTarget;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionEquals;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionNot;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionSetTarget2;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
import com.jpexs.decompiler.flash.action.swf4.*;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
@@ -63,17 +44,7 @@ import com.jpexs.decompiler.flash.helpers.NulWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphPartChangeException;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
import com.jpexs.decompiler.graph.SecondPassException;
|
||||
import com.jpexs.decompiler.graph.TranslateException;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.*;
|
||||
import com.jpexs.decompiler.graph.model.CommentItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
@@ -81,16 +52,10 @@ import com.jpexs.helpers.ByteArrayRange;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -99,16 +64,25 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Represents one ACTIONRECORD, also has some static method to work with Actions
|
||||
* Represents one ACTIONRECORD, also has some static method to work with Actions.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public abstract class Action implements GraphSourceItem {
|
||||
|
||||
/**
|
||||
* When to inform listeners about progress
|
||||
*/
|
||||
private static final int INFORM_LISTENER_RESOLUTION = 1000;
|
||||
|
||||
/**
|
||||
* Whether this action is ignored
|
||||
*/
|
||||
private boolean ignored = false;
|
||||
|
||||
/**
|
||||
* File offset of this action
|
||||
*/
|
||||
public long fileOffset = -1;
|
||||
|
||||
/**
|
||||
@@ -121,51 +95,57 @@ public abstract class Action implements GraphSourceItem {
|
||||
*/
|
||||
protected int actionLength;
|
||||
|
||||
/**
|
||||
* Address of this action
|
||||
*/
|
||||
private long address;
|
||||
|
||||
/**
|
||||
* Virtual address (address before deobfuscation)
|
||||
*/
|
||||
private long virtualAddress = -1;
|
||||
|
||||
/**
|
||||
* Charset - SWFs version 5 and lower do not use UTF-8
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
@Override
|
||||
public long getLineOffset() {
|
||||
return fileOffset;
|
||||
}
|
||||
|
||||
public String getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Names of ActionScript properties
|
||||
*/
|
||||
public static final String[] propertyNames = new String[]{
|
||||
"_X",
|
||||
"_Y",
|
||||
"_xscale",
|
||||
"_yscale",
|
||||
"_currentframe",
|
||||
"_totalframes",
|
||||
"_alpha",
|
||||
"_visible",
|
||||
"_width",
|
||||
"_height",
|
||||
"_rotation",
|
||||
"_target",
|
||||
"_framesloaded",
|
||||
"_name",
|
||||
"_droptarget",
|
||||
"_url",
|
||||
"_highquality",
|
||||
"_focusrect",
|
||||
"_soundbuftime",
|
||||
"_quality",
|
||||
"_xmouse",
|
||||
"_ymouse"
|
||||
"_X",
|
||||
"_Y",
|
||||
"_xscale",
|
||||
"_yscale",
|
||||
"_currentframe",
|
||||
"_totalframes",
|
||||
"_alpha",
|
||||
"_visible",
|
||||
"_width",
|
||||
"_height",
|
||||
"_rotation",
|
||||
"_target",
|
||||
"_framesloaded",
|
||||
"_name",
|
||||
"_droptarget",
|
||||
"_url",
|
||||
"_highquality",
|
||||
"_focusrect",
|
||||
"_soundbuftime",
|
||||
"_quality",
|
||||
"_xmouse",
|
||||
"_ymouse"
|
||||
};
|
||||
|
||||
/**
|
||||
* Property names list
|
||||
*/
|
||||
public static final List<String> propertyNamesList = Arrays.asList(propertyNames);
|
||||
|
||||
/**
|
||||
* Property names list in lower case
|
||||
*/
|
||||
public static final List<String> propertyNamesListLowerCase = new ArrayList<>();
|
||||
|
||||
{
|
||||
@@ -174,10 +154,32 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(Action.class.getName());
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Gets the line offset.
|
||||
* @return Line offset
|
||||
*/
|
||||
@Override
|
||||
public long getLineOffset() {
|
||||
return fileOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets charset
|
||||
* @return Charset
|
||||
*/
|
||||
public String getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs new Action
|
||||
*
|
||||
* @param actionCode Action type identifier
|
||||
* @param actionLength Length of action data
|
||||
@@ -188,13 +190,15 @@ public abstract class Action implements GraphSourceItem {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new Action
|
||||
*/
|
||||
public Action() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns address of this action
|
||||
*
|
||||
* @return address of this action
|
||||
* Gets the address.
|
||||
* @return Address
|
||||
*/
|
||||
@Override
|
||||
public long getAddress() {
|
||||
@@ -202,9 +206,9 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return code of this action
|
||||
* Gets code of this action.
|
||||
*
|
||||
* @return code of this action
|
||||
* @return Code of this action
|
||||
*/
|
||||
public int getActionCode() {
|
||||
return actionCode;
|
||||
@@ -212,15 +216,15 @@ public abstract class Action implements GraphSourceItem {
|
||||
|
||||
/**
|
||||
* Gets all addresses which are referenced from this action and/or
|
||||
* subactions
|
||||
* subactions.
|
||||
*
|
||||
* @param refs list of addresses
|
||||
* @param refs List of addresses
|
||||
*/
|
||||
public void getRef(Set<Long> refs) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all addresses which are referenced from the list of actions
|
||||
* Gets all addresses which are referenced from the list of actions.
|
||||
*
|
||||
* @param list List of actions
|
||||
* @return List of addresses
|
||||
@@ -233,12 +237,16 @@ public abstract class Action implements GraphSourceItem {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets total length of this action.
|
||||
* @return Total length of this action
|
||||
*/
|
||||
public int getTotalActionLength() {
|
||||
return actionLength + 1 + (actionCode >= 0x80 ? 2 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets address of this instruction
|
||||
* Sets address of this instruction.
|
||||
*
|
||||
* @param address Address
|
||||
*/
|
||||
@@ -247,7 +255,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
*/
|
||||
@@ -257,7 +265,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads String from FlasmLexer
|
||||
* Reads String from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @return String value
|
||||
@@ -273,7 +281,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads Block startServer from FlasmLexer
|
||||
* Reads Block startServer from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @throws IOException
|
||||
@@ -287,7 +295,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads Identifier from FlasmLexer
|
||||
* Reads Identifier from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @return Identifier name
|
||||
@@ -303,7 +311,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads long value from FlasmLexer
|
||||
* Reads long value from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @return long value
|
||||
@@ -319,7 +327,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads boolean value from FlasmLexer
|
||||
* Reads boolean value from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @return boolean value
|
||||
@@ -334,6 +342,13 @@ public abstract class Action implements GraphSourceItem {
|
||||
return (Boolean) symb.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads optional comma from FlasmLexer.
|
||||
*
|
||||
* @param lex FlasmLexer
|
||||
* @throws IOException
|
||||
* @throws ActionParseException
|
||||
*/
|
||||
protected void lexOptionalComma(FlasmLexer lex) throws IOException, ActionParseException {
|
||||
ASMParsedSymbol symb = lex.lex();
|
||||
if (symb.type != ASMParsedSymbol.TYPE_COMMA) {
|
||||
@@ -342,7 +357,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets action converted to bytes
|
||||
* Gets action converted to bytes.
|
||||
*
|
||||
* @param version SWF version
|
||||
* @return Array of bytes
|
||||
@@ -359,11 +374,16 @@ public abstract class Action implements GraphSourceItem {
|
||||
return surroundWithAction(baos.toByteArray(), version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content bytes of action.
|
||||
* @param sos SWFOutputStream
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void getContentBytes(SWFOutputStream sos) throws IOException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of action converted to bytes
|
||||
* Gets the length of action converted to bytes.
|
||||
*
|
||||
* @return Length
|
||||
*/
|
||||
@@ -372,12 +392,16 @@ public abstract class Action implements GraphSourceItem {
|
||||
return getContentBytesLength() + (actionCode >= 0x80 ? 3 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of content bytes of action.
|
||||
* @return Length
|
||||
*/
|
||||
protected int getContentBytesLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the action length to the length calculated from action bytes
|
||||
* Updates the action length to the length calculated from action bytes.
|
||||
*/
|
||||
public void updateLength() {
|
||||
int length = getBytesLength();
|
||||
@@ -385,7 +409,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Surrounds byte array with Action header
|
||||
* Surrounds byte array with Action header.
|
||||
*
|
||||
* @param data Byte array
|
||||
* @param version SWF version
|
||||
@@ -407,16 +431,20 @@ public abstract class Action implements GraphSourceItem {
|
||||
return baos2.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets file offset.
|
||||
* @return File offset
|
||||
*/
|
||||
@Override
|
||||
public long getFileOffset() {
|
||||
return fileOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of Actions to bytes
|
||||
* Converts list of Actions to bytes.
|
||||
*
|
||||
* @param list List of actions
|
||||
* @param addZero Whether or not to add 0 UI8 value to the end
|
||||
* @param addZero Whether to add 0 UI8 value to the end
|
||||
* @param version SWF version
|
||||
* @return Array of bytes
|
||||
*/
|
||||
@@ -437,11 +465,25 @@ public abstract class Action implements GraphSourceItem {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of Actions to bytes.
|
||||
* @param list List of actions
|
||||
* @param addZero Whether to add 0 UI8 value to the end
|
||||
* @param version SWF version
|
||||
* @return ByteArrayRange
|
||||
*/
|
||||
public static ByteArrayRange actionsToByteArrayRange(List<Action> list, boolean addZero, int version) {
|
||||
byte[] bytes = Action.actionsToBytes(list, addZero, version);
|
||||
return new ByteArrayRange(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets constant pool of actions.
|
||||
* @param src ASMSource
|
||||
* @param constantPools List of constant pools
|
||||
* @param tryInline Whether to try to inline constant pools
|
||||
* @throws ConstantPoolTooBigException
|
||||
*/
|
||||
public static void setConstantPools(ASMSource src, List<List<String>> constantPools, boolean tryInline) throws ConstantPoolTooBigException {
|
||||
try {
|
||||
ActionList actions = src.getActions();
|
||||
@@ -485,7 +527,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set addresses of actions in the list
|
||||
* Sets addresses of actions in the list.
|
||||
*
|
||||
* @param list List of actions
|
||||
* @param baseAddress Address of first action in the list
|
||||
@@ -506,7 +548,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of actions to ASM source
|
||||
* Converts list of actions to ASM source.
|
||||
*
|
||||
* @param listeners
|
||||
* @param address
|
||||
@@ -725,6 +767,16 @@ public abstract class Action implements GraphSourceItem {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts constant pool actions to String.
|
||||
* @param listeners List of listeners
|
||||
* @param address Address
|
||||
* @param list List of actions
|
||||
* @param version SWF version
|
||||
* @param exportMode Export mode
|
||||
* @param writer GraphTextWriter
|
||||
* @return GraphTextWriter
|
||||
*/
|
||||
public static GraphTextWriter constantPoolActionsToString(List<DisassemblyListener> listeners, long address, ActionList list, int version, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
int poolIdx = 0;
|
||||
writer.appendNoHilight(Helper.constants).newLine();
|
||||
@@ -752,9 +804,9 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert action to ASM source
|
||||
* Converts action to ASM source.
|
||||
*
|
||||
* @param container
|
||||
* @param container Container
|
||||
* @param knownAddreses List of important offsets to mark as labels
|
||||
* @param exportMode PCode or hex?
|
||||
* @return String of P-code source
|
||||
@@ -763,20 +815,37 @@ public abstract class Action implements GraphSourceItem {
|
||||
return toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the action.
|
||||
* @param lda Local data area
|
||||
* @return Whether the action was executed successfully
|
||||
*/
|
||||
public abstract boolean execute(LocalDataArea lda);
|
||||
|
||||
/**
|
||||
* Gets the number of stack items that are popped by this item.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @return Number of stack items that are popped by this item
|
||||
*/
|
||||
@Override
|
||||
public int getStackPopCount(BaseLocalData localData, TranslateStack stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of stack items that are pushed by this item.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @return Number of stack items that are pushed by this item
|
||||
*/
|
||||
@Override
|
||||
public int getStackPushCount(BaseLocalData localData, TranslateStack stack) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops long value off the stack
|
||||
* Pops long value off the stack.
|
||||
*
|
||||
* @param stack Stack
|
||||
* @return long value
|
||||
@@ -791,19 +860,13 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts action index to address in the specified list of actions
|
||||
* Converts action index to address in the specified list of actions.
|
||||
*
|
||||
* @param actions List of actions
|
||||
* @param ip Action index
|
||||
* @return address
|
||||
*/
|
||||
public static long ip2adr(List<Action> actions, int ip) {
|
||||
/* List<Action> actions=new ArrayList<Action>();
|
||||
for(GraphSourceItem s:sources){
|
||||
if(s instanceof Action){
|
||||
actions.add((Action)s);
|
||||
}
|
||||
}*/
|
||||
if (ip >= actions.size()) {
|
||||
if (actions.isEmpty()) {
|
||||
return 0;
|
||||
@@ -817,11 +880,11 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts address to action index in the specified list of actions
|
||||
* Converts address to action index in the specified list of actions.
|
||||
*
|
||||
* @param actions List of actions
|
||||
* @param addr Address
|
||||
* @return action index
|
||||
* @return Action index
|
||||
*/
|
||||
public static int adr2ip(List<Action> actions, long addr) {
|
||||
for (int ip = 0; ip < actions.size(); ip++) {
|
||||
@@ -838,20 +901,31 @@ public abstract class Action implements GraphSourceItem {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts actions to ActionScript source code - decompiles.
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param asm ASM source
|
||||
* @param actions List of actions
|
||||
* @param path Path
|
||||
* @param writer Writer
|
||||
* @param charset Charset
|
||||
* @return Writer
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static GraphTextWriter actionsToSource(Map<String, Map<String, Trait>> uninitializedClassTraits, final ASMSource asm, final List<Action> actions, final String path, GraphTextWriter writer, String charset) throws InterruptedException {
|
||||
return Action.actionsToSource(uninitializedClassTraits, asm, actions, path, writer, charset, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of actions to ActionScript source code
|
||||
* Converts list of actions to ActionScript source code.
|
||||
*
|
||||
* @param asm
|
||||
* @param asm ASM source
|
||||
* @param actions List of actions
|
||||
* @param path
|
||||
* @param writer
|
||||
* @param charset
|
||||
* @param treeOperations
|
||||
* @return
|
||||
* @param path Path
|
||||
* @param writer Writer
|
||||
* @param charset Charset
|
||||
* @param treeOperations List of tree operations
|
||||
* @return Writer
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
public static GraphTextWriter actionsToSource(Map<String, Map<String, Trait>> uninitializedClassTraits, final ASMSource asm, final List<Action> actions, final String path, GraphTextWriter writer, String charset, List<ActionTreeOperation> treeOperations) throws InterruptedException {
|
||||
@@ -916,20 +990,33 @@ public abstract class Action implements GraphSourceItem {
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of actions to List of treeItems
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param insideDoInitAction Inside DoInitAction?
|
||||
* @param insideFunction Inside function?
|
||||
* @param actions List of actions
|
||||
* @param version SWF version
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @param charset Charset
|
||||
* @return List of treeItems
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static List<GraphTargetItem> actionsToTree(Map<String, Map<String, Trait>> uninitializedClassTraits, boolean insideDoInitAction, boolean insideFunction, List<Action> actions, int version, int staticOperation, String path, String charset) throws InterruptedException {
|
||||
return actionsToTree(uninitializedClassTraits, insideDoInitAction, insideFunction, new HashMap<>(), new HashMap<>(), new HashMap<>(), actions, version, staticOperation, path, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of actions to List of treeItems
|
||||
* Converts list of actions to List of treeItems.
|
||||
*
|
||||
* @param regNames Register names
|
||||
* @param variables
|
||||
* @param functions
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param actions List of actions
|
||||
* @param version SWF version
|
||||
* @param staticOperation
|
||||
* @param path
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @return List of treeItems
|
||||
* @throws java.lang.InterruptedException
|
||||
*/
|
||||
@@ -950,9 +1037,9 @@ public abstract class Action implements GraphSourceItem {
|
||||
/**
|
||||
* Translates this function to stack and output.
|
||||
*
|
||||
* @param uninitializedClassTraits
|
||||
* @param secondPassData
|
||||
* @param insideDoInitAction
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Inside DoInitAction?
|
||||
* @param lineStartIns Line start instruction
|
||||
* @param stack Stack
|
||||
* @param output Output
|
||||
@@ -966,42 +1053,83 @@ public abstract class Action implements GraphSourceItem {
|
||||
public void translate(Map<String, Map<String, Trait>> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, GraphSourceItem lineStartIns, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the item to target items.
|
||||
* @param localData Local data
|
||||
* @param stack Stack
|
||||
* @param output Output list
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public void translate(BaseLocalData localData, TranslateStack stack, List<GraphTargetItem> output, int staticOperation, String path) throws InterruptedException {
|
||||
ActionLocalData aLocalData = (ActionLocalData) localData;
|
||||
translate(aLocalData.uninitializedClassTraits, aLocalData.secondPassData, aLocalData.insideDoInitAction, aLocalData.lineStartAction, stack, output, aLocalData.regNames, aLocalData.variables, aLocalData.functions, staticOperation, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this item is a jump.
|
||||
* @return True if this item is a jump, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isJump() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this item is a branch.
|
||||
* @return True if this item is a branch, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isBranch() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this item is an exit (throw, return, etc.).
|
||||
* @return True if this item is an exit, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isExit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets branches
|
||||
* @param code Code
|
||||
* @return List of IPs to branch to
|
||||
*/
|
||||
@Override
|
||||
public List<Integer> getBranches(GraphSource code) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this item is ignored.
|
||||
* @return True if this item is ignored, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isIgnored() {
|
||||
return ignored;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this item is ignored.
|
||||
* @param ignored True if this item is ignored, false otherwise
|
||||
* @param pos Sub position
|
||||
*/
|
||||
@Override
|
||||
public void setIgnored(boolean ignored, int pos) {
|
||||
this.ignored = ignored;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares variables for the given container.
|
||||
* @param cnt Container
|
||||
* @param variables Variables - map of variable names to variable items
|
||||
* @return
|
||||
*/
|
||||
private static HashMap<String, GraphTargetItem> prepareVariables(GraphSourceItemContainer cnt, HashMap<String, GraphTargetItem> variables) {
|
||||
HashMap<String, GraphTargetItem> variables2 = new LinkedHashMap<>(variables);
|
||||
if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) {
|
||||
@@ -1014,12 +1142,34 @@ public abstract class Action implements GraphSourceItem {
|
||||
return variables2;
|
||||
}
|
||||
|
||||
public static List<GraphTargetItem> actionsPartToTree(ActionGraph graph, Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
|
||||
/**
|
||||
* Converts list of actions to tree.
|
||||
* @param graph ActionGraph
|
||||
* @param switchParts Switch parts
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Inside DoInitAction?
|
||||
* @param lineStartActionRef Line start action reference
|
||||
* @param registerNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param stack Stack
|
||||
* @param actions List of actions
|
||||
* @param start Start
|
||||
* @param end End
|
||||
* @param version SWF version
|
||||
* @param staticOperation Static operation
|
||||
* @param path Path
|
||||
* @param charset Charset
|
||||
* @return List of tree items
|
||||
* @throws InterruptedException
|
||||
* @throws GraphPartChangeException
|
||||
*/
|
||||
public static List<GraphTargetItem> actionsPartToTree(ActionGraph graph, Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> lineStartActionRef, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
|
||||
if (start < actions.size() && (end > 0) && (start > 0)) {
|
||||
logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""});
|
||||
}
|
||||
ActionLocalData localData = new ActionLocalData(switchParts, secondPassData, insideDoInitAction, registerNames, variables, functions, graph.getUninitializedClassTraits());
|
||||
localData.lineStartAction = fi.getVal();
|
||||
localData.lineStartAction = lineStartActionRef.getVal();
|
||||
List<GraphTargetItem> output = new ArrayList<>();
|
||||
int ip = start;
|
||||
boolean isWhile = false;
|
||||
@@ -1057,7 +1207,7 @@ public abstract class Action implements GraphSourceItem {
|
||||
|
||||
if (isStackEmpty) {
|
||||
localData.lineStartAction = action;
|
||||
fi.setVal(action);
|
||||
lineStartActionRef.setVal(action);
|
||||
}
|
||||
if (action instanceof GraphSourceItemContainer) {
|
||||
GraphSourceItemContainer cnt = (GraphSourceItemContainer) action;
|
||||
@@ -1153,6 +1303,11 @@ public abstract class Action implements GraphSourceItem {
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets item without global prefix.
|
||||
* @param ti Target item
|
||||
* @return Target item without global prefix
|
||||
*/
|
||||
public static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) {
|
||||
GraphTargetItem t = ti;
|
||||
if (!(t instanceof GetMemberActionItem)) {
|
||||
@@ -1181,11 +1336,20 @@ public abstract class Action implements GraphSourceItem {
|
||||
return ti;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the loops are ignored.
|
||||
* @return True if the loops are ignored, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean ignoredLoops() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets constant pool to actions.
|
||||
* @param actions List of actions
|
||||
* @param cpool Constant pool
|
||||
*/
|
||||
public static void setConstantPool(List<? extends GraphSourceItem> actions, ConstantPool cpool) {
|
||||
for (GraphSourceItem a : actions) {
|
||||
if (a instanceof ActionPush) {
|
||||
@@ -1206,11 +1370,24 @@ public abstract class Action implements GraphSourceItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ASM source with replaced Actions.
|
||||
* @param container Container
|
||||
* @param knownAddreses Known addresses
|
||||
* @param exportMode Export mode
|
||||
* @param writer Writer
|
||||
* @return Writer
|
||||
*/
|
||||
public GraphTextWriter getASMSourceReplaced(ActionList container, Set<Long> knownAddreses, ScriptExportMode exportMode, GraphTextWriter writer) {
|
||||
writer.appendNoHilight(getASMSource(container, knownAddreses, exportMode));
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts ECMA object to float point.
|
||||
* @param o Object
|
||||
* @return Float point
|
||||
*/
|
||||
public static double toFloatPoint(Object o) {
|
||||
if (o instanceof Double) {
|
||||
return (Double) o;
|
||||
@@ -1240,6 +1417,14 @@ public abstract class Action implements GraphSourceItem {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Get to Set.
|
||||
* (variables, members, properties)
|
||||
* @param get Get item
|
||||
* @param value Value
|
||||
* @param variables Variables
|
||||
* @return Set item
|
||||
*/
|
||||
public static GraphTargetItem gettoset(GraphTargetItem get, GraphTargetItem value, List<VariableActionItem> variables) {
|
||||
GraphTargetItem ret = get;
|
||||
boolean boxed = false;
|
||||
@@ -1269,26 +1454,51 @@ public abstract class Action implements GraphSourceItem {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this item is a DeobfuscatePop instruction.
|
||||
* It is a special instruction for deobfuscation.
|
||||
* @return True if this item is a DeobfuscatePop instruction, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isDeobfuscatePop() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the line in the high level source code.
|
||||
* @return Line
|
||||
*/
|
||||
@Override
|
||||
public int getLine() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the high level source code file name.
|
||||
* @return File name
|
||||
*/
|
||||
@Override
|
||||
public String getFile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets virtual address. A virtual address can be used for storing original
|
||||
* address before applying deobfuscation.
|
||||
*
|
||||
* @return Virtual address
|
||||
*/
|
||||
@Override
|
||||
public long getVirtualAddress() {
|
||||
return virtualAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets virtual address. A virtual address can be used for storing original
|
||||
* address before applying deobfuscation.
|
||||
*
|
||||
* @param virtualAddress Virtual address
|
||||
*/
|
||||
@Override
|
||||
public void setVirtualAddress(long virtualAddress) {
|
||||
this.virtualAddress = virtualAddress;
|
||||
|
||||
+16
-9
@@ -26,12 +26,8 @@ import com.jpexs.decompiler.flash.action.swf5.ActionReturn;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Cleaner for ActionDefineFunction push registers. From Flash 7 onwards,
|
||||
@@ -49,11 +45,22 @@ import java.util.TreeSet;
|
||||
*/
|
||||
public class ActionDefineFunctionPushRegistersCleaner extends SWFDecompilerAdapter {
|
||||
|
||||
/**
|
||||
* Called when an action list is parsed
|
||||
* @param actions Action list
|
||||
* @param swf SWF object
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public void actionListParsed(ActionList actions, SWF swf) throws InterruptedException {
|
||||
cleanActionDefineFunctions(actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans ActionDefineFunctions
|
||||
*
|
||||
* @param actions Action list
|
||||
*/
|
||||
private void cleanActionDefineFunctions(ActionList actions) {
|
||||
for (int i = actions.size() - 1; i >= 0; i--) {
|
||||
Action action = actions.get(i);
|
||||
@@ -71,11 +78,11 @@ public class ActionDefineFunctionPushRegistersCleaner extends SWFDecompilerAdapt
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param code
|
||||
* Cleans push registers from ActionDefineFunction
|
||||
* @param code Action list
|
||||
* @param startIndex Index of first Action in DefineFunction body
|
||||
* @param count Count of actions in DefineFunction
|
||||
* @return
|
||||
* @return True if registers were cleaned, false otherwise
|
||||
*/
|
||||
private boolean cleanPushRegisters(ActionList code, int startIndex, int count) {
|
||||
if (count == 0) {
|
||||
|
||||
@@ -21,79 +21,60 @@ import com.jpexs.decompiler.flash.FinalProcessLocalData;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.action.as2.ActionScript2ClassDetector;
|
||||
import com.jpexs.decompiler.flash.action.as2.Trait;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.EnumerateActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.EnumeratedValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetTargetActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetTypeActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
|
||||
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
|
||||
import com.jpexs.decompiler.flash.action.model.*;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.operations.EqActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.operations.StrictEqActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.operations.StrictNeqActionItem;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionEquals;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionIf;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionJump;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionNot;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionPush;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
import com.jpexs.decompiler.flash.action.swf4.*;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.Block;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphPartChangeException;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.Loop;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
import com.jpexs.decompiler.graph.StopPartKind;
|
||||
import com.jpexs.decompiler.graph.ThrowState;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
import com.jpexs.decompiler.graph.model.SwitchItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import com.jpexs.decompiler.graph.model.WhileItem;
|
||||
import com.jpexs.decompiler.graph.*;
|
||||
import com.jpexs.decompiler.graph.model.*;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* ActionScript 1/2 graph
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionGraph extends Graph {
|
||||
|
||||
/**
|
||||
* Inside DoInitAction
|
||||
*/
|
||||
private boolean insideDoInitAction;
|
||||
|
||||
/**
|
||||
* Inside function
|
||||
*/
|
||||
private boolean insideFunction;
|
||||
|
||||
/**
|
||||
* Uninitialized class traits - maps class name to map of trait name to trait
|
||||
*/
|
||||
private Map<String, Map<String, Trait>> uninitializedClassTraits;
|
||||
|
||||
/**
|
||||
* Constructs ActionGraph
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param path Path
|
||||
* @param insideDoInitAction Inside DoInitAction
|
||||
* @param insideFunction Inside function
|
||||
* @param code Code
|
||||
* @param registerNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param version Version
|
||||
* @param charset Charset
|
||||
*/
|
||||
public ActionGraph(Map<String, Map<String, Trait>> uninitializedClassTraits, String path, boolean insideDoInitAction, boolean insideFunction, List<Action> code, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int version, String charset) {
|
||||
super(new ActionGraphSource(path, insideDoInitAction, code, version, registerNames, variables, functions, charset), new ArrayList<>());
|
||||
this.uninitializedClassTraits = uninitializedClassTraits;
|
||||
@@ -101,15 +82,28 @@ public class ActionGraph extends Graph {
|
||||
this.insideFunction = insideFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get uninitialized class traits
|
||||
* @return Uninitialized class traits - maps class name to map of trait name to trait
|
||||
*/
|
||||
public Map<String, Map<String, Trait>> getUninitializedClassTraits() {
|
||||
return uninitializedClassTraits;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the graphSource
|
||||
* @return GraphSource
|
||||
*/
|
||||
@Override
|
||||
public ActionGraphSource getGraphCode() {
|
||||
return (ActionGraphSource) code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets sub-graphs
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, Graph> getSubGraphs() {
|
||||
LinkedHashMap<String, Graph> subgraphs = new LinkedHashMap<>();
|
||||
@@ -141,15 +135,40 @@ public class ActionGraph extends Graph {
|
||||
return subgraphs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether is inside DoInitAction.
|
||||
* @return True if is inside DoInitAction, false otherwise
|
||||
*/
|
||||
public boolean isInsideDoInitAction() {
|
||||
return insideDoInitAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called after populating all parts.
|
||||
* @param allParts All parts
|
||||
*/
|
||||
@Override
|
||||
protected void afterPopupateAllParts(Set<GraphPart> allParts) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates via Graph - decompiles.
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Inside DoInitAction
|
||||
* @param insideFunction Inside function
|
||||
* @param registerNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param code Code
|
||||
* @param version Version
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @param charset Charset
|
||||
* @return List of graph target items
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static List<GraphTargetItem> translateViaGraph(Map<String, Map<String, Trait>> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, boolean insideFunction, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> code, int version, int staticOperation, String path, String charset) throws InterruptedException {
|
||||
ActionGraph g = new ActionGraph(uninitializedClassTraits, path, insideDoInitAction, insideFunction, code, registerNames, variables, functions, version, charset);
|
||||
ActionLocalData localData = new ActionLocalData(secondPassData, insideDoInitAction, registerNames, uninitializedClassTraits);
|
||||
@@ -157,6 +176,13 @@ public class ActionGraph extends Graph {
|
||||
return g.translate(localData, staticOperation, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Final process stack.
|
||||
* Override this method to provide custom behavior.
|
||||
* @param stack Translate stack
|
||||
* @param output Output
|
||||
* @param path Path
|
||||
*/
|
||||
@Override
|
||||
public void finalProcessStack(TranslateStack stack, List<GraphTargetItem> output, String path) {
|
||||
if (stack.size() > 0) {
|
||||
@@ -172,6 +198,13 @@ public class ActionGraph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a part can be a break candidate.
|
||||
* @param localData Local data
|
||||
* @param part Part
|
||||
* @param throwStates List of throw states
|
||||
* @return True if part can be a break candidate
|
||||
*/
|
||||
@Override
|
||||
protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List<ThrowState> throwStates) {
|
||||
if (part.refs.size() <= 1) {
|
||||
@@ -190,6 +223,14 @@ public class ActionGraph extends Graph {
|
||||
return !isSwitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Final process.
|
||||
* @param list List of GraphTargetItems
|
||||
* @param level Level
|
||||
* @param localData Local data
|
||||
* @param path Path
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
protected void finalProcess(List<GraphTargetItem> list, int level, FinalProcessLocalData localData, String path) throws InterruptedException {
|
||||
|
||||
@@ -464,6 +505,12 @@ public class ActionGraph extends Graph {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves all stack items to commands.
|
||||
* (If it's not a branch stack resistant or other special case)
|
||||
* @param commands Commands
|
||||
* @param stack Stack
|
||||
*/
|
||||
public void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
|
||||
GraphTargetItem enumerate = null;
|
||||
if (!commands.isEmpty() && (commands.get(commands.size() - 1) instanceof EnumerateActionItem)) {
|
||||
@@ -509,6 +556,14 @@ public class ActionGraph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the graph - decompiles.
|
||||
* @param localData Local data
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @return List of GraphTargetItems
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
public List<GraphTargetItem> translate(BaseLocalData localData, int staticOperation, String path) throws InterruptedException {
|
||||
List<GraphTargetItem> ret = super.translate(localData, staticOperation, path);
|
||||
@@ -536,6 +591,10 @@ public class ActionGraph extends Graph {
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
/**
|
||||
* Makes define registers up.
|
||||
* @param list List of GraphTargetItems
|
||||
*/
|
||||
private void makeDefineRegistersUp(List<GraphTargetItem> list) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
@@ -581,6 +640,12 @@ public class ActionGraph extends Graph {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds part.
|
||||
* @param ip IP
|
||||
* @param allParts All parts
|
||||
* @return GraphPart
|
||||
*/
|
||||
private GraphPart findPart(int ip, Set<GraphPart> allParts) {
|
||||
for (GraphPart p : allParts) {
|
||||
if (p.containsIP(ip)) {
|
||||
@@ -590,6 +655,30 @@ public class ActionGraph extends Graph {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check before decompiling next section.
|
||||
* @param currentRet Current return
|
||||
* @param foundGotos Found gotos
|
||||
* @param partCodes Part codes
|
||||
* @param partCodePos Part code position
|
||||
* @param visited Visited
|
||||
* @param code Code
|
||||
* @param localData Local data
|
||||
* @param allParts All parts
|
||||
* @param stack Stack
|
||||
* @param parent Parent part
|
||||
* @param part Part
|
||||
* @param stopPart Stop part
|
||||
* @param stopPartKind Stop part kind
|
||||
* @param loops Loops
|
||||
* @param throwStates Throw states
|
||||
* @param output Output
|
||||
* @param currentLoop Current loop
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @return List of GraphTargetItems to replace current output and stop further processing. Null to continue.
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Override
|
||||
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
|
||||
if (!output.isEmpty()) {
|
||||
@@ -695,6 +784,11 @@ public class ActionGraph extends Graph {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks IP and allows to modify it.
|
||||
* @param ip Current IP
|
||||
* @return New IP
|
||||
*/
|
||||
@Override
|
||||
protected int checkIp(int ip) {
|
||||
int oldIp = ip;
|
||||
@@ -723,6 +817,12 @@ public class ActionGraph extends Graph {
|
||||
return ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares second pass data.
|
||||
* Can return null when no second pass will happen.
|
||||
* @param list List of GraphTargetItems
|
||||
* @return Second pass data or null
|
||||
*/
|
||||
@Override
|
||||
public SecondPassData prepareSecondPass(List<GraphTargetItem> list) {
|
||||
ActionSecondPassData spd = new ActionSecondPassData();
|
||||
@@ -735,6 +835,14 @@ public class ActionGraph extends Graph {
|
||||
return spd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks second pass switches.
|
||||
* @param processedIfs Processed ifs
|
||||
* @param list List of GraphTargetItems
|
||||
* @param allSwitchParts All switch parts
|
||||
* @param allSwitchOnFalseParts All switch on false parts
|
||||
* @param allSwitchExpressions All switch expressions
|
||||
*/
|
||||
private void checkSecondPassSwitches(Set<GraphPart> processedIfs, List<GraphTargetItem> list, List<List<GraphPart>> allSwitchParts, List<List<GraphPart>> allSwitchOnFalseParts, List<List<GraphTargetItem>> allSwitchExpressions) {
|
||||
for (GraphTargetItem item : list) {
|
||||
if (item instanceof IfItem) {
|
||||
|
||||
@@ -18,15 +18,10 @@ package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphPartChangeException;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.*;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -35,31 +30,75 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* ActionScript 1/2 graph source
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionGraphSource extends GraphSource {
|
||||
|
||||
/**
|
||||
* Actions
|
||||
*/
|
||||
private final ActionList actions;
|
||||
|
||||
/**
|
||||
* SWF version
|
||||
*/
|
||||
public int version;
|
||||
|
||||
/**
|
||||
* Register names - map of register number to register name
|
||||
*/
|
||||
private final HashMap<Integer, String> registerNames;
|
||||
|
||||
/**
|
||||
* Variables - map of variable name to variable item
|
||||
*/
|
||||
private final HashMap<String, GraphTargetItem> variables;
|
||||
|
||||
/**
|
||||
* Functions - map of function name to function item
|
||||
*/
|
||||
private final HashMap<String, GraphTargetItem> functions;
|
||||
|
||||
/**
|
||||
* Is inside doInitAction
|
||||
*/
|
||||
private final boolean insideDoInitAction;
|
||||
|
||||
/**
|
||||
* Path
|
||||
*/
|
||||
private final String path;
|
||||
|
||||
/**
|
||||
* Charset - SWFs version 5 and lower do not use UTF-8 charset
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* Position cache
|
||||
*/
|
||||
private List<Long> posCache = null;
|
||||
|
||||
/**
|
||||
* Gets actions
|
||||
* @return Actions
|
||||
*/
|
||||
public List<Action> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new ActionGraphSource
|
||||
* @param path Path
|
||||
* @param insideDoInitAction Is inside doInitAction
|
||||
* @param actions Actions
|
||||
* @param version SWF version
|
||||
* @param registerNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param charset Charset
|
||||
*/
|
||||
public ActionGraphSource(String path, boolean insideDoInitAction, List<Action> actions, int version, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, String charset) {
|
||||
this.actions = actions instanceof ActionList ? (ActionList) actions : new ActionList(actions, charset);
|
||||
this.version = version;
|
||||
@@ -71,15 +110,28 @@ public class ActionGraphSource extends GraphSource {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets charset
|
||||
* @return Charset
|
||||
*/
|
||||
public String getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the important addresses
|
||||
* @return Set of important addresses
|
||||
*/
|
||||
@Override
|
||||
public Set<Long> getImportantAddresses() {
|
||||
return Action.getActionsAllRefs(actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts instruction at the specified position to string
|
||||
* @param pos Position of the instruction
|
||||
* @return Instruction as string
|
||||
*/
|
||||
@Override
|
||||
public String insToString(int pos) {
|
||||
if (pos < actions.size()) {
|
||||
@@ -88,25 +140,57 @@ public class ActionGraphSource extends GraphSource {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the graph source
|
||||
* @return The size of the graph source
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return actions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the graph source item at the specified position
|
||||
* @param pos Position of the graph source item
|
||||
* @return The graph source item at the specified position
|
||||
*/
|
||||
@Override
|
||||
public GraphSourceItem get(int pos) {
|
||||
return actions.get(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the graph source item at the specified position
|
||||
* @param pos Position of the graph source item
|
||||
* @param t The graph source item
|
||||
*/
|
||||
public void set(int pos, Action t) {
|
||||
actions.set(pos, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the graph source is empty
|
||||
* @return True if the graph source is empty, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return actions.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates the part of the graph source
|
||||
* @param graph Graph
|
||||
* @param part Graph part
|
||||
* @param localData Local data
|
||||
* @param stack Translate stack
|
||||
* @param start Start position
|
||||
* @param end End position
|
||||
* @param staticOperation Unused
|
||||
* @param path Path
|
||||
* @return List of graph target items
|
||||
* @throws InterruptedException
|
||||
* @throws GraphPartChangeException
|
||||
*/
|
||||
@Override
|
||||
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException {
|
||||
Reference<GraphSourceItem> fi = new Reference<>(localData.lineStartInstruction);
|
||||
@@ -116,8 +200,10 @@ public class ActionGraphSource extends GraphSource {
|
||||
return r;
|
||||
}
|
||||
|
||||
private List<Long> posCache = null;
|
||||
|
||||
/**
|
||||
* Rebuilds the position cache
|
||||
*/
|
||||
private void rebuildCache() {
|
||||
posCache = new ArrayList<>();
|
||||
for (int i = 0; i < size(); i++) {
|
||||
@@ -125,6 +211,11 @@ public class ActionGraphSource extends GraphSource {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts position to address
|
||||
* @param pos Position
|
||||
* @return Address
|
||||
*/
|
||||
@Override
|
||||
public long pos2adr(int pos) {
|
||||
GraphSourceItem si = actions.get(pos);
|
||||
@@ -134,6 +225,11 @@ public class ActionGraphSource extends GraphSource {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts address to position
|
||||
* @param adr Address
|
||||
* @return Position
|
||||
*/
|
||||
@Override
|
||||
public int adr2pos(long adr) {
|
||||
if (posCache == null) {
|
||||
@@ -154,6 +250,12 @@ public class ActionGraphSource extends GraphSource {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts address to position
|
||||
* @param adr Address
|
||||
* @param nearest Nearest
|
||||
* @return Position
|
||||
*/
|
||||
@Override
|
||||
public int adr2pos(long adr, boolean nearest) {
|
||||
if (posCache == null) {
|
||||
@@ -178,6 +280,10 @@ public class ActionGraphSource extends GraphSource {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets variables
|
||||
* @return Map of variable name to variable item
|
||||
*/
|
||||
public HashMap<String, GraphTargetItem> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.helpers.CodeFormatting;
|
||||
import com.jpexs.decompiler.flash.helpers.FileTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -41,43 +42,82 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* List of actions.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionList extends ArrayList<Action> {
|
||||
|
||||
/**
|
||||
* Deobfuscation mode
|
||||
*/
|
||||
public int deobfuscationMode;
|
||||
|
||||
/**
|
||||
* File data
|
||||
*/
|
||||
public byte[] fileData;
|
||||
|
||||
/**
|
||||
* Charset - SWF version 5 or lower does not have UTF-8 charset
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* Constructs a new action list with the specified charset.
|
||||
* @param charset Charset
|
||||
*/
|
||||
public ActionList(String charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the charset.
|
||||
* @return Charset
|
||||
*/
|
||||
public String getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new action list with the specified actions and charset.
|
||||
* @param actions Actions
|
||||
* @param charset Charset
|
||||
*/
|
||||
public ActionList(Collection<Action> actions, String charset) {
|
||||
super(actions);
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets actions.
|
||||
* @param list Actions
|
||||
*/
|
||||
public void setActions(List<Action> list) {
|
||||
clear();
|
||||
addAll(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes actions.
|
||||
* @param actionsToRemove Actions to remove
|
||||
*/
|
||||
public void removeActions(List<Action> actionsToRemove) {
|
||||
ActionListReader.removeActions(this, actionsToRemove, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes action.
|
||||
* @param index Index
|
||||
*/
|
||||
public void removeAction(int index) {
|
||||
ActionListReader.removeAction(this, index, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes action.
|
||||
* @param index Index
|
||||
* @param count Count
|
||||
*/
|
||||
public void removeAction(int index, int count) {
|
||||
if (size() <= index + count - 1) {
|
||||
// Can't remove count elements, only size - index is available
|
||||
@@ -89,22 +129,45 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds action.
|
||||
* @param index Index
|
||||
* @param action Action
|
||||
*/
|
||||
public void addAction(int index, Action action) {
|
||||
ActionListReader.addAction(this, index, action, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds actions.
|
||||
* @param index Index
|
||||
* @param actions Actions
|
||||
*/
|
||||
public void addActions(int index, List<Action> actions) {
|
||||
ActionListReader.addActions(this, index, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes action list.
|
||||
*/
|
||||
public void fixActionList() {
|
||||
ActionListReader.fixActionList(this, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets container last actions.
|
||||
* @param action Action
|
||||
* @return Container last actions
|
||||
*/
|
||||
public List<Action> getContainerLastActions(Action action) {
|
||||
return ActionListReader.getContainerLastActions(this, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets references for action.
|
||||
* @param target Target
|
||||
* @return References
|
||||
*/
|
||||
public Iterator<Action> getReferencesFor(final Action target) {
|
||||
return new Iterator<Action>() {
|
||||
private final Iterator<Action> iterator = ActionList.this.iterator();
|
||||
@@ -167,6 +230,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant pools.
|
||||
* @return Constant pools
|
||||
*/
|
||||
public Iterable<ActionConstantPool> getConstantPools() {
|
||||
return () -> new Iterator<ActionConstantPool>() {
|
||||
private final Iterator<Action> iterator = ActionList.this.iterator();
|
||||
@@ -203,6 +270,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets pushes.
|
||||
* @return Pushes
|
||||
*/
|
||||
public Iterable<ActionPush> getPushes() {
|
||||
return () -> new Iterator<ActionPush>() {
|
||||
private final Iterator<Action> iterator = ActionList.this.iterator();
|
||||
@@ -239,6 +310,11 @@ public class ActionList extends ArrayList<Action> {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets constant pool index reference count.
|
||||
* @param index Index
|
||||
* @return Constant pool index reference count
|
||||
*/
|
||||
public int getConstantPoolIndexReferenceCount(int index) {
|
||||
int count = 0;
|
||||
for (Action action : this) {
|
||||
@@ -258,6 +334,11 @@ public class ActionList extends ArrayList<Action> {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets inline constant pool string.
|
||||
* @param index Index
|
||||
* @param str String
|
||||
*/
|
||||
public void inlineConstantPoolString(int index, String str) {
|
||||
for (ActionPush push : getPushes()) {
|
||||
for (int i = 0; i < push.values.size(); i++) {
|
||||
@@ -272,6 +353,9 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes non-referenced constant pool items.
|
||||
*/
|
||||
public void removeNonReferencedConstantPoolItems() {
|
||||
int maxSize = 0;
|
||||
for (ActionConstantPool constantPool : getConstantPools()) {
|
||||
@@ -321,6 +405,9 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes nops.
|
||||
*/
|
||||
public void removeNops() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
if (get(i) instanceof ActionNop) {
|
||||
@@ -329,15 +416,30 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets action by address.
|
||||
* @param address Address
|
||||
* @return Action
|
||||
*/
|
||||
public Action getByAddress(long address) {
|
||||
int idx = getIndexByAddress(address);
|
||||
return idx == -1 ? null : get(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets index by action.
|
||||
* @param action Action
|
||||
* @return Index
|
||||
*/
|
||||
public int getIndexByAction(Action action) {
|
||||
return getIndexByAddress(action.getAddress());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets index by address.
|
||||
* @param address Address
|
||||
* @return Index
|
||||
*/
|
||||
public int getIndexByAddress(long address) {
|
||||
int min = 0;
|
||||
int max = size() - 1;
|
||||
@@ -357,6 +459,11 @@ public class ActionList extends ArrayList<Action> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets container.
|
||||
* @param idx Index
|
||||
* @return Container
|
||||
*/
|
||||
public GraphSourceItemContainer getContainer(int idx) {
|
||||
Action action = get(idx);
|
||||
int i = idx - 1;
|
||||
@@ -376,6 +483,11 @@ public class ActionList extends ArrayList<Action> {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets container end index.
|
||||
* @param idx Index
|
||||
* @return Container end index
|
||||
*/
|
||||
public int getContainerEndIndex(int idx) {
|
||||
Action action = get(idx);
|
||||
int i = idx - 1;
|
||||
@@ -395,6 +507,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets unreachable actions.
|
||||
* @return Unreachable actions
|
||||
*/
|
||||
public List<Action> getUnreachableActions() {
|
||||
int[] isReachable = getUnreachableActionsMap(-1, 0);
|
||||
List<Action> unreachableActions = new ArrayList<>();
|
||||
@@ -411,6 +527,12 @@ public class ActionList extends ArrayList<Action> {
|
||||
return unreachableActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets unreachable actions.
|
||||
* @param jumpIndex Jump index
|
||||
* @param jumpTargetIndex Jump target index
|
||||
* @return Unreachable actions
|
||||
*/
|
||||
public List<Action> getUnreachableActions(int jumpIndex, int jumpTargetIndex) {
|
||||
int[] isReachable = getUnreachableActionsMap(jumpIndex, jumpTargetIndex);
|
||||
isReachable[jumpIndex] = 0;
|
||||
@@ -428,6 +550,12 @@ public class ActionList extends ArrayList<Action> {
|
||||
return unreachableActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets unreachable actions map.
|
||||
* @param jumpIndex Jump index
|
||||
* @param jumpTargetIndex Jump target index
|
||||
* @return Unreachable actions array - ip to reachable
|
||||
*/
|
||||
private int[] getUnreachableActionsMap(int jumpIndex, int jumpTargetIndex) {
|
||||
int size = size();
|
||||
|
||||
@@ -498,6 +626,9 @@ public class ActionList extends ArrayList<Action> {
|
||||
return isReachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines pushes.
|
||||
*/
|
||||
public void combinePushes() {
|
||||
for (int i = 0; i < size() - 1; i++) {
|
||||
Action action = get(i);
|
||||
@@ -522,6 +653,9 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands pushes.
|
||||
*/
|
||||
public void expandPushes() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
Action action = get(i);
|
||||
@@ -543,6 +677,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves to file.
|
||||
* @param fileName File name
|
||||
*/
|
||||
public void saveToFile(String fileName) {
|
||||
File file = new File(fileName);
|
||||
try (FileTextWriter writer = new FileTextWriter(Configuration.getCodeFormatting(), new FileOutputStream(file))) {
|
||||
@@ -552,6 +690,10 @@ public class ActionList extends ArrayList<Action> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts to string.
|
||||
* @return String
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false);
|
||||
@@ -559,15 +701,4 @@ public class ActionList extends ArrayList<Action> {
|
||||
writer.finishHilights();
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
/*public String toSource() {
|
||||
try {
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false);
|
||||
actionsToSource(null, this, "", writer, charset);
|
||||
return writer.toString();
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(ActionList.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
return null;
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -33,14 +33,9 @@ import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.stat.Statistics;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -49,25 +44,28 @@ import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Class for reading data from SWF file
|
||||
* Class for reading Action data from SWF file.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionListReader {
|
||||
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(ActionListReader.class.getName());
|
||||
|
||||
/**
|
||||
* Reads list of actions from the stream. Reading ends with
|
||||
* ActionEndFlag(=0) or end of the stream.
|
||||
*
|
||||
* @param listeners
|
||||
* @param sis
|
||||
* @param version
|
||||
* @param ip
|
||||
* @param endIp
|
||||
* @param path
|
||||
* @param deobfuscationMode
|
||||
* @param listeners List of listeners
|
||||
* @param sis SWF input stream
|
||||
* @param version SWF version
|
||||
* @param ip Start IP
|
||||
* @param endIp End IP
|
||||
* @param path Path
|
||||
* @param deobfuscationMode Deobfuscation mode
|
||||
* @return List of actions
|
||||
* @throws IOException
|
||||
* @throws java.lang.InterruptedException
|
||||
@@ -101,13 +99,13 @@ public class ActionListReader {
|
||||
* Reads list of actions from the stream. Reading ends with
|
||||
* ActionEndFlag(=0) or end of the stream.
|
||||
*
|
||||
* @param listeners
|
||||
* @param sis
|
||||
* @param version
|
||||
* @param ip
|
||||
* @param endIp
|
||||
* @param path
|
||||
* @param deobfuscationMode
|
||||
* @param listeners List of listeners
|
||||
* @param sis SWF input stream
|
||||
* @param version SWF version
|
||||
* @param ip Start IP
|
||||
* @param endIp End IP
|
||||
* @param path Path
|
||||
* @param deobfuscationMode Deobfuscation mode
|
||||
* @return List of actions
|
||||
* @throws IOException
|
||||
* @throws java.lang.InterruptedException
|
||||
@@ -183,6 +181,12 @@ public class ActionListReader {
|
||||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes action list.
|
||||
* @param actions Action list
|
||||
* @param nextOffsets Next offsets
|
||||
* @return Fixed action list
|
||||
*/
|
||||
public static ActionList fixActionList(ActionList actions, Map<Long, Long> nextOffsets) {
|
||||
Map<Action, List<Action>> containerLastActions = new HashMap<>();
|
||||
getContainerLastActions(actions, containerLastActions);
|
||||
@@ -229,6 +233,15 @@ public class ActionListReader {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets original actions.
|
||||
* @param sis SWF input stream
|
||||
* @param startIp Start IP
|
||||
* @param endIp End IP
|
||||
* @return List of actions
|
||||
* @throws IOException
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public static List<Action> getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException {
|
||||
// Map of the actions. Use TreeMap to sort the keys in ascending order
|
||||
Map<Long, Action> actionMap = new TreeMap<>();
|
||||
@@ -241,6 +254,13 @@ public class ActionListReader {
|
||||
return new ArrayList<>(actionMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets near address.
|
||||
* @param actions Action list
|
||||
* @param address Address
|
||||
* @param next Next
|
||||
* @return Near address
|
||||
*/
|
||||
private static long getNearAddress(ActionList actions, long address, boolean next) {
|
||||
int min = 0;
|
||||
int max = actions.size() - 1;
|
||||
@@ -262,6 +282,11 @@ public class ActionListReader {
|
||||
: (max >= 0 ? actions.get(max).getAddress() : -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts list of actions to map of address to action.
|
||||
* @param actions List of actions
|
||||
* @return Map of address to action
|
||||
*/
|
||||
private static Map<Long, Action> actionListToMap(List<Action> actions) {
|
||||
Map<Long, Action> map = new HashMap<>(actions.size());
|
||||
for (Action a : actions) {
|
||||
@@ -275,6 +300,11 @@ public class ActionListReader {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets jumps.
|
||||
* @param actions List of actions
|
||||
* @param jumps Jumps - map of jumpAction to targetAction
|
||||
*/
|
||||
private static void getJumps(List<Action> actions, Map<Action, Action> jumps) {
|
||||
Map<Long, Action> actionMap = actionListToMap(actions);
|
||||
for (Action a : actions) {
|
||||
@@ -304,6 +334,12 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets container last actions.
|
||||
* @param actions List of actions
|
||||
* @param action Action
|
||||
* @return List of last actions
|
||||
*/
|
||||
public static List<Action> getContainerLastActions(ActionList actions, Action action) {
|
||||
GraphSourceItemContainer container = (GraphSourceItemContainer) action;
|
||||
List<Long> sizes = container.getContainerSizes();
|
||||
@@ -321,6 +357,11 @@ public class ActionListReader {
|
||||
return lasts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets container last actions.
|
||||
* @param actions List of actions
|
||||
* @param lastActions Last actions
|
||||
*/
|
||||
private static void getContainerLastActions(ActionList actions, Map<Action, List<Action>> lastActions) {
|
||||
for (Action a : actions) {
|
||||
if (a instanceof GraphSourceItemContainer) {
|
||||
@@ -329,6 +370,13 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates addresses.
|
||||
* @param actions List of actions
|
||||
* @param address Address
|
||||
* @param charset Charset
|
||||
* @return End address
|
||||
*/
|
||||
private static long updateAddresses(List<Action> actions, long address, String charset) {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action a = actions.get(i);
|
||||
@@ -343,12 +391,21 @@ public class ActionListReader {
|
||||
return address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates action lengths.
|
||||
* @param actions List of actions
|
||||
*/
|
||||
private static void updateActionLengths(List<Action> actions) {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
actions.get(i).updateLength();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates action stores.
|
||||
* @param actions List of actions
|
||||
* @param jumps Jumps - map of jumpAction to targetAction
|
||||
*/
|
||||
private static void updateActionStores(List<Action> actions, Map<Action, Action> jumps) {
|
||||
Map<Long, Action> actionMap = actionListToMap(actions);
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
@@ -371,6 +428,11 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates container sizes.
|
||||
* @param actions List of actions
|
||||
* @param containerLastActions Container last actions
|
||||
*/
|
||||
private static void updateContainerSizes(List<Action> actions, Map<Action, List<Action>> containerLastActions) {
|
||||
for (int i = 0; i < actions.size(); i++) {
|
||||
Action a = actions.get(i);
|
||||
@@ -388,6 +450,12 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces jump targets.
|
||||
* @param jumps Jumps - map of jumpAction to targetAction
|
||||
* @param oldTarget Old target
|
||||
* @param newTarget New target
|
||||
*/
|
||||
private static void replaceJumpTargets(Map<Action, Action> jumps, Action oldTarget, Action newTarget) {
|
||||
for (Action a : jumps.keySet()) {
|
||||
if (jumps.get(a) == oldTarget) {
|
||||
@@ -396,6 +464,12 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces container last actions.
|
||||
* @param containerLastActions Container last actions
|
||||
* @param oldTarget Old target
|
||||
* @param newTarget New target
|
||||
*/
|
||||
private static void replaceContainerLastActions(Map<Action, List<Action>> containerLastActions, Action oldTarget, Action newTarget) {
|
||||
for (Action a : containerLastActions.keySet()) {
|
||||
List<Action> targets = containerLastActions.get(a);
|
||||
@@ -407,6 +481,14 @@ public class ActionListReader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates jumps.
|
||||
* @param actions List of actions
|
||||
* @param jumps Jumps - map of jumpAction to targetAction
|
||||
* @param containerLastActions Container last actions
|
||||
* @param endAddress End address
|
||||
* @param charset Charset
|
||||
*/
|
||||
private static void updateJumps(List<Action> actions, Map<Action, Action> jumps, Map<Action, List<Action>> containerLastActions, long endAddress, String charset) {
|
||||
if (actions.isEmpty()) {
|
||||
return;
|
||||
@@ -449,12 +531,12 @@ public class ActionListReader {
|
||||
/**
|
||||
* Removes an action from the action list, and updates all references This
|
||||
* method will keep the inner actions of the container when you remove the
|
||||
* container
|
||||
* container.
|
||||
*
|
||||
* @param actions
|
||||
* @param index
|
||||
* @param removeWhenLast
|
||||
* @return
|
||||
* @param actions List of actions
|
||||
* @param index Index
|
||||
* @param removeWhenLast Remove when last
|
||||
* @return True if action was removed, false otherwise
|
||||
*/
|
||||
public static boolean removeAction(ActionList actions, int index, boolean removeWhenLast) {
|
||||
|
||||
@@ -513,12 +595,12 @@ public class ActionListReader {
|
||||
/**
|
||||
* Removes multiple actions from the action list, and updates all references
|
||||
* This method will keep the inner actions of the container when you remove
|
||||
* the container
|
||||
* the container.
|
||||
*
|
||||
* @param actions
|
||||
* @param actionsToRemove
|
||||
* @param removeWhenLast
|
||||
* @return
|
||||
* @param actions List of actions
|
||||
* @param actionsToRemove Actions to remove
|
||||
* @param removeWhenLast Remove when last
|
||||
* @return True if actions were removed, false otherwise
|
||||
*/
|
||||
public static boolean removeActions(ActionList actions, List<Action> actionsToRemove, boolean removeWhenLast) {
|
||||
|
||||
@@ -575,14 +657,14 @@ public class ActionListReader {
|
||||
|
||||
/**
|
||||
* Adds an action to the action list to the specified location, and updates
|
||||
* all references
|
||||
* all references.
|
||||
*
|
||||
* @param actions
|
||||
* @param index
|
||||
* @param action
|
||||
* @param addToContainer
|
||||
* @param replaceJump
|
||||
* @return
|
||||
* @param actions List of actions
|
||||
* @param index Index
|
||||
* @param action Action
|
||||
* @param addToContainer Add to container
|
||||
* @param replaceJump Replace jump
|
||||
* @return True if action was added, false otherwise
|
||||
*/
|
||||
public static boolean addAction(ActionList actions, int index, Action action,
|
||||
boolean addToContainer, boolean replaceJump) {
|
||||
@@ -644,12 +726,12 @@ public class ActionListReader {
|
||||
|
||||
/**
|
||||
* Adds an action to the action list to the specified location, and updates
|
||||
* all references
|
||||
* all references.
|
||||
*
|
||||
* @param actions
|
||||
* @param index
|
||||
* @param newActions
|
||||
* @return
|
||||
* @param actions List of actions
|
||||
* @param index Index
|
||||
* @param newActions New actions
|
||||
* @return True if actions were added, false otherwise
|
||||
*/
|
||||
public static boolean addActions(ActionList actions, int index, List<Action> newActions) {
|
||||
|
||||
@@ -687,6 +769,23 @@ public class ActionListReader {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads action list at the specified position.
|
||||
* @param listeners List of listeners
|
||||
* @param cpool Constant pool
|
||||
* @param sis SWF input stream
|
||||
* @param actions Actions
|
||||
* @param nextOffsets Next offsets
|
||||
* @param ip IP
|
||||
* @param startIp Start IP
|
||||
* @param endIp End IP
|
||||
* @param path Path
|
||||
* @param indeterminate Indeterminate
|
||||
* @param visitedContainers Visited containers
|
||||
* @param charset Charset
|
||||
* @return Action
|
||||
* @throws IOException
|
||||
*/
|
||||
private static Action readActionListAtPos(List<DisassemblyListener> listeners, ConstantPool cpool,
|
||||
SWFInputStream sis, Map<Long, Action> actions, Map<Long, Long> nextOffsets,
|
||||
long ip, long startIp, long endIp, String path, boolean indeterminate, List<Long> visitedContainers, String charset) throws IOException {
|
||||
@@ -792,6 +891,12 @@ public class ActionListReader {
|
||||
return entryAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes constant pools.
|
||||
* @param listeners List of listeners
|
||||
* @param actions Actions
|
||||
* @return True if constant pools were fixed, false otherwise
|
||||
*/
|
||||
public static boolean fixConstantPools(List<DisassemblyListener> listeners, ActionList actions) {
|
||||
Action lastAction = actions.get(actions.size() - 1);
|
||||
int endIp = (int) lastAction.getAddress();
|
||||
@@ -813,6 +918,21 @@ public class ActionListReader {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes constant pools.
|
||||
* @param listeners List of listeners
|
||||
* @param cpool Constant pool
|
||||
* @param actions Actions
|
||||
* @param actionMap Action map
|
||||
* @param ip IP
|
||||
* @param startIp Start IP
|
||||
* @param endIp End IP
|
||||
* @param path Path
|
||||
* @param indeterminate Indeterminate
|
||||
* @param visitedContainers Visited containers
|
||||
* @return True if constant pools were fixed, false otherwise
|
||||
* @throws IOException
|
||||
*/
|
||||
private static boolean fixConstantPools(List<DisassemblyListener> listeners, ConstantPool cpool,
|
||||
List<Action> actions, Map<Integer, Action> actionMap,
|
||||
int ip, int startIp, int endIp, String path, boolean indeterminate, List<Integer> visitedContainers) throws IOException {
|
||||
|
||||
@@ -22,28 +22,53 @@ import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* Local data for ActionScript decompilation.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionLocalData extends BaseLocalData {
|
||||
|
||||
/**
|
||||
* Uninitialized class traits - map of class name to map of trait name to trait
|
||||
*/
|
||||
public final Map<String, Map<String, Trait>> uninitializedClassTraits;
|
||||
|
||||
/**
|
||||
* Register names - map of register number to register name
|
||||
*/
|
||||
public final HashMap<Integer, String> regNames;
|
||||
|
||||
/**
|
||||
* Variables - map of variable name to variable target item
|
||||
*/
|
||||
public final HashMap<String, GraphTargetItem> variables;
|
||||
|
||||
/**
|
||||
* Functions - map of function name to function target item
|
||||
*/
|
||||
public final HashMap<String, GraphTargetItem> functions;
|
||||
|
||||
/**
|
||||
* Line start action
|
||||
*/
|
||||
public GraphSourceItem lineStartAction;
|
||||
|
||||
/**
|
||||
* Is inside doInitAction
|
||||
*/
|
||||
public boolean insideDoInitAction;
|
||||
|
||||
/**
|
||||
* Constructs new ActionLocalData
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Is inside doInitAction
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
*/
|
||||
public ActionLocalData(SecondPassData secondPassData, boolean insideDoInitAction, Map<String, Map<String, Trait>> uninitializedClassTraits) {
|
||||
this.secondPassData = secondPassData;
|
||||
regNames = new HashMap<>();
|
||||
@@ -53,6 +78,13 @@ public class ActionLocalData extends BaseLocalData {
|
||||
this.uninitializedClassTraits = uninitializedClassTraits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new ActionLocalData
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Is inside doInitAction
|
||||
* @param regNames Register names
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
*/
|
||||
public ActionLocalData(SecondPassData secondPassData, boolean insideDoInitAction, HashMap<Integer, String> regNames, Map<String, Map<String, Trait>> uninitializedClassTraits) {
|
||||
this.regNames = regNames;
|
||||
this.secondPassData = secondPassData;
|
||||
@@ -62,6 +94,16 @@ public class ActionLocalData extends BaseLocalData {
|
||||
this.uninitializedClassTraits = uninitializedClassTraits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs new ActionLocalData
|
||||
* @param switchParts Switch parts
|
||||
* @param secondPassData Second pass data
|
||||
* @param insideDoInitAction Is inside doInitAction
|
||||
* @param regNames Register names
|
||||
* @param variables Variables
|
||||
* @param functions Functions
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
*/
|
||||
public ActionLocalData(Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, Map<String, Map<String, Trait>> uninitializedClassTraits) {
|
||||
this.allSwitchParts = switchParts;
|
||||
this.regNames = regNames;
|
||||
|
||||
@@ -17,18 +17,27 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents ActionScript array.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionScriptArray extends ActionScriptObject {
|
||||
|
||||
/**
|
||||
* Array values
|
||||
*/
|
||||
protected List<Object> values = new ArrayList<>();
|
||||
|
||||
//TODO: implement some methods?
|
||||
|
||||
/**
|
||||
* Enumerates all members of this object
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<String> enumerate() {
|
||||
List<String> ret = super.enumerate();
|
||||
@@ -38,6 +47,11 @@ public class ActionScriptArray extends ActionScriptObject {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets member of this object
|
||||
* @param path Member path
|
||||
* @return Member value
|
||||
*/
|
||||
@Override
|
||||
public Object getMember(String path) {
|
||||
if (path.matches("[1-9][0-9]*|0")) {
|
||||
@@ -46,6 +60,11 @@ public class ActionScriptArray extends ActionScriptObject {
|
||||
return super.getMember(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets member of this object
|
||||
* @param path Member path
|
||||
* @param value Value to set
|
||||
*/
|
||||
@Override
|
||||
public void setMember(String path, Object value) {
|
||||
if (path.matches("[1-9][0-9]*|0")) {
|
||||
@@ -55,6 +74,11 @@ public class ActionScriptArray extends ActionScriptObject {
|
||||
super.setMember(path, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets value at index
|
||||
* @param index Index
|
||||
* @param value Value
|
||||
*/
|
||||
public void setValueAtIndex(int index, Object value) {
|
||||
if (index < 0) {
|
||||
return;
|
||||
@@ -71,6 +95,9 @@ public class ActionScriptArray extends ActionScriptObject {
|
||||
trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims array by removing trailing undefined values
|
||||
*/
|
||||
public void trim() {
|
||||
for (int i = values.size() - 1; i >= 0; i--) {
|
||||
if (values.get(i) == Undefined.INSTANCE) {
|
||||
@@ -81,6 +108,11 @@ public class ActionScriptArray extends ActionScriptObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets value at index
|
||||
* @param index Index
|
||||
* @return Value
|
||||
*/
|
||||
public Object getValueAtIndex(int index) {
|
||||
if (index < 0) {
|
||||
return Undefined.INSTANCE; //throw error?
|
||||
|
||||
@@ -20,29 +20,60 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents an ActionScript function.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionScriptFunction extends ActionScriptObject {
|
||||
|
||||
/**
|
||||
* Offset of the function
|
||||
*/
|
||||
protected long functionOffset;
|
||||
|
||||
/**
|
||||
* Length of the function
|
||||
*/
|
||||
protected long functionLength;
|
||||
|
||||
/**
|
||||
* Name of the function
|
||||
*/
|
||||
protected String functionName;
|
||||
|
||||
/**
|
||||
* Names of the parameters
|
||||
*/
|
||||
protected List<String> paramNames;
|
||||
|
||||
/**
|
||||
* Names of the registers - map of register index to register name
|
||||
*/
|
||||
protected Map<Integer, String> funcRegNames;
|
||||
|
||||
/**
|
||||
* Gets function name
|
||||
* @return Function name
|
||||
*/
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets register names
|
||||
* @return Register names
|
||||
*/
|
||||
public Map<Integer, String> getFuncRegNames() {
|
||||
return funcRegNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constucts a new ActionScriptFunction
|
||||
* @param functionOffset Offset of the function
|
||||
* @param functionLength Length of the function
|
||||
* @param functionName Name of the function
|
||||
* @param paramNames Names of the parameters
|
||||
* @param funcRegNames Names of the registers
|
||||
*/
|
||||
public ActionScriptFunction(long functionOffset, long functionLength, String functionName, List<String> paramNames, Map<Integer, String> funcRegNames) {
|
||||
this.functionOffset = functionOffset;
|
||||
this.functionLength = functionLength;
|
||||
@@ -51,10 +82,18 @@ public class ActionScriptFunction extends ActionScriptObject {
|
||||
this.funcRegNames = funcRegNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets function length
|
||||
* @return Function length
|
||||
*/
|
||||
public long getFunctionLength() {
|
||||
return functionLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets function offset
|
||||
* @return Function offset
|
||||
*/
|
||||
public long getFunctionOffset() {
|
||||
return functionOffset;
|
||||
}
|
||||
|
||||
@@ -17,25 +17,41 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents an ActionScript object.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionScriptObject implements Cloneable {
|
||||
|
||||
/**
|
||||
* Properties of the object
|
||||
*/
|
||||
protected Map<Integer, Object> properties = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Members of the object
|
||||
*/
|
||||
protected Map<String, Object> members = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Object that this object extends
|
||||
*/
|
||||
protected Object extendsObj;
|
||||
|
||||
/**
|
||||
* Objects that this object implements
|
||||
*/
|
||||
protected List<Object> implementsObjs = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Clears all members of the object
|
||||
*/
|
||||
public void clearMembers() {
|
||||
for (Object o : members.values()) {
|
||||
if (o instanceof ActionScriptObject) {
|
||||
@@ -45,31 +61,57 @@ public class ActionScriptObject implements Cloneable {
|
||||
members.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all properties of the object
|
||||
*/
|
||||
public void clearProperties() {
|
||||
properties.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all members and properties of the object
|
||||
*/
|
||||
public void clear() {
|
||||
clearMembers();
|
||||
clearProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets implements objects
|
||||
* @return Implements objects
|
||||
*/
|
||||
public List<Object> getImplementsObjs() {
|
||||
return implementsObjs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets implements objects
|
||||
* @param implementsObjs Implements objects
|
||||
*/
|
||||
public void setImplementsObjs(List<Object> implementsObjs) {
|
||||
this.implementsObjs = implementsObjs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets extends object
|
||||
* @param extendsObj Extends object
|
||||
*/
|
||||
public void setExtendsObj(Object extendsObj) {
|
||||
this.extendsObj = extendsObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets extends object
|
||||
* @return Extends object
|
||||
*/
|
||||
public Object getExtendsObj() {
|
||||
return extendsObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a member from the object
|
||||
* @param path Path to the member
|
||||
*/
|
||||
public void removeMember(String path) {
|
||||
String[] pathParts;
|
||||
if (path.startsWith("/")) {
|
||||
@@ -91,14 +133,28 @@ public class ActionScriptObject implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates all members of the object
|
||||
* @return List of member names
|
||||
*/
|
||||
public List<String> enumerate() {
|
||||
return new ArrayList<>(members.keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a property of the object
|
||||
* @param index Index of the property
|
||||
* @param value Value of the property
|
||||
*/
|
||||
public void setProperty(int index, Object value) {
|
||||
properties.put(index, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a property of the object
|
||||
* @param index Index of the property
|
||||
* @return Value of the property
|
||||
*/
|
||||
public Object getProperty(int index) {
|
||||
if (!properties.containsKey(index)) {
|
||||
return Undefined.INSTANCE;
|
||||
@@ -106,6 +162,11 @@ public class ActionScriptObject implements Cloneable {
|
||||
return properties.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a member of the object
|
||||
* @param path Path to the member
|
||||
* @param value Value of the member
|
||||
*/
|
||||
public void setMember(String path, Object value) {
|
||||
String[] pathParts;
|
||||
if (path.startsWith("/")) {
|
||||
@@ -127,6 +188,10 @@ public class ActionScriptObject implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the object
|
||||
* @return Cloned object
|
||||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
@@ -137,6 +202,11 @@ public class ActionScriptObject implements Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets path to a member
|
||||
* @param obj Member
|
||||
* @return Path to the member
|
||||
*/
|
||||
public String getMemberPath(Object obj) {
|
||||
if (obj == this) {
|
||||
return "";
|
||||
@@ -157,10 +227,20 @@ public class ActionScriptObject implements Cloneable {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member of the object
|
||||
* @param name Name of the member
|
||||
* @return Member
|
||||
*/
|
||||
protected Object getThisMember(String name) {
|
||||
return members.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member of the object
|
||||
* @param path Path to the member
|
||||
* @return Member
|
||||
*/
|
||||
public Object getMember(String path) {
|
||||
String[] pathParts;
|
||||
if (path.startsWith("/")) {
|
||||
|
||||
@@ -17,17 +17,32 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a with block in ActionScript.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionScriptWith {
|
||||
|
||||
/**
|
||||
* Object that is used in the with block.
|
||||
*/
|
||||
protected ActionScriptObject obj;
|
||||
|
||||
/**
|
||||
* Start address of the with block.
|
||||
*/
|
||||
protected long startAddr;
|
||||
|
||||
/**
|
||||
* Length of the with block.
|
||||
*/
|
||||
protected long length;
|
||||
|
||||
/**
|
||||
* Constructs a new ActionScriptWith object.
|
||||
* @param obj Object that is used in the with block.
|
||||
* @param startAddr Start address of the with block.
|
||||
* @param length Length of the with block.
|
||||
*/
|
||||
public ActionScriptWith(ActionScriptObject obj, long startAddr, long length) {
|
||||
this.obj = obj;
|
||||
this.startAddr = startAddr;
|
||||
|
||||
@@ -19,16 +19,26 @@ package com.jpexs.decompiler.flash.action;
|
||||
import com.jpexs.decompiler.graph.GraphPart;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.SecondPassData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Second pass data for ActionScript 1/2 decompiler.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionSecondPassData extends SecondPassData {
|
||||
|
||||
/**
|
||||
* List of parts for each switch statement
|
||||
*/
|
||||
List<List<GraphPart>> switchParts = new ArrayList<>();
|
||||
/**
|
||||
* List of onFalse parts for each switch statement
|
||||
*/
|
||||
List<List<GraphPart>> switchOnFalseParts = new ArrayList<>();
|
||||
/**
|
||||
* List of case expressions for each switch statement
|
||||
*/
|
||||
List<List<GraphTargetItem>> switchCaseExpressions = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -17,13 +17,18 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Operation on action tree.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface ActionTreeOperation {
|
||||
|
||||
/**
|
||||
* Run operation on action tree.
|
||||
* @param tree Action tree
|
||||
*/
|
||||
public void run(List<GraphTargetItem> tree);
|
||||
}
|
||||
|
||||
+12
-1
@@ -17,15 +17,26 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
/**
|
||||
*
|
||||
* Constant pool too big exception.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ConstantPoolTooBigException extends Exception {
|
||||
|
||||
/**
|
||||
* Index of new item
|
||||
*/
|
||||
public int index;
|
||||
|
||||
/**
|
||||
* Size of constant pool
|
||||
*/
|
||||
public int size;
|
||||
|
||||
/**
|
||||
* Constructs a new ConstantPoolTooBigException with the specified index and size.
|
||||
* @param index Index of new item
|
||||
* @param size Size of constant pool
|
||||
*/
|
||||
public ConstantPoolTooBigException(int index, int size) {
|
||||
super("Constant pool too big. index=" + index + ", size=" + size);
|
||||
this.index = index;
|
||||
|
||||
@@ -19,13 +19,20 @@ package com.jpexs.decompiler.flash.action;
|
||||
import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
|
||||
/**
|
||||
*
|
||||
* Adapter for DepthState object.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DepthStateObjectAdapter extends ActionScriptObject {
|
||||
|
||||
/**
|
||||
* DepthState object
|
||||
*/
|
||||
protected DepthState ds;
|
||||
|
||||
/**
|
||||
* Constructs a new DepthStateObjectAdapter with the given DepthState object.
|
||||
* @param ds DepthState object
|
||||
*/
|
||||
public DepthStateObjectAdapter(DepthState ds) {
|
||||
this.ds = ds;
|
||||
}
|
||||
|
||||
@@ -17,46 +17,84 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* Display object class.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class DisplayObject extends ActionScriptObject {
|
||||
|
||||
/**
|
||||
* Display list.
|
||||
*/
|
||||
protected Map<Integer, Object> displayList = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Total frames.
|
||||
*/
|
||||
protected int totalFrames = 1;
|
||||
|
||||
/**
|
||||
* Current frame.
|
||||
*/
|
||||
protected int currentFrame = 1;
|
||||
|
||||
/**
|
||||
* Paused.
|
||||
*/
|
||||
protected boolean paused = false;
|
||||
|
||||
/**
|
||||
* Dragging.
|
||||
*/
|
||||
protected boolean dragging = false;
|
||||
|
||||
/**
|
||||
* Starts drag.
|
||||
*/
|
||||
public void startDrag() {
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops drag.
|
||||
*/
|
||||
public void stopDrag() {
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current frame.
|
||||
* @return Current frame.
|
||||
*/
|
||||
public int getCurrentFrame() {
|
||||
return currentFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets total frames.
|
||||
* @return Total frames.
|
||||
*/
|
||||
public int getTotalFrames() {
|
||||
return totalFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes to frame.
|
||||
* @param label Label.
|
||||
*/
|
||||
public void gotoLabel(String label) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Goes to frame.
|
||||
* @param frame Frame.
|
||||
*/
|
||||
public void gotoFrame(int frame) {
|
||||
if (frame < 1) {
|
||||
frame = 1;
|
||||
@@ -67,31 +105,65 @@ public class DisplayObject extends ActionScriptObject {
|
||||
this.currentFrame = frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses.
|
||||
*/
|
||||
public void pause() {
|
||||
paused = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays.
|
||||
*/
|
||||
public void play() {
|
||||
paused = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls function.
|
||||
* @param functionAddress Function address.
|
||||
* @param functionLength Function length.
|
||||
* @param args Arguments.
|
||||
* @param regNames Register names.
|
||||
* @param thisObj This object.
|
||||
* @return Result.
|
||||
*/
|
||||
public Object callFunction(long functionAddress, long functionLength, List<Object> args, Map<Integer, String> regNames, Object thisObj) {
|
||||
//TODO
|
||||
return Undefined.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls frame.
|
||||
* @param frame Frame.
|
||||
*/
|
||||
public void callFrame(int frame) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to display list.
|
||||
* @param depth Depth.
|
||||
* @param obj Object.
|
||||
*/
|
||||
public void addToDisplayList(int depth, Object obj) {
|
||||
displayList.put(depth, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes from display list.
|
||||
* @param depth Depth.
|
||||
* @return
|
||||
*/
|
||||
public Object removeFromDisplayList(int depth) {
|
||||
return displayList.remove(depth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets from display list.
|
||||
* @param depth Depth.
|
||||
* @return
|
||||
*/
|
||||
public Object getFromDisplayList(int depth) {
|
||||
return displayList.get(depth);
|
||||
}
|
||||
|
||||
@@ -18,50 +18,94 @@ package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Local data area for ActionScript execution.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class LocalDataArea {
|
||||
|
||||
/**
|
||||
* Constant pool
|
||||
*/
|
||||
public List<String> constantPool;
|
||||
|
||||
/**
|
||||
* Stack
|
||||
*/
|
||||
public Stack<Object> stack = new Stack<>();
|
||||
|
||||
/**
|
||||
* Functions
|
||||
*/
|
||||
public List<ActionScriptFunction> functions = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Local variables
|
||||
*/
|
||||
public Map<String, Object> localVariables = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Withs
|
||||
*/
|
||||
public List<ActionScriptWith> withs = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Local registers - map of register index to value
|
||||
*/
|
||||
public Map<Integer, Object> localRegisters = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Target object
|
||||
*/
|
||||
public Object target;
|
||||
|
||||
/**
|
||||
* Stage
|
||||
*/
|
||||
public Stage stage;
|
||||
|
||||
/**
|
||||
* Jump
|
||||
*/
|
||||
public Long jump;
|
||||
|
||||
/**
|
||||
* Return value
|
||||
*/
|
||||
public Object returnValue;
|
||||
|
||||
/**
|
||||
* Execution exception
|
||||
*/
|
||||
public String executionException;
|
||||
|
||||
/**
|
||||
* Check stack size
|
||||
*/
|
||||
public boolean checkStackSize = true;
|
||||
|
||||
/**
|
||||
* Undefined count
|
||||
*/
|
||||
public int undefinedCount = 0;
|
||||
|
||||
/**
|
||||
* Constructs a new local data area.
|
||||
* @param stage Stage
|
||||
*/
|
||||
public LocalDataArea(Stage stage) {
|
||||
this.stage = stage;
|
||||
this.target = this.stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new local data area.
|
||||
* @param stage Stage
|
||||
* @param preserveVariableOrder Preserve variable order
|
||||
*/
|
||||
public LocalDataArea(Stage stage, boolean preserveVariableOrder) {
|
||||
this.stage = stage;
|
||||
target = this.stage;
|
||||
@@ -70,6 +114,10 @@ public class LocalDataArea {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the stack is empty.
|
||||
* @return True if the stack is empty, otherwise false
|
||||
*/
|
||||
public boolean stackIsEmpty() {
|
||||
if (!checkStackSize) {
|
||||
return false;
|
||||
@@ -77,6 +125,11 @@ public class LocalDataArea {
|
||||
return stack.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the stack has a minimum size.
|
||||
* @param count Count
|
||||
* @return True if the stack has a minimum size, otherwise false
|
||||
*/
|
||||
public boolean stackHasMinSize(int count) {
|
||||
if (!checkStackSize) {
|
||||
return true;
|
||||
@@ -84,6 +137,9 @@ public class LocalDataArea {
|
||||
return stack.size() >= count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the local data area.
|
||||
*/
|
||||
public void clear() {
|
||||
constantPool = null;
|
||||
stack.clear();
|
||||
@@ -99,10 +155,19 @@ public class LocalDataArea {
|
||||
undefinedCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes a value onto the stack.
|
||||
* @param val Value
|
||||
* @return Value
|
||||
*/
|
||||
public synchronized Object push(Object val) {
|
||||
return stack.push(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Peeks at the top of the stack.
|
||||
* @return Value
|
||||
*/
|
||||
public synchronized Object peek() {
|
||||
if (!checkStackSize && stack.isEmpty()) {
|
||||
undefinedCount++;
|
||||
@@ -112,6 +177,10 @@ public class LocalDataArea {
|
||||
return stack.peek();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a value from the stack.
|
||||
* @return Value
|
||||
*/
|
||||
public synchronized Object pop() {
|
||||
boolean isEmpty = stack.isEmpty();
|
||||
if (!checkStackSize && stack.isEmpty()) {
|
||||
@@ -121,10 +190,18 @@ public class LocalDataArea {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a value from the stack as a number.
|
||||
* @return Value
|
||||
*/
|
||||
public synchronized Double popAsNumber() {
|
||||
return EcmaScript.toNumberAs2(pop());
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops a value from the stack as a string.
|
||||
* @return Value
|
||||
*/
|
||||
public synchronized String popAsString() {
|
||||
return EcmaScript.toString(pop());
|
||||
}
|
||||
|
||||
@@ -20,23 +20,40 @@ import com.jpexs.decompiler.flash.timeline.DepthState;
|
||||
import com.jpexs.decompiler.flash.timeline.Frame;
|
||||
import com.jpexs.decompiler.flash.timeline.Timeline;
|
||||
import com.jpexs.decompiler.flash.timeline.Timelined;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* Stage object for ActionScript execution.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Stage extends DisplayObject {
|
||||
|
||||
/**
|
||||
* Start time of the movie
|
||||
*/
|
||||
protected long startTime;
|
||||
|
||||
/**
|
||||
* Timelined object
|
||||
*/
|
||||
protected Timelined timelined;
|
||||
|
||||
/**
|
||||
* Timeline
|
||||
*/
|
||||
protected Timeline timeline;
|
||||
|
||||
/**
|
||||
* Current frame
|
||||
*/
|
||||
protected Frame frame;
|
||||
|
||||
/**
|
||||
* Constructs a new Stage object.
|
||||
* @param timelined Timelined object
|
||||
*/
|
||||
public Stage(Timelined timelined) {
|
||||
startTime = System.currentTimeMillis();
|
||||
this.timelined = timelined;
|
||||
@@ -44,6 +61,10 @@ public class Stage extends DisplayObject {
|
||||
this.frame = timelined != null && this.timeline.getFrameCount() > 0 ? this.timeline.getFrame(0) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerates the instance names.
|
||||
* @return List of instance names
|
||||
*/
|
||||
@Override
|
||||
public List<String> enumerate() {
|
||||
List<String> ret = new ArrayList<>();
|
||||
@@ -57,6 +78,11 @@ public class Stage extends DisplayObject {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the member with the given name.
|
||||
* @param name Name of the member
|
||||
* @return Member object
|
||||
*/
|
||||
@Override
|
||||
protected Object getThisMember(String name) {
|
||||
if (frame != null) {
|
||||
@@ -69,10 +95,18 @@ public class Stage extends DisplayObject {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current frame.
|
||||
* @return Current frame
|
||||
*/
|
||||
public long getTime() {
|
||||
return System.currentTimeMillis() - startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets total frames.
|
||||
* @return Total frames
|
||||
*/
|
||||
@Override
|
||||
public int getTotalFrames() {
|
||||
if (timeline == null) {
|
||||
@@ -81,6 +115,10 @@ public class Stage extends DisplayObject {
|
||||
return timeline.getFrameCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto frame.
|
||||
* @param frameNum Frame.
|
||||
*/
|
||||
@Override
|
||||
public void gotoFrame(int frameNum) {
|
||||
super.gotoFrame(frameNum);
|
||||
@@ -89,6 +127,10 @@ public class Stage extends DisplayObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto label.
|
||||
* @param label Label
|
||||
*/
|
||||
@Override
|
||||
public void gotoLabel(String label) {
|
||||
if (timeline == null) {
|
||||
@@ -100,18 +142,33 @@ public class Stage extends DisplayObject {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops sounds.
|
||||
*/
|
||||
public void stopSounds() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle quality.
|
||||
*/
|
||||
public void toggleQuality() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL.
|
||||
* @param url URL
|
||||
* @param target Target
|
||||
*/
|
||||
public void getURL(String url, String target) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Traces the given values.
|
||||
* @param val Values
|
||||
*/
|
||||
public void trace(Object... val) {
|
||||
|
||||
}
|
||||
|
||||
@@ -20,10 +20,16 @@ import com.jpexs.decompiler.flash.action.model.ConstantPool;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
|
||||
/**
|
||||
*
|
||||
* Store type action interface.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface StoreTypeAction {
|
||||
|
||||
/**
|
||||
* Gets variable name.
|
||||
* @param stack Stack
|
||||
* @param cpool Constant pool
|
||||
* @return Variable name
|
||||
*/
|
||||
public String getVariableName(TranslateStack stack, ConstantPool cpool);
|
||||
}
|
||||
|
||||
@@ -17,13 +17,20 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
/**
|
||||
*
|
||||
* Unknown action exception.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class UnknownActionException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* OpCode.
|
||||
*/
|
||||
public int opCode;
|
||||
|
||||
/**
|
||||
* Constructs a new unknown action exception.
|
||||
* @param opCode OpCode
|
||||
*/
|
||||
public UnknownActionException(int opCode) {
|
||||
super("Unknown opCode: 0x" + Integer.toHexString(opCode));
|
||||
this.opCode = opCode;
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.action.model.ActionItem;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
* Raised when actual address has been referenced with an unknown jump
|
||||
* Raised when actual address has been referenced with an unknown jump.
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
@@ -43,7 +44,7 @@ public class UnknownJumpException extends RuntimeException {
|
||||
public List<ActionItem> output;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Constructs a new unknown jump exception.
|
||||
*
|
||||
* @param stack Actual stack
|
||||
* @param addr Actual address
|
||||
@@ -56,9 +57,9 @@ public class UnknownJumpException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the object
|
||||
* Returns a string representation of the object.
|
||||
*
|
||||
* @return a string representation of the object.
|
||||
* @return A string representation of the object
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
+95
-62
@@ -17,22 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
import com.jpexs.decompiler.flash.IdentifiersDeobfuscation;
|
||||
import com.jpexs.decompiler.flash.action.model.CallFunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.CallMethodActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ExtendsActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ImplementsOpActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.NewMethodActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.NewObjectActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.ReturnActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
|
||||
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
|
||||
import com.jpexs.decompiler.flash.action.model.*;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
@@ -41,41 +26,48 @@ import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
import com.jpexs.decompiler.graph.model.PushItem;
|
||||
import com.jpexs.decompiler.graph.model.ScriptEndItem;
|
||||
import com.jpexs.decompiler.graph.model.TernarOpItem;
|
||||
import com.jpexs.decompiler.graph.model.*;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* Detects AS2 classes inside DoInitAction tags
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ActionScript2ClassDetector {
|
||||
|
||||
/**
|
||||
* Logger
|
||||
*/
|
||||
private static final Logger logger = Logger.getLogger(ActionScript2ClassDetector.class.getName());
|
||||
|
||||
/**
|
||||
* Assert exception
|
||||
*/
|
||||
private class AssertException extends Exception {
|
||||
|
||||
/**
|
||||
* Condition
|
||||
*/
|
||||
private final String condition;
|
||||
|
||||
/**
|
||||
* Constructs a new AssertException
|
||||
* @param condition Condition
|
||||
*/
|
||||
public AssertException(String condition) {
|
||||
super(condition);
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets condition
|
||||
* @return Condition
|
||||
*/
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
@@ -84,12 +76,12 @@ public class ActionScript2ClassDetector {
|
||||
|
||||
/**
|
||||
* Checks whether an item is direct submember of path. a.b.c.d is submember
|
||||
* of a.b.c, x.y.z is not submember of x,
|
||||
* of a.b.c, x.y.z is not submember of x.
|
||||
*
|
||||
* @param item
|
||||
* @param objectPath
|
||||
* @param item Item
|
||||
* @param objectPath Path
|
||||
* @param newPathItem New submember name
|
||||
* @return
|
||||
* @return True if item is submember of path
|
||||
*/
|
||||
private boolean isMemberOfPath(GraphTargetItem item, List<String> objectPath, Reference<String> newPathItem) {
|
||||
List<String> path = getMembersPath(item);
|
||||
@@ -109,9 +101,9 @@ public class ActionScript2ClassDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d]
|
||||
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d].
|
||||
*
|
||||
* @param item
|
||||
* @param item Item
|
||||
* @return List of path or null if not members path
|
||||
*/
|
||||
private List<String> getMembersPath(GraphTargetItem item) {
|
||||
@@ -144,6 +136,12 @@ public class ActionScript2ClassDetector {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts SetMemberActionItem to GetMemberActionItem,
|
||||
* SetVariableActionItem to GetVariableActionItem.
|
||||
* @param item Item
|
||||
* @return Converted item
|
||||
*/
|
||||
private GraphTargetItem setMemberToGetMember(GraphTargetItem item) {
|
||||
if (item instanceof SetMemberActionItem) {
|
||||
return new GetMemberActionItem(null, null, ((SetMemberActionItem) item).object, ((SetMemberActionItem) item).objectName);
|
||||
@@ -153,6 +151,13 @@ public class ActionScript2ClassDetector {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts NewMethodActionItem or NewObjectActionItem
|
||||
* to GetMemberActionItem or GetVariableActionItem.
|
||||
* @param nobj Item
|
||||
* @return Converted item
|
||||
* @throws AssertException
|
||||
*/
|
||||
private GraphTargetItem newToGetMember(GraphTargetItem nobj) throws AssertException {
|
||||
if (nobj instanceof NewMethodActionItem) {
|
||||
NewMethodActionItem nm = (NewMethodActionItem) nobj;
|
||||
@@ -164,6 +169,11 @@ public class ActionScript2ClassDetector {
|
||||
throw new AssertException("NewMethod or NewObject expected");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets path of setmembers: a.b.c.d => [a,b,c,d].
|
||||
* @param item Item
|
||||
* @return List of path or null if not members path
|
||||
*/
|
||||
private List<String> getSetMembersPath(GraphTargetItem item) {
|
||||
if (item instanceof SetVariableActionItem) {
|
||||
SetVariableActionItem sv = (SetVariableActionItem) item;
|
||||
@@ -199,10 +209,10 @@ public class ActionScript2ClassDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get register id or -1 if not found
|
||||
* Get register id or -1 if not found.
|
||||
*
|
||||
* @param item
|
||||
* @return
|
||||
* @param item Item
|
||||
* @return Register id
|
||||
*/
|
||||
private int getAsRegisterNum(GraphTargetItem item, String assertName) throws AssertException {
|
||||
if (item instanceof DirectValueActionItem) {
|
||||
@@ -219,28 +229,10 @@ public class ActionScript2ClassDetector {
|
||||
throw new AssertException("not a register - " + assertName);
|
||||
}
|
||||
|
||||
/*private boolean isInstanceRegister(GraphTargetItem item, Reference<Integer> instanceReg, Reference<Integer> classReg,Reference<GraphTargetItem> extracted, String assertName) throws AssertException {
|
||||
if (item instanceof DirectValueActionItem) {
|
||||
DirectValueActionItem dv = (DirectValueActionItem) item;
|
||||
if (dv.value instanceof RegisterNumber) {
|
||||
RegisterNumber rn = (RegisterNumber) dv.value;
|
||||
if (rn.number == instanceReg.getVal()) {
|
||||
return true;
|
||||
} else if (rn.number == classReg.getVal()) {
|
||||
return false;
|
||||
}else{
|
||||
throw new AssertException(assertName + " - unknown register");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (item instanceof TemporaryRegister) {
|
||||
TemporaryRegister tr = (TemporaryRegister) item;
|
||||
if (!"prototype".equals(getAsString(gm.memberName, "memberName"))) {
|
||||
throw new AssertException("memberName not \"prototype\"");
|
||||
}
|
||||
return tr.getRegId();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets item without global prefix.
|
||||
* @param ti Item
|
||||
* @return Item without global prefix
|
||||
*/
|
||||
private static GraphTargetItem getWithoutGlobal(GraphTargetItem ti) {
|
||||
GraphTargetItem t = ti;
|
||||
@@ -270,6 +262,13 @@ public class ActionScript2ClassDetector {
|
||||
return ti;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts item to string.
|
||||
* @param item Item
|
||||
* @param itemName Item name for exception
|
||||
* @return String
|
||||
* @throws AssertException
|
||||
*/
|
||||
private String getAsString(GraphTargetItem item, String itemName) throws AssertException {
|
||||
if (!(item instanceof DirectValueActionItem)) {
|
||||
throw new AssertException(itemName + " not DirectValue");
|
||||
@@ -281,6 +280,19 @@ public class ActionScript2ClassDetector {
|
||||
return mnDv.getAsString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects classes in AS2 script.
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param parts Parts
|
||||
* @param variables Variables
|
||||
* @param partsPos Parts position
|
||||
* @param commandsStartPos Commands start position
|
||||
* @param commandsEndPos Commands end position
|
||||
* @param commands Commands
|
||||
* @param classNamePath Class name path
|
||||
* @param scriptPath Script path
|
||||
* @return True if class was detected
|
||||
*/
|
||||
private boolean checkClassContent(Map<String, Map<String, Trait>> uninitializedClassTraits, List<GraphTargetItem> parts, HashMap<String, GraphTargetItem> variables, int partsPos, int commandsStartPos, int commandsEndPos, List<GraphTargetItem> commands, List<String> classNamePath, String scriptPath) {
|
||||
|
||||
try {
|
||||
@@ -787,7 +799,12 @@ public class ActionScript2ClassDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
//in some weird cases, ifs are detected as ternars, this method expands ternars to ifs
|
||||
|
||||
/**
|
||||
* In some weird cases, ifs are detected as ternars,
|
||||
* this method expands ternars to ifs.
|
||||
* @param commands Commands
|
||||
*/
|
||||
private void expandTernars(List<GraphTargetItem> commands) {
|
||||
for (int i = 0; i < commands.size(); i++) {
|
||||
if (commands.get(i) instanceof TernarOpItem) {
|
||||
@@ -811,6 +828,15 @@ public class ActionScript2ClassDetector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if variants.
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param commands Commands
|
||||
* @param variables Variables
|
||||
* @param pos Position
|
||||
* @param scriptPath Script path
|
||||
* @return True if some of the variants was detected
|
||||
*/
|
||||
private boolean checkIfVariants(Map<String, Map<String, Trait>> uninitializedClassTraits, List<GraphTargetItem> commands, HashMap<String, GraphTargetItem> variables, int pos, String scriptPath) {
|
||||
|
||||
expandTernars(commands);
|
||||
@@ -950,6 +976,13 @@ public class ActionScript2ClassDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks class.
|
||||
* @param uninitializedClassTraits Uninitialized class traits
|
||||
* @param commands Commands
|
||||
* @param variables Variables
|
||||
* @param scriptPath Script path
|
||||
*/
|
||||
public void checkClass(Map<String, Map<String, Trait>> uninitializedClassTraits, List<GraphTargetItem> commands, HashMap<String, GraphTargetItem> variables, String scriptPath) {
|
||||
List<GraphTargetItem> localCommands = new ArrayList<>(commands);
|
||||
boolean changed = false;
|
||||
|
||||
+38
-15
@@ -16,17 +16,8 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -37,11 +28,23 @@ import java.util.logging.Logger;
|
||||
*/
|
||||
public class ActionScript2Classes {
|
||||
|
||||
/**
|
||||
* Map of class name to map of trait name to trait
|
||||
*/
|
||||
private static final Map<String, Map<String, Trait>> classToTraits = new HashMap<>();
|
||||
/**
|
||||
* Map of class name to list of parent class names
|
||||
*/
|
||||
private static final Map<String, List<String>> classInheritance = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Whether the classes are already initialized
|
||||
*/
|
||||
private static boolean inited = false;
|
||||
|
||||
/**
|
||||
* Initialize the classes
|
||||
*/
|
||||
private static synchronized void initClasses() {
|
||||
if (inited) {
|
||||
return;
|
||||
@@ -100,6 +103,13 @@ public class ActionScript2Classes {
|
||||
inited = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if trait exists in class.
|
||||
* @param className Class name
|
||||
* @param name Trait name
|
||||
* @param withInheritance Whether to check also parent classes
|
||||
* @return True if trait exists
|
||||
*/
|
||||
public static boolean traitExists(String className, String name, boolean withInheritance) {
|
||||
if (!classToTraits.containsKey(className)) {
|
||||
return false;
|
||||
@@ -124,11 +134,11 @@ public class ActionScript2Classes {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class traits, null when class not exists (or is not built-in)
|
||||
* Get class traits, null when class not exists (or is not built-in).
|
||||
*
|
||||
* @param className
|
||||
* @param withInheritance
|
||||
* @return
|
||||
* @param className Class name
|
||||
* @param withInheritance Whether to include parent classes
|
||||
* @return Map of trait name to trait
|
||||
*/
|
||||
public static Map<String, Trait> getClassTraits(String className, boolean withInheritance) {
|
||||
initClasses();
|
||||
@@ -157,16 +167,29 @@ public class ActionScript2Classes {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of class name to map of trait name to trait.
|
||||
* @return Map of class name to map of trait name to trait
|
||||
*/
|
||||
public static Map<String, Map<String, Trait>> getClassToTraits() {
|
||||
initClasses();
|
||||
return classToTraits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get map of class name to list of parent class names.
|
||||
* @return Map of class name to list of parent class names
|
||||
*/
|
||||
public static Map<String, List<String>> getClassInheritance() {
|
||||
initClasses();
|
||||
return classInheritance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sample test
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Map<String, Trait> traits = getClassTraits("flash.filters.BevelFilter", true);
|
||||
if (traits != null) {
|
||||
|
||||
@@ -17,16 +17,38 @@
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a method trait in ActionScript 2.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Method implements Trait {
|
||||
|
||||
/**
|
||||
* Whether the method is static
|
||||
*/
|
||||
private final boolean isStatic;
|
||||
|
||||
/**
|
||||
* Name of the method
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Return type of the method
|
||||
*/
|
||||
private final String returnType;
|
||||
|
||||
/**
|
||||
* Name of the class the method is in
|
||||
*/
|
||||
private final String className;
|
||||
|
||||
/**
|
||||
* Constructs a new method trait.
|
||||
* @param isStatic Whether the method is static
|
||||
* @param name Name of the method
|
||||
* @param returnType Return type of the method
|
||||
* @param className Name of the class the method is in
|
||||
*/
|
||||
public Method(boolean isStatic, String name, String returnType, String className) {
|
||||
this.isStatic = isStatic;
|
||||
this.name = name;
|
||||
@@ -34,35 +56,63 @@ public class Method implements Trait {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the class the method is in.
|
||||
* @return Class name
|
||||
*/
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the method is static.
|
||||
* @return Whether the method is static
|
||||
*/
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the method.
|
||||
* @return Name
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the return type of the method.
|
||||
* @return Return type
|
||||
*/
|
||||
public String getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the method to a string.
|
||||
* @return String representation
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return (isStatic ? "static " : "") + "function " + name + ": " + returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the call type of the method.
|
||||
* @return Call type
|
||||
*/
|
||||
@Override
|
||||
public String getCallType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the trait.
|
||||
* @return Trait type
|
||||
*/
|
||||
@Override
|
||||
public String getType() {
|
||||
return "Function";
|
||||
|
||||
@@ -17,18 +17,38 @@
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a trait in ActionScript 2.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public interface Trait {
|
||||
|
||||
/**
|
||||
* Whether the trait is static
|
||||
* @return Whether the trait is static
|
||||
*/
|
||||
public boolean isStatic();
|
||||
|
||||
/**
|
||||
* Gets the name of the trait
|
||||
* @return Name of the trait
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Gets the type of the trait
|
||||
* @return Type of the trait
|
||||
*/
|
||||
public String getType();
|
||||
|
||||
/**
|
||||
* Gets the call type of the trait
|
||||
* @return Call type of the trait
|
||||
*/
|
||||
public String getCallType();
|
||||
|
||||
/**
|
||||
* Gets the class name of the trait
|
||||
* @return Class name of the trait
|
||||
*/
|
||||
public String getClassName();
|
||||
}
|
||||
|
||||
+24
-17
@@ -17,15 +17,7 @@
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.action.model.CallMethodActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.DeleteActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.GetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.NewMethodActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.*;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.ClassActionItem;
|
||||
import com.jpexs.decompiler.flash.action.model.clauses.InterfaceActionItem;
|
||||
import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
|
||||
@@ -34,22 +26,19 @@ import com.jpexs.decompiler.flash.tags.DoInitActionTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* Uninitialized class fields detector for ActionScript 2.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class UninitializedClassFieldsDetector {
|
||||
|
||||
/**
|
||||
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d]
|
||||
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d].
|
||||
*
|
||||
* @param item
|
||||
* @param item Item to get path from
|
||||
* @return List of path or null if not members path
|
||||
*/
|
||||
private List<String> getMembersPath(GraphTargetItem item) {
|
||||
@@ -92,6 +81,11 @@ public class UninitializedClassFieldsDetector {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets full path of item: a.b.c.d => [a,b,c,d].
|
||||
* @param item Item to get path from
|
||||
* @return List of path or null if not members path
|
||||
*/
|
||||
private List<String> getFullPath(GraphTargetItem item) {
|
||||
if (item instanceof GetMemberActionItem) {
|
||||
return getMembersPath(item);
|
||||
@@ -149,6 +143,14 @@ public class UninitializedClassFieldsDetector {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the class contains a trait.
|
||||
* @param classTraits Class traits
|
||||
* @param classInheritance Class inheritance
|
||||
* @param className Class name
|
||||
* @param name Trait name
|
||||
* @return Whether the class contains the trait
|
||||
*/
|
||||
private boolean containsTrait(Map<String, Map<String, Trait>> classTraits, Map<String, List<String>> classInheritance, String className, String name) {
|
||||
if (!classTraits.containsKey(className)) {
|
||||
return false;
|
||||
@@ -164,6 +166,11 @@ public class UninitializedClassFieldsDetector {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates uninitialized class traits.
|
||||
* @param swf SWF
|
||||
* @return Map of class name to map of trait name to trait
|
||||
*/
|
||||
public Map<String, Map<String, Trait>> calculateAs2UninitializedClassTraits(SWF swf) {
|
||||
if (swf.isAS3()) {
|
||||
return new HashMap<>();
|
||||
|
||||
@@ -17,16 +17,38 @@
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
|
||||
/**
|
||||
*
|
||||
* Represents a variable trait in ActionScript 2.
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class Variable implements Trait {
|
||||
|
||||
/**
|
||||
* Whether the variable is static
|
||||
*/
|
||||
private final boolean isStatic;
|
||||
|
||||
/**
|
||||
* Name of the variable
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Type of the variable
|
||||
*/
|
||||
private final String type;
|
||||
|
||||
/**
|
||||
* Name of the class the variable is in
|
||||
*/
|
||||
private final String className;
|
||||
|
||||
/**
|
||||
* Constructs a new variable trait.
|
||||
* @param isStatic Whether the variable is static
|
||||
* @param name Name of the variable
|
||||
* @param type Type of the variable
|
||||
* @param className Name of the class the variable is in
|
||||
*/
|
||||
public Variable(boolean isStatic, String name, String type, String className) {
|
||||
this.isStatic = isStatic;
|
||||
this.name = name;
|
||||
@@ -34,31 +56,55 @@ public class Variable implements Trait {
|
||||
this.className = className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the variable is static
|
||||
* @return Whether the variable is static
|
||||
*/
|
||||
@Override
|
||||
public boolean isStatic() {
|
||||
return isStatic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the variable
|
||||
* @return Name of the variable
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the variable
|
||||
* @return Type of the variable
|
||||
*/
|
||||
@Override
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the variable to a string
|
||||
* @return String representation of the variable
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return (isStatic ? "static " : "") + "var " + name + ": " + getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the call type of the variable
|
||||
* @return Call type of the variable
|
||||
*/
|
||||
@Override
|
||||
public String getCallType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class name of the variable
|
||||
* @return Class name of the variable
|
||||
*/
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return className;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* ActionScript 2.0 decompilation.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.as2;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Deobfuscating ActionScript 1/2 code.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.deobfuscation;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Fast action list.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.fastactionlist;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Flash Lite Actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.flashlite;
|
||||
+1
-1
@@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.action.model;
|
||||
import com.jpexs.decompiler.graph.model.CompoundableBinaryOp;
|
||||
|
||||
/**
|
||||
* CompoundableBinaryOp but for AS1/2, which does not have &&, || compound
|
||||
* CompoundableBinaryOp but for AS1/2, which does not have &&, || compound
|
||||
* operator.
|
||||
*
|
||||
* @author JPEXS
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* High-level ActionScript 1/2 model of various clauses.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.model.clauses;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* High-level ActionScript 1/2 model of operations.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.model.operations;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* ActionScript1/2 high-level model.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.model;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Parsing, decompiling and execution of ActionScript 1/2 bytecode.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Parsing ActionScript 1/2 scripts and P-code.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.parser;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Parsing ActionScript 1/2 PCode.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.parser.pcode;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Parsing ActionScript 1/2 scripts.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.parser.script;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Special actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.special;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* SWF 3 actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf3;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* SWF 4 actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf4;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* SWF 5 actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf5;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* SWF 6 actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf6;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* SWF 7 actions.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action.swf7;
|
||||
Reference in New Issue
Block a user