diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java index b6d79ec20..9f49772a8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AbortRetryIgnoreHandler.java @@ -17,22 +17,46 @@ package com.jpexs.decompiler.flash; /** - * + * A handler for abort, retry, ignore, ignore all dialog * @author JPEXS */ public interface AbortRetryIgnoreHandler { + /** + * Undefined result + */ public static int UNDEFINED = -1; + /** + * Abort result + */ public static int ABORT = 0; + /** + * Retry result + */ public static int RETRY = 1; + /** + * Ignore result + */ public static int IGNORE = 2; + /** + * Ignore all result + */ public static int IGNORE_ALL = 3; + /** + * Handles the thrown exception + * @param thrown The thrown exception + * @return The result + */ public int handle(Throwable thrown); + /** + * Returns a new instance of this handler + * @return A new instance of this handler + */ public AbortRetryIgnoreHandler getNewInstance(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AppResources.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AppResources.java index f05f4ded2..970bf46e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AppResources.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/AppResources.java @@ -19,17 +19,31 @@ package com.jpexs.decompiler.flash; import java.util.ResourceBundle; /** - * + * Application resources * @author JPEXS */ public class AppResources { + /** + * Resource bundle + */ private static final ResourceBundle resourceBundle = ResourceBundle.getBundle("com.jpexs.decompiler.flash.locales.AppResources"); + /** + * Translates a key + * @param key The key + * @return The translated key + */ public static String translate(String key) { return resourceBundle.getString(key); } + /** + * Translates a key from a bundle + * @param bundle The bundle + * @param key The key + * @return The translated key + */ public static String translate(String bundle, String key) { ResourceBundle b = ResourceBundle.getBundle(bundle); return b.getString(key); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java index 002b06059..062955de7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ApplicationInfo.java @@ -20,43 +20,94 @@ import java.io.IOException; import java.util.Properties; /** - * + * Application information * @author JPEXS */ public class ApplicationInfo { + /** + * Application name + */ public static final String APPLICATION_NAME = "JPEXS Free Flash Decompiler"; + /** + * CLI application name + */ public static final String CLI_APPLICATION_NAME = "@|blue JPEXS|@ @|green Free|@ @|red Flash Decompiler|@"; + /** + * Short application name + */ public static final String SHORT_APPLICATION_NAME = "FFDec"; + /** + * Vendor + */ public static final String VENDOR = "JPEXS"; + /** + * Library version + */ public static String libraryVersion = ""; + /** + * Version + */ public static String version = ""; + /** + * Revision + */ public static String revision = ""; + /** + * Version major + */ public static int version_major = 4; + /** + * Version minor + */ public static int version_minor = 0; + /** + * Version release + */ public static int version_release = 0; + /** + * Version build + */ public static int version_build = 0; + /** + * Nightly + */ public static boolean nightly = false; + /** + * CLI application version name + */ public static String cliApplicationVerName; + /** + * Application version name + */ public static String applicationVerName; + /** + * Short application version name + */ public static String shortApplicationVerName; + /** + * Git hub project + */ public static final String GIT_HUB_PROJECT = "jindrapetrik/jpexs-decompiler"; + /** + * Project page + */ public static final String PROJECT_PAGE = "https://github.com/" + GIT_HUB_PROJECT; /** @@ -79,6 +130,9 @@ public class ApplicationInfo { loadLibraryVersion(); } + /** + * Loads library version + */ private static void loadLibraryVersion() { Properties prop = new Properties(); try { @@ -97,6 +151,9 @@ public class ApplicationInfo { } } + /** + * Loads properties. + */ private static void loadProperties() { Properties prop = new Properties(); try { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java index 178bc45b4..a2471ace9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BaseLocalData.java @@ -19,18 +19,28 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.SecondPassData; + import java.util.HashSet; import java.util.Set; /** - * + * Base local data * @author JPEXS */ public abstract class BaseLocalData { + /** + * Line start instruction + */ public GraphSourceItem lineStartInstruction; + /** + * Set of all switch parts + */ public Set allSwitchParts = new HashSet<>(); + /** + * Second pass data + */ public SecondPassData secondPassData = null; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java index 11b18187a..6a196c41c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/BinarySWFBundle.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash; import com.jpexs.helpers.SwfHeaderStreamSearch; import com.jpexs.helpers.streams.SeekableInputStream; + import java.io.IOException; import java.io.InputStream; import java.util.LinkedHashMap; @@ -26,23 +27,41 @@ import java.util.Map; import java.util.Set; /** - * + * Binary search SWF bundle * @author JPEXS */ public class BinarySWFBundle implements Bundle { + /** + * SWF search + */ private final SWFSearch search; + /** + * Constructs a new BinarySWFBundle. + * @param is Input stream + * @param noCheck Do not check + * @param searchMode Search mode + * @throws IOException + */ public BinarySWFBundle(InputStream is, boolean noCheck, SearchMode searchMode) throws IOException { search = new SWFSearch(new SwfHeaderStreamSearch(is), noCheck, searchMode); search.process(); } + /** + * Gets size of the search. + * @return Size of the search + */ @Override public int length() { return search.length(); } + /** + * Gets keys. + * @return Keys + */ @Override public Set getKeys() { Set ret = new LinkedHashSet<>(); @@ -52,6 +71,11 @@ public class BinarySWFBundle implements Bundle { return ret; } + /** + * Gets openable. + * @param key Key + * @return Openable + */ @Override public SeekableInputStream getOpenable(String key) { if (!key.startsWith("[")) { @@ -69,6 +93,10 @@ public class BinarySWFBundle implements Bundle { } } + /** + * Gets all. + * @return Map of string to seekable input stream + */ @Override public Map getAll() { Map ret = new LinkedHashMap<>(); @@ -78,16 +106,30 @@ public class BinarySWFBundle implements Bundle { return ret; } + /** + * Gets extension. + * @return Extension + */ @Override public String getExtension() { return "bin"; } + /** + * Checks if read only. + * @return True if read only, false otherwise + */ @Override public boolean isReadOnly() { return true; } + /** + * Replaces openable. + * @param key Key + * @param is Input stream + * @return True if successful, false otherwise + */ @Override public boolean putOpenable(String key, InputStream is) { throw new UnsupportedOperationException("Save not supported for this type of bundle"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java index c553347d6..149529c34 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Bundle.java @@ -17,28 +17,64 @@ package com.jpexs.decompiler.flash; import com.jpexs.helpers.streams.SeekableInputStream; + import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.Set; /** - * + * Bundle interface. + * A bundle is a collection of openable files. (e.g. SWC, ZIP, etc.) * @author JPEXS */ public interface Bundle { + /** + * Gets number of openable files in the bundle. + * @return Number of openable files in the bundle + */ public int length(); + /** + * Gets keys of openable files in the bundle. + * @return Keys of openable files in the bundle + */ public Set getKeys(); + /** + * Gets openable file by key. + * @param key Key + * @return Openable file + * @throws IOException + */ public SeekableInputStream getOpenable(String key) throws IOException; + /** + * Gets all openable files in the bundle. + * @return Map from key to seekable input stream + * @throws IOException + */ public Map getAll() throws IOException; + /** + * Gets extension of the bundle. (without dot) + * @return Extension of the bundle + */ public String getExtension(); + /** + * Checks if the bundle is read-only. + * @return True if the bundle is read-only, false otherwise + */ public boolean isReadOnly(); + /** + * Replace openable file by key. + * @param key Key + * @param is New input stream + * @return True if the file was replaced, false otherwise + * @throws IOException + */ public boolean putOpenable(String key, InputStream is) throws IOException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java index fea1066d0..be89e791c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java @@ -30,29 +30,34 @@ import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.helpers.ImmediateFuture; + import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * Decompiler thread pool. * @author JPEXS */ public class DecompilerPool { + /** + * Executor + */ private final ThreadPoolExecutor executor; + /** + * Openable to futures map + */ private Map>> openableToFutures = new WeakHashMap<>(); + /** + * Constructs a new DecompilerPool. + */ public DecompilerPool() { int threadCount = Configuration.getParallelThreadCount(); executor = new ThreadPoolExecutor(threadCount, threadCount, @@ -60,6 +65,13 @@ public class DecompilerPool { new LinkedBlockingQueue<>()); } + /** + * Submits a task. + * @param src Source + * @param actions Actions + * @param listener Listener + * @return Future + */ public Future submitTask(ASMSource src, ActionList actions, ScriptDecompiledListener listener) { Callable callable = new Callable() { @Override @@ -92,6 +104,13 @@ public class DecompilerPool { return submit(callable); } + /** + * Submits a task. + * @param abcIndex ABC index + * @param pack Script pack + * @param listener Listener + * @return Future + */ public Future submitTask(AbcIndexing abcIndex, ScriptPack pack, ScriptDecompiledListener listener) { Callable callable = new Callable() { @Override @@ -128,6 +147,11 @@ public class DecompilerPool { return submit(callable); } + /** + * Submits a task. + * @param callable Callable + * @return Future + */ private Future submit(Callable callable) { boolean parallel = Configuration.parallelSpeedUp.get(); if (parallel) { @@ -149,6 +173,10 @@ public class DecompilerPool { } } + /** + * Gets statistics. + * @return Statistics + */ public String getStat() { return "core: " + executor.getCorePoolSize() + " size: " + executor.getPoolSize() @@ -159,6 +187,13 @@ public class DecompilerPool { + " completed: " + executor.getCompletedTaskCount(); } + /** + * Decompiles ASM source. + * @param src ASM source + * @param actions Actions + * @return Highlighted text + * @throws InterruptedException + */ public HighlightedText decompile(ASMSource src, ActionList actions) throws InterruptedException { Future future = submitTask(src, actions, null); SWF swf = src.getSwf(); @@ -183,6 +218,13 @@ public class DecompilerPool { return null; } + /** + * Decompiles a script pack. + * @param abcIndex ABC indexing + * @param pack Script pack + * @return Highlighted text + * @throws InterruptedException + */ public HighlightedText decompile(AbcIndexing abcIndex, ScriptPack pack) throws InterruptedException { Future future = submitTask(abcIndex, pack, null); @@ -208,11 +250,19 @@ public class DecompilerPool { return null; } + /** + * Shuts down the pool. + * @throws InterruptedException + */ public void shutdown() throws InterruptedException { executor.shutdown(); executor.awaitTermination(100, TimeUnit.SECONDS); } + /** + * Destroys a SWF. + * @param swf SWF + */ public void destroySwf(SWF swf) { List> futures = openableToFutures.get(swf); if (futures != null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java index b0e339dec..ef0a5e0cf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DeobfuscationListener.java @@ -17,10 +17,13 @@ package com.jpexs.decompiler.flash; /** - * + * Listener for deobfuscation events. * @author JPEXS */ public interface DeobfuscationListener { + /** + * Called when an item is deobfuscated. + */ public void itemDeobfuscated(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DisassemblyListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DisassemblyListener.java index 61a9848a0..a32f25379 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DisassemblyListener.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DisassemblyListener.java @@ -17,14 +17,29 @@ package com.jpexs.decompiler.flash; /** - * + * Listener for disassembly events. * @author JPEXS */ public interface DisassemblyListener { + /** + * Called on progress of reading. + * @param pos Position + * @param total Total length + */ public void progressReading(long pos, long total); + /** + * Called on progress of deobfuscating. + * @param pos Position + * @param total Total length + */ public void progressToString(long pos, long total); + /** + * Called on progress of deobfuscating. + * @param pos Position + * @param total Total length + */ public void progressDeobfuscating(long pos, long total); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EndOfStreamException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EndOfStreamException.java index f9b39ce56..d5daa37ed 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EndOfStreamException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EndOfStreamException.java @@ -19,11 +19,14 @@ package com.jpexs.decompiler.flash; import java.io.IOException; /** - * + * Exception thrown when end of stream is reached. * @author JPEXS */ public class EndOfStreamException extends IOException { + /** + * Constructs a new EndOfStreamException. + */ public EndOfStreamException() { super("Premature end of the stream reached"); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EventListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EventListener.java index da51db135..fa9ac25c1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EventListener.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/EventListener.java @@ -17,14 +17,33 @@ package com.jpexs.decompiler.flash; /** - * + * Interface for listening to events. * @author JPEXS */ public interface EventListener { + /** + * Handles exporting event. + * @param type Event type + * @param index Index of the exported item + * @param count Total count of exported items + * @param data Data + */ public void handleExportingEvent(String type, int index, int count, Object data); + /** + * Handles exported event. + * @param type Event type + * @param index Index of the exported item + * @param count Total count of exported items + * @param data Data + */ public void handleExportedEvent(String type, int index, int count, Object data); + /** + * Handles event. + * @param event Event name + * @param data Data + */ public void handleEvent(String event, Object data); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java index 2798f0d77..5196624e2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java @@ -17,32 +17,49 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.graph.Loop; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; /** - * + * Final decompilation processing local d ata. * @author JPEXS */ public class FinalProcessLocalData { + /** + * Temporary registers used in the code. + */ public final HashSet temporaryRegisters; + + /** + * Loops in the code. + */ public final List loops; + + /** + * Register usage. Map of setLocal ip to set of getLocal ips. + */ public Map> registerUsage; - public Set getRegisterUsage(int regIndex) { + /** + * Returns register usage for given setLocal ip. + * @param setLocalIp SetLocal ip + * @return Set of getLocal ips + */ + public Set getRegisterUsage(int setLocalIp) { if (registerUsage == null) { return new HashSet<>(); } - if (!registerUsage.containsKey(regIndex)) { + if (!registerUsage.containsKey(setLocalIp)) { return new HashSet<>(); } - return registerUsage.get(regIndex); + return registerUsage.get(setLocalIp); } + /** + * Constructs new FinalProcessLocalData. + * @param loops Loops in the code + */ public FinalProcessLocalData(List loops) { temporaryRegisters = new HashSet<>(); registerUsage = new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java index 1d98abbc5..3b1748447 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java @@ -25,49 +25,90 @@ import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; + +import java.util.*; import java.util.regex.Pattern; /** - * + * Identifiers deobfuscation. * @author JPEXS */ public class IdentifiersDeobfuscation { + /** + * Random number generator. + */ private static final Random rnd = new Random(); + /** + * Default size of random string. + */ private final int DEFAULT_FOO_SIZE = 10; + /** + * All variable names. + */ public HashSet allVariableNamesStr = new HashSet<>(); + /** + * Type counts. + */ private final HashMap typeCounts = new HashMap<>(); + /** + * AS2 name cache. + */ private static final Cache as2NameCache = Cache.getInstance(false, true, "as2_ident", true); + /** + * AS3 name cache. + */ private static final Cache as3NameCache = Cache.getInstance(false, true, "as3_ident", true); + /** + * Valid first characters. + */ public static final String VALID_FIRST_CHARACTERS = "\\p{Lu}\\p{Ll}\\p{Lt}\\p{Lm}\\p{Lo}_$"; + /** + * Valid next characters. + */ public static final String VALID_NEXT_CHARACTERS = VALID_FIRST_CHARACTERS + "\\p{Nl}\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}"; + /** + * Valid name pattern. + */ private static final Pattern VALID_NAME_PATTERN = Pattern.compile("^[a-zA-Z_\\$][a-zA-Z0-9_\\$]*$"); + /** + * Identifier pattern. + */ private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("^[" + VALID_FIRST_CHARACTERS + "][" + VALID_NEXT_CHARACTERS + "]*$"); + /** + * Valid name pattern with dot. + */ private static final Pattern VALID_NAME_PATTERN_DOT = Pattern.compile("^[a-zA-Z_\\$][a-zA-Z0-9_.\\$]*$"); + /** + * Identifier pattern with dot. + */ private static final Pattern IDENTIFIER_PATTERN_DOT = Pattern.compile("^[" + VALID_FIRST_CHARACTERS + "][" + VALID_NEXT_CHARACTERS + ".]*$"); + /** + * Random name generator characters. + */ public static final String FOO_CHARACTERS = "bcdfghjklmnpqrstvwz"; + /** + * Random name generator join characters. + */ public static final String FOO_JOIN_CHARACTERS = "aeiouy"; - // http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000477.html + /** + * Reserved words in AS2. + * http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000477.html + */ public static final String[] reservedWordsAS2 = { // is "add" really a keyword? documentation says yes, but I can create "add" variable in CS6... // "add", @@ -99,7 +140,10 @@ public class IdentifiersDeobfuscation { "typeof", "undefined", "var", "void", "while", "with" }; - // http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/syntax.html + /** + * Reserved words in AS3. + * http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/syntax.html + */ public static final String[] reservedWordsAS3 = { "as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "else", "extends", "false", "finally", "for", "function", "if", "implements", "import", "in", "instanceof", @@ -111,7 +155,9 @@ public class IdentifiersDeobfuscation { "void", "while", "with" }; - // TODO, why do we have 2 different list? Moved from AVM2Deobfuscation + /** + * TODO, why do we have 2 different list? Moved from AVM2Deobfuscation + */ public static final String[] reservedWordsAS3_2 = { "as", "break", "case", "catch", "class", "const", "continue", "default", "delete", "do", "each", "else", "extends", "false", "finally", "for", "function", "get", "if", "implements", "import", "in", "instanceof", @@ -119,9 +165,16 @@ public class IdentifiersDeobfuscation { "return", "set", "super", "switch", "this", "throw", "true", "try", "typeof", "use", "var", /*"void",*/ "while", "with", "dynamic", "default", "final", "in", "static"}; - //syntactic keywords - can be used as identifiers, but that have special meaning in certain contexts + /** + * Syntactic keywords - can be used as identifiers, but that have special meaning in certain contexts + */ public static final String[] syntacticKeywordsAS3 = {"each", "get", "set", "namespace", "include", "dynamic", "final", "native", "override", "static"}; + /** + * Checks if string is reserved word. + * @param s String + * @param as3 Is ActionScript3 + */ public static boolean isReservedWord(String s, boolean as3) { if (s == null) { return false; @@ -136,7 +189,11 @@ public class IdentifiersDeobfuscation { return false; } - // TODO: Why do we need this method??? + /** + * TODO: Why do we need this method??? + * @param s String + * @return True if string is reserved word + */ public static boolean isReservedWord2(String s) { if (s == null) { return false; @@ -151,6 +208,12 @@ public class IdentifiersDeobfuscation { return false; } + /** + * Generates random string. + * @param firstUppercase First character uppercase + * @param rndSize Random size + * @return Random string + */ public static String fooString(boolean firstUppercase, int rndSize) { int len = 3 + rnd.nextInt(rndSize - 3); StringBuilder sb = new StringBuilder(len); @@ -170,6 +233,14 @@ public class IdentifiersDeobfuscation { return sb.toString(); } + /** + * Deobfuscates instance names. + * @param as3 Is ActionScript3 + * @param namesMap Names map + * @param renameType Rename type + * @param tags Tags + * @param selected Preselected names + */ public void deobfuscateInstanceNames(boolean as3, HashMap namesMap, RenameType renameType, Iterable tags, Map selected) { for (Tag t : tags) { if (t instanceof DefineSpriteTag) { @@ -197,6 +268,15 @@ public class IdentifiersDeobfuscation { } } + /** + * Deobfuscates package names. + * @param as3 Is ActionScript3 + * @param pkg Package + * @param namesMap Names map + * @param renameType Rename type + * @param selected Preselected names + * @return Deobfuscated package + */ public DottedChain deobfuscatePackage(boolean as3, DottedChain pkg, HashMap namesMap, RenameType renameType, Map selected) { if (namesMap.containsKey(pkg)) { return namesMap.get(pkg); @@ -221,6 +301,15 @@ public class IdentifiersDeobfuscation { return null; } + /** + * Deobfuscates name with package. + * @param as3 Is ActionScript3 + * @param n Name + * @param namesMap Names map + * @param renameType Rename type + * @param selected Preselected names + * @return Deobfuscated name + */ public String deobfuscateNameWithPackage(boolean as3, String n, HashMap namesMap, RenameType renameType, Map selected) { DottedChain nChain = DottedChain.parseNoSuffix(n); DottedChain pkg = nChain.getWithoutLast(); @@ -251,6 +340,12 @@ public class IdentifiersDeobfuscation { return null; } + /** + * Checks if string is valid slash path. + * @param s String + * @param exceptions Exceptions + * @return True if string is valid slash path + */ private static boolean isValidSlashPath(String s, String... exceptions) { String[] slashParts = s.split("\\/"); if (s.isEmpty()) { @@ -274,6 +369,12 @@ public class IdentifiersDeobfuscation { return true; } + /** + * Checks if string is valid name with slash. + * @param s String + * @param exceptions Exceptions + * @return True if string is valid name with slash + */ public static boolean isValidNameWithSlash(String s, String... exceptions) { if (s.contains(":")) { String[] pathVar = s.split(":"); @@ -291,6 +392,13 @@ public class IdentifiersDeobfuscation { } } + /** + * Checks if string is valid name with dot. + * @param as3 Is ActionScript3 + * @param s String + * @param exceptions Exceptions + * @return True if string is valid name with dot + */ public static boolean isValidNameWithDot(boolean as3, String s, String... exceptions) { for (String e : exceptions) { if (e.equals(s)) { @@ -313,6 +421,13 @@ public class IdentifiersDeobfuscation { return false; } + /** + * Checks if string is valid name. + * @param as3 Is ActionScript3 + * @param s String + * @param exceptions Exceptions + * @return True if string is valid name + */ public static boolean isValidName(boolean as3, String s, String... exceptions) { for (String e : exceptions) { if (e.equals(s)) { @@ -335,6 +450,17 @@ public class IdentifiersDeobfuscation { return false; } + /** + * Deobfuscates name. + * @param as3 Is ActionScript3 + * @param s String + * @param firstUppercase First character uppercase + * @param usageType Usage type + * @param namesMap Names map + * @param renameType Rename type + * @param selected Preselected names + * @return Deobfuscated name + */ public String deobfuscateName(boolean as3, String s, boolean firstUppercase, String usageType, HashMap namesMap, RenameType renameType, Map selected) { if (usageType == null) { usageType = "name"; @@ -380,6 +506,12 @@ public class IdentifiersDeobfuscation { return null; } + /** + * Appends obfuscated identifier. + * @param s String + * @param writer Writer + * @return Writer + */ public static GraphTextWriter appendObfuscatedIdentifier(String s, GraphTextWriter writer) { writer.append("\u00A7"); escapeOIdentifier(s, writer); @@ -387,7 +519,7 @@ public class IdentifiersDeobfuscation { } /** - * Ensures identifier is valid and if not, uses paragraph syntax + * Ensures identifier is valid and if not, uses paragraph syntax. * * @param as3 Is ActionScript3 * @param s Identifier @@ -426,6 +558,12 @@ public class IdentifiersDeobfuscation { return ret; } + /** + * Escapes obfuscated identifier. + * @param s String + * @param writer Writer + * @return Writer + */ public static GraphTextWriter escapeOIdentifier(String s, GraphTextWriter writer) { for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); @@ -465,6 +603,11 @@ public class IdentifiersDeobfuscation { return writer; } + /** + * Escapes obfuscated identifier. + * @param s String + * @return Escaped string + */ public static String escapeOIdentifier(String s) { StringBuilder ret = new StringBuilder(s.length()); for (int i = 0; i < s.length(); i++) { @@ -505,6 +648,9 @@ public class IdentifiersDeobfuscation { return ret.toString(); } + /** + * Clears cache. + */ public static void clearCache() { as2NameCache.clear(); as3NameCache.clear(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java index 43df2e32d..6c257d5b8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceInfo.java @@ -18,43 +18,79 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.iggy.conversion.IggySwfBundle; import com.jpexs.helpers.Path; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; + +import java.io.*; /** - * + * Information about openable source. * @author JPEXS */ public class OpenableSourceInfo { + /** + * Input stream of the source + */ private final InputStream inputStream; + /** + * File path of the source + */ private String file; + /** + * Title of the file + */ private String fileTitle; + /** + * Whether to auto-detect bundle + */ private final boolean detectBundle; + /** + * Whether the source is empty + */ private boolean empty = false; + /** + * Kind of the source + */ private OpenableSourceKind kind; + /** + * Constructs OpenableSourceInfo with empty source + * @param fileTitle Title of the file + */ public OpenableSourceInfo(String fileTitle) { this(null, null, fileTitle, false); empty = true; } + /** + * Check if the source is empty + * @return true if the source is empty + */ public boolean isEmpty() { return empty; } + /** + * Constructs OpenableSourceInfo with input stream + * @param inputStream Input stream of the source + * @param file File path of the source + * @param fileTitle Title of the file + */ public OpenableSourceInfo(InputStream inputStream, String file, String fileTitle) { this(inputStream, file, fileTitle, true); } + /** + * Constructs OpenableSourceInfo with input stream + * @param inputStream Input stream of the source + * @param file File path of the source + * @param fileTitle Title of the file + * @param detectBundle Whether to auto-detect bundle + */ public OpenableSourceInfo(InputStream inputStream, String file, String fileTitle, boolean detectBundle) { this.inputStream = inputStream; this.file = file; @@ -63,10 +99,17 @@ public class OpenableSourceInfo { detectKind(); } + /** + * Gets kind of the source. + * @return Kind of the source + */ public OpenableSourceKind getKind() { return kind; } + /** + * Detects kind of the source. + */ private void detectKind() { if (isBundle()) { kind = OpenableSourceKind.BUNDLE; @@ -77,32 +120,54 @@ public class OpenableSourceInfo { } } + /** + * Gets input stream of the source. + * @return Input stream of the source + */ public InputStream getInputStream() { return inputStream; } + /** + * Gets file path of the source. + * @return File path of the source + */ public String getFile() { return file; } + /** + * Sets file path of the source. + * @param file File path of the source + */ public void setFile(String file) { this.file = file; detectKind(); empty = false; } + /** + * Sets title of the file. + * + * @param fileTitle File title + */ public void setFileTitle(String fileTitle) { this.fileTitle = fileTitle; } + /** + * Gets title of the file. + * + * @return File title + */ public String getFileTitle() { return fileTitle; } /** - * Get title of the file + * Gets title of the file. * - * @return file title + * @return File title */ public String getFileTitleOrName() { if (fileTitle != null) { @@ -111,11 +176,15 @@ public class OpenableSourceInfo { return file; } + /** + * Checks if the source is a bundle. + * @return True if the source is a bundle + */ public boolean isBundle() { if (inputStream == null && file != null) { File fileObj = new File(file); String fileName = fileObj.getName(); - if (fileName.startsWith("asdec_") && fileName.endsWith(".tmp")) { + if (fileName.startsWith("asdec_") && fileName.endsWith(".tmp")) { //FIXME: is this still needed? return false; } String extension = Path.getExtension(fileObj); @@ -124,6 +193,13 @@ public class OpenableSourceInfo { return false; } + /** + * Gets bundle from the source. + * @param noCheck Whether to check the bundle + * @param searchMode Search mode + * @return Bundle or null + * @throws IOException + */ public Bundle getBundle(boolean noCheck, SearchMode searchMode) throws IOException { if (!isBundle()) { return null; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java index 77886a007..da4900515 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/OpenableSourceKind.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; /** - * + * Openable source kind. * @author JPEXS */ public enum OpenableSourceKind { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java index d15e2ecdb..8f8e536f3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ParseException.java @@ -17,15 +17,26 @@ package com.jpexs.decompiler.flash; /** - * + * Parse exception. * @author JPEXS */ public abstract class ParseException extends Exception { + /** + * Line number where the exception occurred. + */ public long line; + /** + * Text of the exception. + */ public String text; + /** + * Constructs a new parse exception. + * @param text + * @param line + */ public ParseException(String text, long line) { super("ParseException:" + text + " on line " + line); this.line = line; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java index a60005a3b..8e1f61052 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ReadOnlyTagList.java @@ -17,45 +17,82 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.tags.Tag; + import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** - * + * Tag list that is read-only. * @author JPEXS */ public class ReadOnlyTagList implements Iterable { + /** + * Empty read-only tag list. + */ public static final ReadOnlyTagList EMPTY = new ReadOnlyTagList(new ArrayList<>()); + /** + * List of tags. + */ private final List list; + /** + * Constructs read-only tag list. + * @param list List of tags + */ public ReadOnlyTagList(List list) { this.list = list; } + /** + * Returns iterator for tags. + * @return Iterator for tags + */ @Override public Iterator iterator() { return list.iterator(); } + /** + * Returns number of tags. + * @return Number of tags + */ public int size() { return list.size(); } + /** + * Returns true if list is empty. + * @return True if list is empty + */ public boolean isEmpty() { return list.isEmpty(); } + /** + * Returns tag at index. + * @param index Index + * @return Tag + */ public Tag get(int index) { return list.get(index); } + /** + * Returns index of tag. + * @param tag Tag + * @return Index of tag or -1 if not found + */ public int indexOf(Tag tag) { return list.indexOf(tag); } + /** + * Converts list to array list. + * @return Array list + */ public ArrayList toArrayList() { return new ArrayList<>(list); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RetryTask.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RetryTask.java index 779a3c8dd..3bb6883c1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RetryTask.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RetryTask.java @@ -19,20 +19,36 @@ package com.jpexs.decompiler.flash; import java.io.IOException; /** - * + * Task that can be retried on error. * @author JPEXS */ public class RetryTask { + /** + * Runnable that can throw IOException. + */ private final RunnableIOEx r; + /** + * Handler for retrying. + */ private final AbortRetryIgnoreHandler handler; + /** + * Constructs a new RetryTask. + * @param r Runnable that can throw IOException + * @param handler Handler for retrying + */ public RetryTask(RunnableIOEx r, AbortRetryIgnoreHandler handler) { this.r = r; this.handler = handler; } + /** + * Runs the task. + * @throws IOException + * @throws InterruptedException + */ public void run() throws IOException, InterruptedException { boolean retry; do { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOEx.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOEx.java index 4ce7e1173..5de4392f4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOEx.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOEx.java @@ -19,11 +19,16 @@ package com.jpexs.decompiler.flash; import java.io.IOException; /** - * + * Runnable with IOException and InterruptedException. * @author JPEXS */ @FunctionalInterface public interface RunnableIOEx { + /** + * Run method. + * @throws IOException + * @throws InterruptedException + */ public void run() throws IOException, InterruptedException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOExResult.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOExResult.java index 643427d99..80fcbbbff 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOExResult.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/RunnableIOExResult.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; /** - * + * Interface for runnable with result. * @param Type of result * @author JPEXS */ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java index 5196541d5..d1491e392 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWC.java @@ -16,31 +16,48 @@ */ package com.jpexs.decompiler.flash; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; /** - * + * SWC file. * @author JPEXS */ public class SWC extends ZippedBundle { + /** + * Constructs SWC from input stream. + * @param is Input stream + * @throws IOException + */ public SWC(InputStream is) throws IOException { super(is); } + /** + * Constructs SWC from file. + * @param filename File + * @throws IOException + */ public SWC(File filename) throws IOException { super(filename); } + /** + * Initializes SWC bundle. + * @param is Input stream + * @param filename File + * @throws IOException + */ @Override protected void initBundle(InputStream is, File filename) throws IOException { super.initBundle(is, filename); @@ -76,6 +93,10 @@ public class SWC extends ZippedBundle { } } + /** + * Returns extension of SWC file. + * @return Extension + */ @Override public String getExtension() { return "swc"; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 180c77b66..88c707423 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -26,13 +26,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AbcMultiNameCollisionFixer; import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; -import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; -import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; @@ -41,36 +35,13 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.action.ActionGraphSource; -import com.jpexs.decompiler.flash.action.ActionList; -import com.jpexs.decompiler.flash.action.ActionListReader; -import com.jpexs.decompiler.flash.action.ActionLocalData; +import com.jpexs.decompiler.flash.action.*; import com.jpexs.decompiler.flash.action.as2.UninitializedClassFieldsDetector; -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.GetVariableActionItem; +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.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; +import com.jpexs.decompiler.flash.action.swf4.*; +import com.jpexs.decompiler.flash.action.swf5.*; import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.cache.AS2Cache; import com.jpexs.decompiler.flash.cache.AS3Cache; @@ -96,135 +67,48 @@ import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; -import com.jpexs.decompiler.flash.tags.DebugIDTag; -import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; -import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.DefineSpriteTag; -import com.jpexs.decompiler.flash.tags.DoABC2Tag; -import com.jpexs.decompiler.flash.tags.DoABCTag; -import com.jpexs.decompiler.flash.tags.DoInitActionTag; -import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; -import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; -import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; -import com.jpexs.decompiler.flash.tags.EndTag; -import com.jpexs.decompiler.flash.tags.ExportAssetsTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.tags.JPEGTablesTag; -import com.jpexs.decompiler.flash.tags.MetadataTag; -import com.jpexs.decompiler.flash.tags.ProtectTag; -import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.SymbolClassTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagStub; -import com.jpexs.decompiler.flash.tags.VideoFrameTag; -import com.jpexs.decompiler.flash.tags.base.ASMSource; -import com.jpexs.decompiler.flash.tags.base.ASMSourceContainer; -import com.jpexs.decompiler.flash.tags.base.BinaryDataInterface; -import com.jpexs.decompiler.flash.tags.base.BoundedTag; -import com.jpexs.decompiler.flash.tags.base.ButtonTag; -import com.jpexs.decompiler.flash.tags.base.CharacterIdTag; -import com.jpexs.decompiler.flash.tags.base.CharacterTag; -import com.jpexs.decompiler.flash.tags.base.DrawableTag; -import com.jpexs.decompiler.flash.tags.base.Exportable; -import com.jpexs.decompiler.flash.tags.base.FontTag; -import com.jpexs.decompiler.flash.tags.base.ImageTag; -import com.jpexs.decompiler.flash.tags.base.ImportTag; -import com.jpexs.decompiler.flash.tags.base.MorphShapeTag; -import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; -import com.jpexs.decompiler.flash.tags.base.RemoveTag; -import com.jpexs.decompiler.flash.tags.base.RenderContext; -import com.jpexs.decompiler.flash.tags.base.ShapeTag; -import com.jpexs.decompiler.flash.tags.base.SoundTag; -import com.jpexs.decompiler.flash.tags.base.TextTag; +import com.jpexs.decompiler.flash.tags.*; +import com.jpexs.decompiler.flash.tags.base.*; import com.jpexs.decompiler.flash.tags.enums.ImageFormat; import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; -import com.jpexs.decompiler.flash.timeline.AS2Package; import com.jpexs.decompiler.flash.timeline.Frame; -import com.jpexs.decompiler.flash.timeline.FrameScript; -import com.jpexs.decompiler.flash.timeline.TagScript; -import com.jpexs.decompiler.flash.timeline.Timeline; -import com.jpexs.decompiler.flash.timeline.Timelined; +import com.jpexs.decompiler.flash.timeline.*; import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; -import com.jpexs.decompiler.flash.types.ColorTransform; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SOUNDINFO; +import com.jpexs.decompiler.flash.types.*; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFField; import com.jpexs.decompiler.flash.types.sound.SoundInfoSoundCacheEntry; import com.jpexs.decompiler.flash.xfl.FLAVersion; import com.jpexs.decompiler.flash.xfl.XFLConverter; import com.jpexs.decompiler.flash.xfl.XFLExportSettings; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.decompiler.graph.model.IfItem; import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.Cache; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.ImmediateFuture; -import com.jpexs.helpers.NulStream; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.Reference; -import com.jpexs.helpers.SerializableImage; +import com.jpexs.helpers.*; import com.jpexs.helpers.utf8.Utf8Helper; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.awt.*; import java.awt.geom.AffineTransform; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.*; import java.nio.charset.Charset; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.EmptyStackException; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; +import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; /** * Class representing SWF file. @@ -677,8 +561,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } /** - * Check whether the ExporterInfo (GFX) tag has flag for stripping shapes from DefineFont. - * @return + * Checks whether the ExporterInfo (GFX) tag has flag for stripping shapes from DefineFont. + * @return True if the flag is set, false otherwise. */ public boolean hasStrippedShapesFromFonts() { if (exporterInfo == null) { @@ -692,7 +576,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets main ABCIndexing object for playerflobal.swc - * @return + * @return ABCIndexing */ public static AbcIndexing getPlayerGlobalAbcIndex() { return playerGlobalAbcIndex; @@ -700,7 +584,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets main ABCIndexing object for airglobal.swc - * @return + * @return ABCIndexing */ public static AbcIndexing getAirGlobalAbcIndex() { return airGlobalAbcIndex; @@ -715,7 +599,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ABCIndexing object - * @return + * @return ABCIndexing */ public AbcIndexing getAbcIndex() { if (abcIndex != null) { @@ -745,7 +629,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets number of ABCIndex dependent SWFs - * @return + * @return Number of dependent SWFs */ public int getNumAbcIndexDependencies() { return numAbcIndexDependencies; @@ -753,7 +637,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Set dependencies for ABCIndex for resolving names during editation. - * @param swfs + * @param swfs List of SWFs to set as dependencies */ public void setAbcIndexDependencies(List swfs) { abcIndex = null; @@ -799,7 +683,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets SWF charset. SWF version 5 or lower were non-unicode. SWF object has assigned charset. - * @return + * @return Charset */ public String getCharset() { return charset; @@ -807,7 +691,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets SWF charset. SWF version 5 or lower were non-unicode. SWF object has assigned charset. - * @param charset + * @param charset Charset */ public void setCharset(String charset) { this.charset = charset; @@ -815,7 +699,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets modification flag for header. - * @param headerModified + * @param headerModified Header modified flag */ public void setHeaderModified(boolean headerModified) { this.headerModified = headerModified; @@ -823,7 +707,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets modification flag for header.s - * @return + * @return True if header was modified, false otherwise */ public boolean isHeaderModified() { return headerModified; @@ -911,7 +795,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Clears specified dump info. - * @param di + * @param di Dump info to clear */ private void clearDumpInfo(DumpInfo di) { for (DumpInfo childInfo : di.getChildInfos()) { @@ -998,8 +882,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets all CharacterIdTags for specified character (with the same characterId). - * @param characterId - * @return + * @param characterId Character id + * @return List of CharacterIdTags */ public List getCharacterIdTags(int characterId) { if (characterIdTags == null) { @@ -1011,7 +895,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets CharacterIdTag with specific tag type. - * @param characterId + * @param characterId Id of the character * @param tagId Id of type of the tag. For example DefineFontNameTag.ID * @return CharacterIdTag or null when not found */ @@ -1032,7 +916,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Computes dependent characters of specified Timelined object. - * @param timelined + * @param timelined Timelined object * @param dep Adds results to this map. */ private void computeDependentCharacters(Timelined timelined, Map> dep) { @@ -1087,7 +971,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets dependent characters of a character. - * @param characterId + * @param characterId Character id * @return Set of dependent characterIds */ public Set getDependentCharacters(int characterId) { @@ -1151,7 +1035,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets dependent frames for specified character. - * @param characterId + * @param characterId Character id * @return Set of dependent characterids */ public Set getDependentFrames(int characterId) { @@ -1168,7 +1052,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets character tag by character id - * @param characterId + * @param characterId Character id * @return CharacterTag or null when not found */ public CharacterTag getCharacter(int characterId) { @@ -1177,7 +1061,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets character tag by the assigned AS3 class name (SymbolClass tag) - * @param className + * @param className Class name * @return CharacterTag or null when not found */ public CharacterTag getCharacterByClass(String className) { @@ -1193,7 +1077,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets character tag by the assigned export name (ExportAssets tag) - * @param exportName + * @param exportName Export name * @return CharacterTag or null when not found */ public CharacterTag getCharacterByExportName(String exportName) { @@ -1211,7 +1095,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets export name for specified character. * Export names come from ExportAssets tag. - * @param characterId + * @param characterId Character id * @return Export name or null when no assigned exportname. */ public String getExportName(int characterId) { @@ -1222,7 +1106,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets URL from where the specified class was imported (ImportAssets/2 tag). - * @param className + * @param className Class name * @return URL or null when it's not imported */ public String getClassSourceUrl(String className) { @@ -1231,7 +1115,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets FontTag by class name. - * @param fontClass + * @param fontClass Class name * @return FontTag or null when not found */ public FontTag getFontByClass(String fontClass) { @@ -1250,7 +1134,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets FontTag by font name (that one from DefineFontNameTag). - * @param fontName + * @param fontName Font name * @return FontTag or null when not found */ public FontTag getFontByName(String fontName) { @@ -1270,9 +1154,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets FontTag by font name in tag and font style. * The font name is taken directly from that tag (from FontInfoTag for DefineFont1). - * @param fontName - * @param bold - * @param italic + * @param fontName Font name + * @param bold Bold + * @param italic Italic * @return FontTag or null when not found */ public FontTag getFontByNameInTag(String fontName, boolean bold, boolean italic) { @@ -1295,7 +1179,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * Normal .getCharacterId method od the CharacterTag does not work for * imported characters. * - * @param tag + * @param tag CharacterId tag * @return Character id or -1 if not found */ public int getCharacterId(CharacterIdTag tag) { @@ -1311,7 +1195,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets FontTag by fontId (= characterId). * Logs a SEVERE message when the charter found, but is not a FontTag. - * @param fontId + * @param fontId Font id * @return FontTag or null when not found or the character is not a FontTag */ public FontTag getFont(int fontId) { @@ -1330,7 +1214,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ImageTag by imageId (= characterId). * Logs a SEVERE message when the charter found, but is not a ImageTag. - * @param imageId + * @param imageId Image id * @return ImageTag or null when not found or the character is not an ImageTag */ public ImageTag getImage(int imageId) { @@ -1349,7 +1233,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets DefineSoundTag by soundId (= characterId). * Logs a SEVERE message when the charter found, but is not a DefineSoundTag. - * @param soundId + * @param soundId Sound id * @return DefineSoundTag or null when not found or the character is not an DefineSoundTag */ public DefineSoundTag getSound(int soundId) { @@ -1368,7 +1252,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets TextTag by textId (= characterId). * Logs a SEVERE message when the charter found, but is not a TextTag. - * @param textId + * @param textId Text id * @return TextTag or null when not found or the character is not an TextTag */ public TextTag getText(int textId) { @@ -1386,7 +1270,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets list of all ABC container tags in this SWF. - * @return + * @return List of ABCContainerTag */ public List getAbcList() { if (abcList == null) { @@ -1405,7 +1289,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether this SWF is AS3. * The information is coming from FileAttributesTag and its actionscript3 flag. - * @return + * @return True if AS3, false otherwise */ public boolean isAS3() { FileAttributesTag fileAttributes = getFileAttributes(); @@ -1531,7 +1415,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Resets all timelines of the specified timelined object. - * @param timelined + * @param timelined Timelined object */ public void resetTimelines(Timelined timelined) { timelined.resetTimeline(); @@ -1546,10 +1430,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Walks all tags lin the list and searches for characterTags, characterIdTags and DefineExternalImage2 - * @param list - * @param externalImages2 - * @param characters - * @param characterIdTags + * @param list List of tags + * @param externalImages2 Map of imageId to DefineExternalImage2 + * @param characters Map of characterId to CharacterTag + * @param characterIdTags Map of characterId to list of CharacterIdTags */ private void parseCharacters(Iterable list, Map externalImages2, Map characters, Map> characterIdTags) { Iterator iterator = list.iterator(); @@ -1599,9 +1483,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether a sprite is not recursive and thus valid. - * @param sprite + * @param sprite Sprite to check * @param path Already processed character ids - * @return + * @return True if valid, false otherwise */ private boolean isSpriteValid(DefineSpriteTag sprite, List path) { if (path.contains(sprite.spriteId)) { @@ -1621,7 +1505,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets timeline. - * @return + * @return Timeline */ @Override public Timeline getTimeline() { @@ -1645,7 +1529,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * Gets all tags with specified type id. * * @param tagId Identificator of tag type - * @return + * @return List of tags */ public List getTagData(int tagId) { List ret = new ArrayList<>(); @@ -1660,7 +1544,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Saves this SWF into OutputStream. * - * @param os + * @param os OutputStream */ @Override public void saveTo(OutputStream os) throws IOException { @@ -1669,9 +1553,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Saves this SWF into OutputStream with gfx and includeImported option. - * @param os - * @param gfx - * @param includeImported + * @param os OutputStream + * @param gfx GFX + * @param includeImported Include imported characters * @throws IOException */ public void saveTo(OutputStream os, boolean gfx, boolean includeImported) throws IOException { @@ -1718,7 +1602,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets bytes of header. - * @return + * @return Header bytes */ public byte[] getHeaderBytes() { return getHeaderBytes(compression, gfx, encrypted); @@ -1726,9 +1610,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets specifif header bytes. - * @param compression - * @param gfx - * @return + * @param compression Compression + * @param gfx GFX + * @return Header bytes */ private static byte[] getHeaderBytes(SWFCompression compression, boolean gfx) { return getHeaderBytes(compression, gfx, false); @@ -1736,10 +1620,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets specific header bytes with encrypted option. - * @param compression - * @param gfx + * @param compression Compression + * @param gfx GFX * @param encrypted Enable Harman encryption? - * @return + * @return Header bytes */ private static byte[] getHeaderBytes(SWFCompression compression, boolean gfx, boolean encrypted) { if (compression == SWFCompression.LZMA_ABC) { @@ -1785,7 +1669,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Save file to byte array. * @param includeImported Include imported characterss - * @return + * @return Byte array * @throws IOException */ private byte[] saveToByteArray(boolean includeImported) throws IOException { @@ -1794,9 +1678,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Save file to byte array with GFX option. - * @param gfx + * @param gfx GFX * @param includeImported Include imported characterss - * @return + * @return Byte array * @throws IOException */ private byte[] saveToByteArray(boolean gfx, boolean includeImported) throws IOException { @@ -1831,7 +1715,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * Checks whether SWF is modified. * First checks its internal modified flag, if its not, then walks all tags * and checks their modified flag. - * @return + * @return True if modified, false otherwise */ @Override public boolean isModified() { @@ -1852,8 +1736,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } /** - * Sets modified flag.s - * @param value + * Sets modified flag. + * @param value Value to set */ @Override public void setModified(boolean value) { @@ -1904,7 +1788,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param parallelRead Use parallel threads? * @throws java.io.IOException * @throws java.lang.InterruptedException @@ -1916,7 +1800,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param parallelRead Use parallel threads? * @param charset Charset for SWFs with version 5 or lower (they do not use unicode) * @throws java.io.IOException @@ -1929,7 +1813,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param parallelRead Use parallel threads? * @param lazy Do not parse all data, load it as necessary. * @throws java.io.IOException @@ -1942,7 +1826,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param parallelRead Use parallel threads? * @param lazy Do not parse all data, load it as necessary. * @param charset Charset for SWFs with version 5 or lower (they do not use unicode) @@ -1956,7 +1840,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param parallelRead Use parallel threads? @@ -1970,7 +1854,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param parallelRead Use parallel threads? @@ -1985,7 +1869,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param listener Progress listener * @param parallelRead Use parallel threads? */ @@ -1995,7 +1879,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. - * @param is + * @param is Stream to read SWF from * @param listener Progress listener * @param parallelRead Use parallel threads? * @param charset Charset for SWFs with version 5 or lower (they do not use unicode) @@ -2024,7 +1908,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2039,7 +1923,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream - Faster constructor to check SWF only. - * @param is + * @param is Stream to read SWF from * @throws java.io.IOException */ public SWF(InputStream is) throws IOException { @@ -2049,7 +1933,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2067,7 +1951,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2084,7 +1968,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2101,7 +1985,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2120,7 +2004,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Constructs SWF from stream. * - * @param is + * @param is Stream to read SWF from * @param file Path to the file * @param fileTitle Title of the SWF * @param listener Progress listener @@ -2224,7 +2108,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Resolve importAssets/2 tags. * Loads the external files using URL resolver. Calculates all characters. - * @param resolver + * @param resolver URL resolver */ private synchronized void resolveImported(UrlResolver resolver) { for (int p = 0; p < tags.size(); p++) { @@ -2272,7 +2156,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets openable. (Self for SWF) - * @return + * @return SWF */ @Override public SWF getOpenable() { @@ -2281,7 +2165,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets SWF that is root of the DefineBinaryData tag chain. - * @return + * @return Root SWF */ public SWF getRootSwf() { SWF result = this; @@ -2331,7 +2215,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets short file name based on file title and file. - * @return + * @return Short file name */ @Override public String getShortFileName() { @@ -2341,7 +2225,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets title of this SWF incuding parent nodes like SwfList and * DefineBinaryData. - * @return + * @return Title of the SWF */ @Override public String getShortPathTitle() { @@ -2357,9 +2241,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } /** - * Gets full path title of this SWF incuding parent nodes like SwfList and + * Gets full path title of this SWF including parent nodes like SwfList and * DefineBinaryData. - * @return + * @return Full path title of the SWF */ @Override public String getFullPathTitle() { @@ -2376,7 +2260,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets file. - * @param file + * @param file File */ @Override public void setFile(String file) { @@ -2386,7 +2270,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets file modification date. - * @return + * @return Modification date */ public Date getFileModificationDate() { try { @@ -2408,8 +2292,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets all ABC container tags. - * @param list - * @param actionScripts + * @param list List of tags + * @param actionScripts List of ABC container tags */ private static void getAbcTags(Iterable list, List actionScripts) { for (Tag t : list) { @@ -2511,10 +2395,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Compresses SWF file * - * @param is - * @param os - * @param compression - * @param lzmaProperties + * @param is InputStream + * @param os OutputStream + * @param compression Compression + * @param lzmaProperties LZMA properties */ private static void compress(InputStream is, OutputStream os, SWFCompression compression, byte[] lzmaProperties) throws IOException { byte[] hdr = new byte[8]; @@ -2612,9 +2496,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Compresses SWF file. * - * @param fis - * @param fos - * @param compression + * @param fis InputStream + * @param fos OutputStream + * @param compression Compression * @return True on success */ public static boolean compress(InputStream fis, OutputStream fos, SWFCompression compression) { @@ -2628,8 +2512,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Encrypts Harman AIR encryption - * @param is - * @param os + * @param is InputStream + * @param os OutputStream * @return True on success * @throws java.io.IOException */ @@ -2655,8 +2539,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Decrypts Harman AIR encryption - * @param is - * @param os + * @param is InputStream + * @param os OutputStream * @return True on success * @throws java.io.IOException */ @@ -2688,10 +2572,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Decodes LZMA stream. - * @param is - * @param os - * @param lzmaProperties - * @param fileSize + * @param is InputStream + * @param os OutputStream + * @param lzmaProperties LZMA properties + * @param fileSize File size * @throws IOException */ private static void decodeLZMAStream(InputStream is, OutputStream os, byte[] lzmaProperties, long fileSize) throws IOException { @@ -2707,7 +2591,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Decodes SWF header. * @param headerData First 8 bytes of the file - * @return + * @return SWF header * @throws IOException */ public static SWFHeader decodeHeader(byte[] headerData) throws IOException { @@ -2731,9 +2615,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Decompresses SWF file. - * @param fis - * @param fos - * @return + * @param fis InputStream + * @param fos OutputStream + * @return True on success */ public static boolean decompress(InputStream fis, OutputStream fos) { try { @@ -2746,10 +2630,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Decompresses SWF file - * @param is - * @param os + * @param is InputStream + * @param os OutputStream * @param allowUncompressed When true, it will fail when file is not compressed. - * @return + * @return SWF header * @throws IOException */ private static SWFHeader decompress(InputStream is, OutputStream os, boolean allowUncompressed) throws IOException { @@ -2873,10 +2757,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Rename invalid identifiers. - * @param renameType - * @param fis - * @param fos - * @return + * @param renameType Rename type + * @param fis InputStream + * @param fos OutputStream + * @return True on success */ public static boolean renameInvalidIdentifiers(RenameType renameType, InputStream fis, OutputStream fos) { try { @@ -2893,8 +2777,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ScriptPacks for specified class names. - * @param classNames - * @return + * @param classNames List of class names + * @return List of ScriptPacks * @throws Exception */ public List getScriptPacksByClassNames(List classNames) throws Exception { @@ -2923,8 +2807,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Makes scriptpacks unique. * Unique = no two packs with same classpath exist. - * @param packs - * @return + * @param packs List of ScriptPacks + * @return List of unique ScriptPacks */ private List uniqueAS3Packs(List packs) { List ret = new ArrayList<>(); @@ -2945,7 +2829,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * Gets AS3 ScriptPacks. * ScriptPack = script or a part of script (for compound scripts). * @see ScriptPack - * @return + * @return List of ScriptPacks */ public List getAS3Packs() { List packs = new ArrayList<>(); @@ -2964,7 +2848,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets SWF display rect. - * @return + * @return Display RECT */ @Override public RECT getRect() { @@ -2973,8 +2857,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets display RECT with added tags. - * @param added - * @return + * @param added Set of added tags + * @return Display RECT */ @Override public RECT getRect(Set added) { @@ -2983,7 +2867,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets listener for Export events - * @return + * @return Event listener */ public EventListener getExportEventListener() { EventListener evl = new EventListener() { @@ -3017,7 +2901,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * @param exportSettings Export settings * @param parallel Use parallel threads? * @param evl Event listener - * @return + * @return List of exported files * @throws IOException */ public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, ScriptExportSettings exportSettings, boolean parallel, EventListener evl) throws IOException { @@ -3034,7 +2918,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * @param evl Event listener * @param as2 Export AS1/2 * @param as3 Export AS3 - * @return + * @return List of exported files * @throws IOException */ public List exportActionScript(AbortRetryIgnoreHandler handler, String outdir, List as3scripts, ScriptExportSettings exportSettings, boolean parallel, EventListener evl, boolean as2, boolean as3) throws IOException { @@ -3053,7 +2937,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Get ASMSources (AS1/2). * @param exportFileNames Use export filenames - * @return + * @return Map from path to ASMSource */ public Map getASMs(boolean exportFileNames) { return getASMs(exportFileNames, new ArrayList<>(), true); @@ -3064,7 +2948,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * @param exportFileNames Use export filenames * @param nodesToExport Which tree nodes to export * @param exportAll Export everything - * @return + * @return Map from path to ASMSource */ public Map getASMs(boolean exportFileNames, List nodesToExport, boolean exportAll) { if (exportAll) { @@ -3095,13 +2979,12 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Get ASMSources (AS1/2). * @param exportFileNames Use export filenames - * @param exportFileNames * @param treeItem Current item * @param nodesToExport Which tree nodes to export * @param exportAll Export everything * @param asmsToExport Result - * @param pathExportFilenames - * @param pathNoExportFilenames + * @param pathExportFilenames Path for exported filenames + * @param pathNoExportFilenames Path for not exported filenames */ private void getASMs(boolean exportFileNames, TreeItem treeItem, List nodesToExport, boolean exportAll, Map asmsToExport, String pathExportFilenames, String pathNoExportFilenames) { TreeItem realItem = treeItem instanceof TagScript ? ((TagScript) treeItem).getTag() : treeItem; @@ -3171,8 +3054,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets path of ASMSource. * @param exportFileName Use export filenames - * @param treeItem - * @return + * @param treeItem TreeItem + * @return Path */ private String getASMPath(boolean exportFileName, TreeItem treeItem) { @@ -3203,8 +3086,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Wrap ASMSource to tagscript. - * @param treeItem - * @return + * @param treeItem TreeItem + * @return TagScript if script, otherwise treeItem */ private TreeItem getASMWrapToTagScript(TreeItem treeItem) { if (treeItem instanceof Tag) { @@ -3226,7 +3109,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ASMSources of the first level. * @param tagScriptCache Tag to tagscript cache - * @return + * @return List of ASMSource */ public List getFirstLevelASMNodes(Map tagScriptCache) { Timeline timeline = getTimeline(); @@ -3292,7 +3175,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Adds event listener. - * @param listener + * @param listener Listener */ public final void addEventListener(EventListener listener) { listeners.add(listener); @@ -3305,7 +3188,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes event listener. - * @param listener + * @param listener Listener */ public final void removeEventListener(EventListener listener) { listeners.remove(listener); @@ -3318,8 +3201,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Informs all listeners registered on this SWF. - * @param event - * @param data + * @param event Event + * @param data Data */ public void informListeners(String event, Object data) { for (EventListener listener : listeners) { @@ -3329,7 +3212,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets all VideoFrameTags for specified streamId. - * @param streamId + * @param streamId Stream ID * @param tags Input tags * @param output Output - map of frame number to VideoFrameTag. */ @@ -3349,9 +3232,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Write Little endian to stream - * @param os - * @param val - * @param size + * @param os OutputStream + * @param val Value + * @param size Size * @throws IOException */ private static void writeLE(OutputStream os, long val, int size) throws IOException { @@ -3363,11 +3246,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Creates Wav file from PCM data. - * @param fos - * @param soundRateHz + * @param fos OutputStream + * @param soundRateHz Sound rate in Hz * @param soundSize True = 16 bit, false = 8b bit. * @param soundType True = stereo, false = mono - * @param data + * @param data PCM data * @throws IOException */ public static void createWavFromPcmData(OutputStream fos, int soundRateHz, boolean soundSize, boolean soundType, byte[] data) throws IOException { @@ -3405,8 +3288,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets prefix of type of specified character. - * @param characterTag - * @return + * @param characterTag Character tag + * @return Type prefix */ public static String getTypePrefix(CharacterTag characterTag) { if (characterTag instanceof ShapeTag) { @@ -3435,9 +3318,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Converts set of characters to HTML canvas. - * @param fswf + * @param fswf SWF * @param library Set of characterIds - * @param fos + * @param fos OutputStream * @throws IOException */ public static void libraryToHtmlCanvas(SWF fswf, Set library, OutputStream fos) throws IOException { @@ -3487,19 +3370,19 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } /** - * Gets variables from AS1/2 code - * @param constantPool - * @param localData - * @param stack - * @param output - * @param code - * @param ip - * @param variables - * @param functions - * @param strings - * @param visited - * @param usageTypes - * @param path + * Gets variables from AS1/2 code. + * @param constantPool Constant pool + * @param localData Local data + * @param stack Stack + * @param output Output + * @param code Code + * @param ip Instruction pointer + * @param variables Variables + * @param functions Functions + * @param strings Strings + * @param visited Visited + * @param usageTypes Usage types + * @param path Path * @throws InterruptedException */ private static void getVariables(ConstantPool constantPool, BaseLocalData localData, TranslateStack stack, List output, ActionGraphSource code, int ip, List> variables, List functions, HashMap strings, List visited, HashMap usageTypes, String path) throws InterruptedException { @@ -3663,14 +3546,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets variables from AS1/2 code. - * @param insideDoInitAction - * @param variables - * @param functions - * @param strings - * @param usageTypes - * @param code - * @param addr - * @param path + * @param insideDoInitAction Is inside DoInitAction + * @param variables Variables + * @param functions Functions + * @param strings Strings + * @param usageTypes Usage types + * @param code Code + * @param addr Address + * @param path Path * @throws InterruptedException */ private static void getVariables(boolean insideDoInitAction, List> variables, List functions, HashMap strings, HashMap usageTypes, ActionGraphSource code, int addr, String path) throws InterruptedException { @@ -3680,15 +3563,15 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets variables from AS1/2 code. - * @param insideDefineFunction1 - * @param variables - * @param actionsMap - * @param functions - * @param strings - * @param usageTypes - * @param src - * @param path - * @return + * @param insideDefineFunction1 Is inside DefineFunction1 + * @param variables Variables + * @param actionsMap Actions map + * @param functions Functions + * @param strings Strings + * @param usageTypes Usage types + * @param src Source + * @param path Path + * @return List of variables * @throws InterruptedException */ private List> getVariables(boolean insideDefineFunction1, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes, ASMSource src, String path) throws InterruptedException { @@ -3702,14 +3585,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets variables from AS1/2 code. - * @param insideDefineFunction1 - * @param tags - * @param path - * @param variables - * @param actionsMap - * @param functions - * @param strings - * @param usageTypes + * @param insideDefineFunction1 Is inside DefineFunction1 + * @param tags Tags + * @param path Path + * @param variables Variables + * @param actionsMap Actions map + * @param functions Functions + * @param strings Strings + * @param usageTypes Usage types * @throws InterruptedException */ private void getVariables(boolean insideDefineFunction1, Iterable tags, String path, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { @@ -3733,16 +3616,16 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Adds variable for AS1/2 getVariables. - * @param insideDefineFunction1 - * @param asm - * @param path - * @param processed - * @param variables - * @param actionsMap - * @param functions - * @param strings - * @param usageTypes - * @throws InterruptedException + * @param insideDefineFunction1 Is inside DefineFunction1 + * @param asm ASMSource + * @param path Path + * @param processed Processed + * @param variables Variables + * @param actionsMap Actions map + * @param functions Functions + * @param strings Strings + * @param usageTypes Usage types + * @throws InterruptedException */ private void addVariable(boolean insideDefineFunction1, ASMSource asm, String path, List processed, List> variables, HashMap actionsMap, List functions, HashMap strings, HashMap usageTypes) throws InterruptedException { int pos = 1; @@ -3759,8 +3642,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether AS3 string constant exists. * Walks all ABC containers and ABCs inside. - * @param str - * @return + * @param str String + * @return True if exists */ public boolean as3StringConstantExists(String str) { for (ABCContainerTag abcTag : getAbcList()) { @@ -3793,8 +3676,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Deobfuscates AS3 identifiers. - * @param renameType - * @return + * @param renameType Rename type + * @return Number of changes */ public int deobfuscateAS3Identifiers(RenameType renameType) { AbcIndexing ai = getAbcIndex(); @@ -3851,8 +3734,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Deobfuscates identifiers. - * @param renameType - * @return + * @param renameType Rename type + * @return Number of changes * @throws InterruptedException */ public int deobfuscateIdentifiers(RenameType renameType) throws InterruptedException { @@ -3871,8 +3754,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Renames AS2 identifier. - * @param identifier - * @param newname + * @param identifier Identifier + * @param newname New name * @throws InterruptedException */ public void renameAS2Identifier(String identifier, String newname) throws InterruptedException { @@ -3883,8 +3766,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Deobfuscates AS2 identifiers. - * @param renameType - * @return + * @param renameType Rename type + * @return Number of changes * @throws InterruptedException */ private int deobfuscateAS2Identifiers(RenameType renameType) throws InterruptedException { @@ -3893,7 +3776,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Renames AS2 identifiers. - * @param renameType + * @param renameType Rename type * @param selected Preselected identifiers map. Can be null when no preselected. * @return Number of changes * @throws InterruptedException @@ -4148,7 +4031,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets IdentifiersDeobfuscation. - * @return + * @return IdentifiersDeobfuscation */ public IdentifiersDeobfuscation getDeobfuscation() { return deobfuscation; @@ -4216,8 +4099,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Converts MATRIX to AffineTransform. - * @param mat - * @return + * @param mat Matrix + * @return AffineTransform */ public static AffineTransform matrixToTransform(MATRIX mat) { return new AffineTransform(mat.getScaleXFloat(), mat.getRotateSkew0Float(), @@ -4227,8 +4110,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Puts image to frame cache - * @param key - * @param img + * @param key Key + * @param img Image */ public void putToCache(String key, SerializableImage img) { if (Configuration.useFrameCache.get()) { @@ -4238,10 +4121,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Puts sound to sound cache - * @param soundInfo - * @param soundTag + * @param soundInfo Sound info + * @param soundTag Sound tag * @param resample Resample to 44kHz? - * @param data + * @param data Byte data */ public void putToCache(SOUNDINFO soundInfo, SoundTag soundTag, boolean resample, byte[] data) { SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag, resample); @@ -4359,7 +4242,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes ScriptPack from cache. - * @param pack + * @param pack ScriptPack */ public static void uncache(ScriptPack pack) { if (pack != null) { @@ -4376,8 +4259,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether list of Actions of ASMSource is cached. - * @param src - * @return + * @param src ASMSource + * @return True if cached */ public static boolean isActionListCached(ASMSource src) { if (src != null) { @@ -4392,8 +4275,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether ASMSource is cached. - * @param src - * @return + * @param src ASMSource + * @return True if cached */ public static boolean isCached(ASMSource src) { if (src != null) { @@ -4408,8 +4291,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Checks whether ScriptPack is cached. - * @param pack - * @return + * @param pack ScriptPack + * @return True if cached */ public static boolean isCached(ScriptPack pack) { if (pack != null) { @@ -4425,8 +4308,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets HighlightedText of ASMSource from cache. - * @param src - * @return + * @param src ASMSource + * @return True if cached */ public static HighlightedText getFromCache(ASMSource src) { if (src != null) { @@ -4441,8 +4324,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets image from frame cache. - * @param key - * @return + * @param key Key + * @return Image */ public SerializableImage getFromCache(String key) { if (frameCache.contains(key)) { @@ -4453,10 +4336,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets sound from sound cache. - * @param soundInfo - * @param soundTag + * @param soundInfo Sound info + * @param soundTag Sound tag * @param resample Resample to 44kHz - * @return + * @return Byte data */ public byte[] getFromCache(SOUNDINFO soundInfo, SoundTag soundTag, boolean resample) { SoundInfoSoundCacheEntry key = new SoundInfoSoundCacheEntry(soundInfo, soundTag, resample); @@ -4468,8 +4351,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets HighlightedText for ScriptPack from cache. - * @param pack - * @return + * @param pack ScriptPack + * @return Hi */ public static HighlightedText getFromCache(ScriptPack pack) { if (pack != null) { @@ -4485,8 +4368,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ActionList of ASMSource from cache. - * @param src - * @return + * @param src ASMSource + * @return ActionList */ public static ActionList getActionListFromCache(ASMSource src) { if (src != null) { @@ -4501,9 +4384,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets ActionList of ASMSource from cache, if not in cache, parses it. - * @param src + * @param src ASMSource * @param listeners Disassembly listeners - * @return + * @return ActionList * @throws InterruptedException */ public static ActionList getCachedActionList(ASMSource src, final List listeners) throws InterruptedException { @@ -4547,9 +4430,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets HighlightedText of ASMSource and ActionList from cache, decompiles when not cached. - * @param src - * @param actions - * @return + * @param src ASMSource + * @param actions ActionList + * @return HighlightedText * @throws InterruptedException */ public static HighlightedText getCached(ASMSource src, ActionList actions) throws InterruptedException { @@ -4567,8 +4450,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets HighlightedText of ScriptPack from cache, decompiles when not cached. - * @param pack - * @return + * @param pack ScriptPack + * @return HighlightedText * @throws InterruptedException */ public static HighlightedText getCached(ScriptPack pack) throws InterruptedException { @@ -4587,10 +4470,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets Future of HighlightedText of ASMSource, ActionList - * @param src - * @param actions + * @param src ASMSource + * @param actions ActionList * @param listener Decompiled listeners - * @return + * @return Future of HighlightedText * @throws InterruptedException */ public static Future getCachedFuture(ASMSource src, ActionList actions, ScriptDecompiledListener listener) throws InterruptedException { @@ -4612,9 +4495,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets Future of HighlightedText of ScriptPack - * @param pack + * @param pack ScriptPack * @param listener Decompiled listeners - * @return + * @return Future of HighlightedText * @throws InterruptedException */ public static Future getCachedFuture(ScriptPack pack, ScriptDecompiledListener listener) throws InterruptedException { @@ -4637,7 +4520,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets decompiler pool. - * @return + * @return DecompilerPool */ public DecompilerPool getDecompilerPool() { return decompilerPool; @@ -4645,7 +4528,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets cache of Rectangles. - * @return + * @return Cache of Rectangles */ public Cache getRectCache() { return rectCache; @@ -4653,7 +4536,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets shape export data cache. - * @return + * @return Shape export data cache */ public Cache getShapeExportDataCache() { return shapeExportDataCache; @@ -4661,16 +4544,16 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets image of specified frame of timeline. - * @param timeline - * @param frame - * @param time - * @param cursorPosition - * @param mouseButton - * @param displayRect - * @param transformation - * @param colorTransform - * @param backGroundColor - * @param zoom + * @param timeline Timeline + * @param frame Frame + * @param time Time + * @param cursorPosition Cursor position + * @param mouseButton Mouse button + * @param displayRect Display rectangle + * @param transformation Transformation + * @param colorTransform Color transform + * @param backGroundColor Background color + * @param zoom Zoom * @param canUseSmoothing * @return */ @@ -4706,10 +4589,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes character from timeline. - * @param characterId - * @param timeline + * @param characterId Character ID + * @param timeline Timeline * @param listener Listener to call after removing each of character. - * @return + * @return True if modified */ public boolean removeCharacterFromTimeline(int characterId, Timeline timeline, TagRemoveListener listener) { Set chars = new HashSet<>(); @@ -4719,8 +4602,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes character with dependencies. - * @param toRemove - * @param timeline + * @param toRemove Tag to remove + * @param timeline Timeline * @param listener Listener to call after removing each of character. */ private void removeTagWithDependenciesFromTimeline(Tag toRemove, Timeline timeline, TagRemoveListener listener) { @@ -4737,9 +4620,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes character with dependencies. - * @param toRemove - * @param timeline - * @param dependingChars + * @param toRemove Tag to remove + * @param timeline Timeline + * @param dependingChars Depending characters * @param listener Listener to call after removing each of character. * @return */ @@ -4823,10 +4706,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes character with dependencies. - * @param toRemove - * @param timeline + * @param toRemove Tag to remove + * @param timeline Timeline * @param listener Listener to call after removing each of character. - * @return + * @return True if modified */ private boolean removeTagFromTimeline(Tag toRemove, Timeline timeline, TagRemoveListener listener) { boolean modified = false; @@ -4872,8 +4755,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes tags. - * @param tags - * @param removeDependencies + * @param tags Tags + * @param removeDependencies Remove dependencies? * @param listener Listener to call after removing each of character. */ public void removeTags(Collection tags, boolean removeDependencies, TagRemoveListener listener) { @@ -4895,7 +4778,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes tag from SWF timeline. - * @param index + * @param index Index of tag */ @Override public void removeTag(int index) { @@ -4906,7 +4789,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes tag from SWF timeline. - * @param tag + * @param tag Tag */ @Override public void removeTag(Tag tag) { @@ -4917,8 +4800,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes tag from SWF timeline.s - * @param tag - * @param removeDependencies + * @param tag Tag + * @param removeDependencies Remove dependencies? * @param listener Listener to call after removing each of character. */ public void removeTag(Tag tag, boolean removeDependencies, TagRemoveListener listener) { @@ -4932,9 +4815,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Removes tag from SWF timeline. - * @param timelined - * @param tag - * @param removeDependencies + * @param timelined Timelined + * @param tag Tag + * @param removeDependencies Remove dependencies? * @param listener Listener to call after removing each of character. */ private void removeTagInternal(Timelined timelined, Tag tag, boolean removeDependencies, TagRemoveListener listener) { @@ -4961,7 +4844,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets (readonly) list of all tags in the SWF file. - * @return + * @return Tags */ @Override public ReadOnlyTagList getTags() { @@ -4976,7 +4859,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * Gets (readonly) list of all local tags in the SWF file. * local = not imported. * @deprecated The tags from getTags method call are all local by default now. - * @return + * @return Tags */ public ReadOnlyTagList getLocalTags() { /*List localTags = new ArrayList<>(); @@ -4990,7 +4873,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Adds a tag to the SWF. - * @param tag + * @param tag Tag */ @Override public void addTag(Tag tag) { @@ -5001,8 +4884,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Adds a tag to the SWF at the specified index. - * @param index - * @param tag + * @param index Index + * @param tag Tag */ @Override public void addTag(int index, Tag tag) { @@ -5013,7 +4896,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets index of specified tag. - * @param tag + * @param tag Tag * @return Index or -1 when not found */ @Override @@ -5023,8 +4906,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Adds tag just before targetTag in targetTags timeline. - * @param newTag - * @param targetTag + * @param newTag New tag + * @param targetTag Target tag */ public static void addTagBefore(Tag newTag, Tag targetTag) { Timelined tim = targetTag.getTimelined(); @@ -5096,9 +4979,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Replaces character id with another. - * @param oldCharacterId - * @param newCharacterId - * @return + * @param oldCharacterId Old character id + * @param newCharacterId New character id + * @return True if modified */ public boolean replaceCharacter(int oldCharacterId, int newCharacterId) { boolean modified = false; @@ -5122,8 +5005,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Switches ids of two characters. - * @param characterTag - * @param newCharacterId + * @param characterTag Character tag + * @param newCharacterId New character id */ public void replaceCharacterTags(CharacterTag characterTag, int newCharacterId) { int characterId = characterTag.getCharacterId(); @@ -5147,7 +5030,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Converts SWF to string. - * @return + * @return String */ @Override public String toString() { @@ -5156,7 +5039,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Deobfuscates SWF file. - * @param level + * @param level Deobfuscation level * @throws InterruptedException */ public void deobfuscate(DeobfuscationLevel level) throws InterruptedException { @@ -5399,7 +5282,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Generates SWD file for P-code debugging. * - * @param file + * @param file SWD file * @param breakpoints Breakpoints - map of script name to list of lines * @return True on success * @throws IOException @@ -5412,7 +5295,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Generates SWD file for P-code debugging. * - * @param file + * @param file SWD file * @param breakpoints Breakpoints - map of script name to list of lines * @param swfHash SWF identifier * @return True on success @@ -5503,7 +5386,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Generates SWF file for debugging. * - * @param file + * @param file SWD file * @param breakpoints Breakpoints - map of script name to list of lines * @return True on success * @throws IOException @@ -5515,7 +5398,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Generates SWF file for debugging. * - * @param file + * @param file SWD file * @param breakpoints Breakpoints - map of script name to list of lines * @param swfHash SWF identifier * @return True on success @@ -5656,7 +5539,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Enables telemetry. - * @param password + * @param password Password * @return True on success */ public boolean enableTelemetry(String password) { @@ -5684,9 +5567,9 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets Flex Main class. - * @param ignoredClasses - * @param ignoredNs - * @return + * @param ignoredClasses List of ignored classes + * @param ignoredNs List of ignored namespace names + * @return Main class name */ public String getFlexMainClass(List ignoredClasses, List ignoredNs) { String documentClass = getDocumentClass(); @@ -5830,8 +5713,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Replaces a tag in the SWF. - * @param oldTag - * @param newTag + * @param oldTag Old tag + * @param newTag New tag */ @Override public void replaceTag(Tag oldTag, Tag newTag) { @@ -5845,8 +5728,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Replaces tag at given index. - * @param index - * @param newTag + * @param index Index + * @param newTag New tag */ @Override public void replaceTag(int index, Tag newTag) { @@ -5856,7 +5739,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets rect including strokes. - * @return + * @return Rect including strokes */ @Override public RECT getRectWithStrokes() { @@ -5899,11 +5782,11 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Searches needed characters - * @param characterToNeeded - * @param searched - * @param current - * @param visited - * @return + * @param characterToNeeded Character to needed map + * @param searched Searched character id + * @param current Current character id + * @param visited Visited characters + * @return True if found */ private boolean searchNeeded(Map> characterToNeeded, int searched, int current, Set visited) { if (visited.contains(current)) { @@ -5929,7 +5812,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets file title. - * @param fileTitle + * @param fileTitle File title */ public void setFileTitle(String fileTitle) { this.fileTitle = fileTitle; @@ -5938,7 +5821,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets frame count. * It is a number stored in header. - * @return + * @return Frame count */ @Override public int getFrameCount() { @@ -5948,7 +5831,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets frame count. * It is a number stored in header. - * @param frameCount + * @param frameCount Frame count */ @Override public void setFrameCount(int frameCount) { @@ -5957,7 +5840,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Sets openableList which this SWF is part of. - * @param openableList + * @param openableList OpenableList */ @Override public void setOpenableList(OpenableList openableList) { @@ -5966,7 +5849,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets openableList which this SWF is part of. - * @return + * @return OpenableList */ @Override public OpenableList getOpenableList() { @@ -5984,7 +5867,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets uninitialized class traits in AS2. - * @return + * @return Map of class name to map of trait name to trait */ public synchronized Map> getUninitializedAs2ClassTraits() { if (uninitializedAs2ClassTraits == null) { @@ -5995,7 +5878,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * Gets SWF (self) - * @return + * @return SWF */ @Override public SWF getSwf() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFCompression.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFCompression.java index 01c37926d..485492c13 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFCompression.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFCompression.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; /** - * + * SWF compression types. * @author JPEXS */ public enum SWFCompression { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFHeader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFHeader.java index 87a6c58f5..bfb3550d4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFHeader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFHeader.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; /** - * + * SWF header information. * @author JPEXS */ public class SWFHeader { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index 281e2b24a..b29aa1357 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -19,105 +19,11 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.special.ActionEnd; import com.jpexs.decompiler.flash.action.special.ActionUnknown; -import com.jpexs.decompiler.flash.action.swf3.ActionGetURL; -import com.jpexs.decompiler.flash.action.swf3.ActionGoToLabel; -import com.jpexs.decompiler.flash.action.swf3.ActionGotoFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionNextFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionPlay; -import com.jpexs.decompiler.flash.action.swf3.ActionPrevFrame; -import com.jpexs.decompiler.flash.action.swf3.ActionSetTarget; -import com.jpexs.decompiler.flash.action.swf3.ActionStop; -import com.jpexs.decompiler.flash.action.swf3.ActionStopSounds; -import com.jpexs.decompiler.flash.action.swf3.ActionToggleQuality; -import com.jpexs.decompiler.flash.action.swf3.ActionWaitForFrame; -import com.jpexs.decompiler.flash.action.swf4.ActionAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionAnd; -import com.jpexs.decompiler.flash.action.swf4.ActionAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionCall; -import com.jpexs.decompiler.flash.action.swf4.ActionCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionCloneSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionDivide; -import com.jpexs.decompiler.flash.action.swf4.ActionEndDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionGetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionGetTime; -import com.jpexs.decompiler.flash.action.swf4.ActionGetURL2; -import com.jpexs.decompiler.flash.action.swf4.ActionGetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionGotoFrame2; -import com.jpexs.decompiler.flash.action.swf4.ActionIf; -import com.jpexs.decompiler.flash.action.swf4.ActionJump; -import com.jpexs.decompiler.flash.action.swf4.ActionLess; -import com.jpexs.decompiler.flash.action.swf4.ActionMBAsciiToChar; -import com.jpexs.decompiler.flash.action.swf4.ActionMBCharToAscii; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionMBStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionMultiply; -import com.jpexs.decompiler.flash.action.swf4.ActionNot; -import com.jpexs.decompiler.flash.action.swf4.ActionOr; -import com.jpexs.decompiler.flash.action.swf4.ActionPop; -import com.jpexs.decompiler.flash.action.swf4.ActionPush; -import com.jpexs.decompiler.flash.action.swf4.ActionRandomNumber; -import com.jpexs.decompiler.flash.action.swf4.ActionRemoveSprite; -import com.jpexs.decompiler.flash.action.swf4.ActionSetProperty; -import com.jpexs.decompiler.flash.action.swf4.ActionSetTarget2; -import com.jpexs.decompiler.flash.action.swf4.ActionSetVariable; -import com.jpexs.decompiler.flash.action.swf4.ActionStartDrag; -import com.jpexs.decompiler.flash.action.swf4.ActionStringAdd; -import com.jpexs.decompiler.flash.action.swf4.ActionStringEquals; -import com.jpexs.decompiler.flash.action.swf4.ActionStringExtract; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLength; -import com.jpexs.decompiler.flash.action.swf4.ActionStringLess; -import com.jpexs.decompiler.flash.action.swf4.ActionSubtract; -import com.jpexs.decompiler.flash.action.swf4.ActionToInteger; -import com.jpexs.decompiler.flash.action.swf4.ActionTrace; -import com.jpexs.decompiler.flash.action.swf4.ActionWaitForFrame2; -import com.jpexs.decompiler.flash.action.swf5.ActionAdd2; -import com.jpexs.decompiler.flash.action.swf5.ActionBitAnd; -import com.jpexs.decompiler.flash.action.swf5.ActionBitLShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitOr; -import com.jpexs.decompiler.flash.action.swf5.ActionBitRShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitURShift; -import com.jpexs.decompiler.flash.action.swf5.ActionBitXor; -import com.jpexs.decompiler.flash.action.swf5.ActionCallFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionCallMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; -import com.jpexs.decompiler.flash.action.swf5.ActionDecrement; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal; -import com.jpexs.decompiler.flash.action.swf5.ActionDefineLocal2; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete; -import com.jpexs.decompiler.flash.action.swf5.ActionDelete2; -import com.jpexs.decompiler.flash.action.swf5.ActionEnumerate; -import com.jpexs.decompiler.flash.action.swf5.ActionEquals2; -import com.jpexs.decompiler.flash.action.swf5.ActionGetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionIncrement; -import com.jpexs.decompiler.flash.action.swf5.ActionInitArray; -import com.jpexs.decompiler.flash.action.swf5.ActionInitObject; -import com.jpexs.decompiler.flash.action.swf5.ActionLess2; -import com.jpexs.decompiler.flash.action.swf5.ActionModulo; -import com.jpexs.decompiler.flash.action.swf5.ActionNewMethod; -import com.jpexs.decompiler.flash.action.swf5.ActionNewObject; -import com.jpexs.decompiler.flash.action.swf5.ActionPushDuplicate; -import com.jpexs.decompiler.flash.action.swf5.ActionReturn; -import com.jpexs.decompiler.flash.action.swf5.ActionSetMember; -import com.jpexs.decompiler.flash.action.swf5.ActionStackSwap; -import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister; -import com.jpexs.decompiler.flash.action.swf5.ActionTargetPath; -import com.jpexs.decompiler.flash.action.swf5.ActionToNumber; -import com.jpexs.decompiler.flash.action.swf5.ActionToString; -import com.jpexs.decompiler.flash.action.swf5.ActionTypeOf; -import com.jpexs.decompiler.flash.action.swf5.ActionWith; -import com.jpexs.decompiler.flash.action.swf6.ActionEnumerate2; -import com.jpexs.decompiler.flash.action.swf6.ActionGreater; -import com.jpexs.decompiler.flash.action.swf6.ActionInstanceOf; -import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals; -import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater; -import com.jpexs.decompiler.flash.action.swf7.ActionCastOp; -import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; -import com.jpexs.decompiler.flash.action.swf7.ActionExtends; -import com.jpexs.decompiler.flash.action.swf7.ActionImplementsOp; -import com.jpexs.decompiler.flash.action.swf7.ActionThrow; -import com.jpexs.decompiler.flash.action.swf7.ActionTry; +import com.jpexs.decompiler.flash.action.swf3.*; +import com.jpexs.decompiler.flash.action.swf4.*; +import com.jpexs.decompiler.flash.action.swf5.*; +import com.jpexs.decompiler.flash.action.swf6.*; +import com.jpexs.decompiler.flash.action.swf7.*; import com.jpexs.decompiler.flash.amf.amf3.Amf3InputStream; import com.jpexs.decompiler.flash.amf.amf3.Amf3Value; import com.jpexs.decompiler.flash.amf.amf3.NoSerializerExistsException; @@ -125,205 +31,101 @@ import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.dumpview.DumpInfo; import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecial; import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType; -import com.jpexs.decompiler.flash.tags.CSMTextSettingsTag; -import com.jpexs.decompiler.flash.tags.DebugIDTag; -import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsLossless2Tag; -import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; -import com.jpexs.decompiler.flash.tags.DefineBitsTag; -import com.jpexs.decompiler.flash.tags.DefineButton2Tag; -import com.jpexs.decompiler.flash.tags.DefineButtonCxformTag; -import com.jpexs.decompiler.flash.tags.DefineButtonSoundTag; -import com.jpexs.decompiler.flash.tags.DefineButtonTag; -import com.jpexs.decompiler.flash.tags.DefineEditTextTag; -import com.jpexs.decompiler.flash.tags.DefineFont2Tag; -import com.jpexs.decompiler.flash.tags.DefineFont3Tag; -import com.jpexs.decompiler.flash.tags.DefineFont4Tag; -import com.jpexs.decompiler.flash.tags.DefineFontAlignZonesTag; -import com.jpexs.decompiler.flash.tags.DefineFontInfo2Tag; -import com.jpexs.decompiler.flash.tags.DefineFontInfoTag; -import com.jpexs.decompiler.flash.tags.DefineFontNameTag; -import com.jpexs.decompiler.flash.tags.DefineFontTag; -import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag; -import com.jpexs.decompiler.flash.tags.DefineMorphShapeTag; -import com.jpexs.decompiler.flash.tags.DefineScalingGridTag; -import com.jpexs.decompiler.flash.tags.DefineSceneAndFrameLabelDataTag; -import com.jpexs.decompiler.flash.tags.DefineShape2Tag; -import com.jpexs.decompiler.flash.tags.DefineShape3Tag; -import com.jpexs.decompiler.flash.tags.DefineShape4Tag; -import com.jpexs.decompiler.flash.tags.DefineShapeTag; -import com.jpexs.decompiler.flash.tags.DefineSoundTag; -import com.jpexs.decompiler.flash.tags.DefineSpriteTag; -import com.jpexs.decompiler.flash.tags.DefineText2Tag; -import com.jpexs.decompiler.flash.tags.DefineTextTag; -import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; -import com.jpexs.decompiler.flash.tags.DoABC2Tag; -import com.jpexs.decompiler.flash.tags.DoABCTag; -import com.jpexs.decompiler.flash.tags.DoActionTag; -import com.jpexs.decompiler.flash.tags.DoInitActionTag; -import com.jpexs.decompiler.flash.tags.EnableDebugger2Tag; -import com.jpexs.decompiler.flash.tags.EnableDebuggerTag; -import com.jpexs.decompiler.flash.tags.EnableTelemetryTag; -import com.jpexs.decompiler.flash.tags.EndTag; -import com.jpexs.decompiler.flash.tags.ExportAssetsTag; -import com.jpexs.decompiler.flash.tags.FileAttributesTag; -import com.jpexs.decompiler.flash.tags.FrameLabelTag; -import com.jpexs.decompiler.flash.tags.FreeAllTag; -import com.jpexs.decompiler.flash.tags.FreeCharacterTag; -import com.jpexs.decompiler.flash.tags.ImportAssets2Tag; -import com.jpexs.decompiler.flash.tags.ImportAssetsTag; -import com.jpexs.decompiler.flash.tags.JPEGTablesTag; -import com.jpexs.decompiler.flash.tags.MetadataTag; -import com.jpexs.decompiler.flash.tags.NameCharacterTag; -import com.jpexs.decompiler.flash.tags.PathsArePostScriptTag; -import com.jpexs.decompiler.flash.tags.PlaceObject2Tag; -import com.jpexs.decompiler.flash.tags.PlaceObject3Tag; -import com.jpexs.decompiler.flash.tags.PlaceObject4Tag; -import com.jpexs.decompiler.flash.tags.PlaceObjectTag; -import com.jpexs.decompiler.flash.tags.ProductInfoTag; -import com.jpexs.decompiler.flash.tags.ProtectTag; -import com.jpexs.decompiler.flash.tags.RemoveObject2Tag; -import com.jpexs.decompiler.flash.tags.RemoveObjectTag; -import com.jpexs.decompiler.flash.tags.ScriptLimitsTag; -import com.jpexs.decompiler.flash.tags.SetBackgroundColorTag; -import com.jpexs.decompiler.flash.tags.SetTabIndexTag; -import com.jpexs.decompiler.flash.tags.ShowFrameTag; -import com.jpexs.decompiler.flash.tags.SoundStreamBlockTag; -import com.jpexs.decompiler.flash.tags.SoundStreamHead2Tag; -import com.jpexs.decompiler.flash.tags.SoundStreamHeadTag; -import com.jpexs.decompiler.flash.tags.StartSound2Tag; -import com.jpexs.decompiler.flash.tags.StartSoundTag; -import com.jpexs.decompiler.flash.tags.SymbolClassTag; -import com.jpexs.decompiler.flash.tags.SyncFrameTag; -import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.tags.TagStub; -import com.jpexs.decompiler.flash.tags.UnknownTag; -import com.jpexs.decompiler.flash.tags.VideoFrameTag; +import com.jpexs.decompiler.flash.tags.*; import com.jpexs.decompiler.flash.tags.base.ButtonTag; -import com.jpexs.decompiler.flash.tags.gfx.DefineCompactedFont; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalGradient; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalImage2; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalSound; -import com.jpexs.decompiler.flash.tags.gfx.DefineExternalStreamSound; -import com.jpexs.decompiler.flash.tags.gfx.DefineGradientMap; -import com.jpexs.decompiler.flash.tags.gfx.DefineSubImage; -import com.jpexs.decompiler.flash.tags.gfx.ExporterInfo; -import com.jpexs.decompiler.flash.tags.gfx.FontTextureInfo; +import com.jpexs.decompiler.flash.tags.gfx.*; import com.jpexs.decompiler.flash.timeline.Timelined; -import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; -import com.jpexs.decompiler.flash.types.ALPHACOLORMAPDATA; -import com.jpexs.decompiler.flash.types.ARGB; -import com.jpexs.decompiler.flash.types.BITMAPDATA; -import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; -import com.jpexs.decompiler.flash.types.BUTTONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONS; -import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; -import com.jpexs.decompiler.flash.types.COLORMAPDATA; -import com.jpexs.decompiler.flash.types.CXFORM; -import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; -import com.jpexs.decompiler.flash.types.FILLSTYLE; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.FOCALGRADIENT; -import com.jpexs.decompiler.flash.types.GLYPHENTRY; -import com.jpexs.decompiler.flash.types.GRADIENT; -import com.jpexs.decompiler.flash.types.GRADRECORD; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLE2; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.PIX15; -import com.jpexs.decompiler.flash.types.PIX24; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.RGB; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; -import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.TEXTRECORD; -import com.jpexs.decompiler.flash.types.ZONEDATA; -import com.jpexs.decompiler.flash.types.ZONERECORD; -import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.BLURFILTER; -import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; -import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; -import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; -import com.jpexs.decompiler.flash.types.filters.FILTER; -import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; -import com.jpexs.helpers.ByteArrayRange; -import com.jpexs.helpers.FakeMemoryInputStream; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.ImmediateFuture; -import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.ProgressListener; +import com.jpexs.decompiler.flash.types.*; +import com.jpexs.decompiler.flash.types.filters.*; +import com.jpexs.decompiler.flash.types.shaperecords.*; +import com.jpexs.helpers.*; import com.jpexs.helpers.utf8.Utf8Helper; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; + +import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.InflaterInputStream; /** - * Class for reading data from SWF file + * Class for reading data from SWF file. * * @author JPEXS */ public class SWFInputStream implements AutoCloseable { + /** + * Input stream + */ private MemoryInputStream is; + /** + * Starting position in bytes in the stream + */ private long startingPos; + /** + * Logger + */ private static final Logger logger = Logger.getLogger(SWFInputStream.class.getName()); + /** + * Empty byte array + */ public static final byte[] BYTE_ARRAY_EMPTY = new byte[0]; + /** + * Listeners for progress + */ private final List listeners = new ArrayList<>(); + /** + * How much percent is 100% + */ private long percentMax; + /** + * SWF + */ private SWF swf; + /** + * Dump info + */ public DumpInfo dumpInfo; + /** + * Data + */ private byte[] data; + /** + * Maximum limit of reading + */ private int limit; + /** + * Last percent sent to listeners + */ + private int lastPercent = -1; + + /** + * Bit position + */ + private int bitPos = 0; + + /** + * Temporary byte + */ + private int tempByte = 0; + + /** + * Gets charset. + * @return Charset + */ public String getCharset() { if (swf == null) { return Utf8Helper.charsetName; @@ -331,10 +133,18 @@ public class SWFInputStream implements AutoCloseable { return swf.getCharset(); } + /** + * Adds progress listener. + * @param listener Progress listener + */ public void addPercentListener(ProgressListener listener) { listeners.add(listener); } + /** + * Removes progress listener. + * @param listener Progress listener + */ public void removePercentListener(ProgressListener listener) { int index = listeners.indexOf(listener); if (index > -1) { @@ -342,6 +152,9 @@ public class SWFInputStream implements AutoCloseable { } } + /** + * Informs listeners about progress. + */ private void informListeners() { if (listeners.size() > 0 && percentMax > 0) { int percent = (int) (getPos() * 100 / percentMax); @@ -354,17 +167,21 @@ public class SWFInputStream implements AutoCloseable { } } + /** + * Set maximum percent. + * @param percentMax Maximum percent + */ public void setPercentMax(long percentMax) { this.percentMax = percentMax; } /** - * Constructor + * Constructs a new SWFInputStream. * * @param swf SWF to read * @param data SWF data - * @param startingPos - * @param limit + * @param startingPos Starting position in bytes in the stream + * @param limit Maximum limit of reading * @throws java.io.IOException */ public SWFInputStream(SWF swf, byte[] data, long startingPos, int limit) throws IOException { @@ -390,7 +207,7 @@ public class SWFInputStream implements AutoCloseable { * HACK: Special constructor to handle old GFX format - DO NOT USE for * normal purposes - it won't read tags, etc... * - * @param is + * @param is Input stream */ public SWFInputStream(InputStream is) throws IOException { this.swf = null; @@ -400,6 +217,10 @@ public class SWFInputStream implements AutoCloseable { this.is = new FakeMemoryInputStream(is); } + /** + * Gets SWF + * @return SWF + */ public SWF getSwf() { return swf; } @@ -423,10 +244,24 @@ public class SWFInputStream implements AutoCloseable { is.seek(pos - startingPos); } + /** + * Creates new dump level. + * @param name Name + * @param type Type + * @return + */ private DumpInfo newDumpLevel(String name, String type) { return newDumpLevel(name, type, DumpInfoSpecialType.NONE, null); } + /** + * Creates new dump level. + * @param name Name + * @param type Type + * @param specialType Special type + * @param specialValue Special value + * @return + */ private DumpInfo newDumpLevel(String name, String type, DumpInfoSpecialType specialType, Object specialValue) { if (dumpInfo != null) { long startByte = is.getPos(); @@ -444,10 +279,17 @@ public class SWFInputStream implements AutoCloseable { return dumpInfo; } + /** + * Ends dump level. + */ private void endDumpLevel() { endDumpLevel(null); } + /** + * Ends dump level. + * @param value Value + */ private void endDumpLevel(Object value) { if (dumpInfo != null) { if (dumpInfo.startBit == 0 && bitPos == 0) { @@ -460,6 +302,10 @@ public class SWFInputStream implements AutoCloseable { } } + /** + * Ends dump level until. + * @param di Dump info + */ private void endDumpLevelUntil(DumpInfo di) { if (di != null) { while (dumpInfo != null && dumpInfo != di) { @@ -469,7 +315,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one byte from the stream + * Reads one byte from the stream. * * @return byte * @throws IOException @@ -479,12 +325,20 @@ public class SWFInputStream implements AutoCloseable { return readNoBitReset(); } + /** + * Aligns reading on byte. + */ private void alignByte() { bitPos = 0; } - private int lastPercent = -1; + /** + * Reads one byte from the stream. + * @return Byte + * @throws IOException + * @throws EndOfStreamException + */ private int readNoBitReset() throws IOException, EndOfStreamException { int r = is.read(); if (r == -1) { @@ -496,9 +350,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one UI8 (Unsigned 8bit integer) value from the stream + * Reads one UI8 (Unsigned 8bit integer) value from the stream. * - * @param name + * @param name Name * @return UI8 value or -1 on error * @throws IOException */ @@ -510,9 +364,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one null terminated string value from the stream + * Reads one null terminated string value from the stream. * - * @param name + * @param name Name * @return String value * @throws IOException */ @@ -534,9 +388,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one netstring (length + string) value from the stream + * Reads one netstring (length + string) value from the stream. * - * @param name + * @param name Name * @return String value * @throws IOException */ @@ -549,9 +403,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one UI32 (Unsigned 32bit integer) value from the stream + * Reads one UI32 (Unsigned 32bit integer) value from the stream. * - * @param name + * @param name Name * @return UI32 value * @throws IOException */ @@ -563,7 +417,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one UI32 (Unsigned 32bit integer) value from the stream + * Reads one UI32 (Unsigned 32bit integer) value from the stream. * * @return UI32 value * @throws IOException @@ -573,9 +427,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one UI16 (Unsigned 16bit integer) value from the stream + * Reads one UI16 (Unsigned 16bit integer) value from the stream. * - * @param name + * @param name Name * @return UI16 value * @throws IOException */ @@ -587,7 +441,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one UI16 (Unsigned 16bit integer) value from the stream + * Reads one UI16 (Unsigned 16bit integer) value from the stream. * * @return UI16 value * @throws IOException @@ -596,6 +450,12 @@ public class SWFInputStream implements AutoCloseable { return readEx() + (readEx() << 8); } + /** + * Reads one UI24 (Unsigned 24bit integer) value from the stream. + * @param name Name + * @return + * @throws IOException + */ public int readUI24(String name) throws IOException { newDumpLevel(name, "UI24"); int ret = readEx() + (readEx() << 8) + (readEx() << 16); @@ -604,9 +464,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SI32 (Signed 32bit integer) value from the stream + * Reads one SI32 (Signed 32bit integer) value from the stream. * - * @param name + * @param name Name * @return SI32 value * @throws IOException */ @@ -617,6 +477,12 @@ public class SWFInputStream implements AutoCloseable { return uval; } + /** + * Reads one SI32 (Signed 32bit integer) value from the stream. + * + * @return SI32 value + * @throws IOException + */ private long readSI32Internal() throws IOException { long uval = readEx() + (readEx() << 8) + (readEx() << 16) + (readEx() << 24); if (uval >= 0x80000000) { @@ -626,9 +492,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SI16 (Signed 16bit integer) value from the stream + * Reads one SI16 (Signed 16bit integer) value from the stream. * - * @param name + * @param name Name * @return SI16 value * @throws IOException */ @@ -639,6 +505,12 @@ public class SWFInputStream implements AutoCloseable { return uval; } + /** + * Reads one SI16 (Signed 16bit integer) value from the stream. + * + * @return SI16 value + * @throws IOException + */ private int readSI16Internal() throws IOException { int uval = readEx() + (readEx() << 8); if (uval >= 0x8000) { @@ -648,9 +520,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SI8 (Signed 8bit integer) value from the stream + * Reads one SI8 (Signed 8bit integer) value from the stream. * - * @param name + * @param name Name * @return SI8 value * @throws IOException */ @@ -662,7 +534,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SI8 (Signed 8bit integer) value from the stream + * Reads one SI8 (Signed 8bit integer) value from the stream. * * @return SI8 value * @throws IOException @@ -676,9 +548,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FIXED (Fixed point 16.16) value from the stream + * Reads one FIXED (Fixed point 16.16) value from the stream. * - * @param name + * @param name Name * @return FIXED value * @throws IOException */ @@ -691,9 +563,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FIXED8 (Fixed point 8.8) signed value from the stream + * Reads one FIXED8 (Fixed point 8.8) signed value from the stream. * - * @param name + * @param name Name * @return FIXED8 value * @throws IOException */ @@ -705,6 +577,11 @@ public class SWFInputStream implements AutoCloseable { return ret; } + /** + * Reads long value from the stream. + * @return Long value + * @throws IOException + */ private long readLong() throws IOException { byte[] readBuffer = readBytesInternalEx(8); return (((long) readBuffer[3] << 56) @@ -719,9 +596,9 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one DOUBLE (double precision floating point value) value from the - * stream + * stream. * - * @param name + * @param name Name * @return DOUBLE value * @throws IOException */ @@ -735,9 +612,9 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one FLOAT (single precision floating point value) value from the - * stream + * stream. * - * @param name + * @param name Name * @return FLOAT value * @throws IOException */ @@ -754,9 +631,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FLOAT16 (16bit floating point value) value from the stream + * Reads one FLOAT16 (16bit floating point value) value from the stream. * - * @param name + * @param name Name * @return FLOAT16 value * @throws IOException */ @@ -772,10 +649,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads bytes from the stream + * Reads bytes from the stream. * * @param count Number of bytes to read - * @param name + * @param name Name * @return Array of read bytes * @throws IOException */ @@ -791,10 +668,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads AMF3 encoded value from the stream + * Reads AMF3 encoded value from the stream. * - * @param name - * @return + * @param name Name + * @return AMF3 value * @throws IOException */ public Amf3Value readAmf3Object(String name) throws IOException, NoSerializerExistsException { @@ -805,10 +682,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads byte range from the stream + * Reads byte range from the stream. * * @param count Number of bytes to read - * @param name + * @param name Name * @return ByteArrayRange object * @throws IOException */ @@ -817,12 +694,12 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads byte range from the stream + * Reads byte range from the stream. * * @param count Number of bytes to read - * @param name - * @param specialType - * @param specialValue + * @param name Name + * @param specialType Special type + * @param specialValue Special value * @return ByteArrayRange object * @throws IOException */ @@ -843,7 +720,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads bytes from the stream + * Reads bytes from the stream. * * @param count Number of bytes to read * @return Array of read bytes @@ -865,7 +742,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Skip bytes from the stream + * Skip bytes from the stream. * * @param count Number of bytes to skip * @throws IOException @@ -885,10 +762,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Skip bytes from the stream + * Skip bytes from the stream. * * @param count Number of bytes to skip - * @param name + * @param name Name * @throws IOException */ public void skipBytesEx(long count, String name) throws IOException { @@ -902,7 +779,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Skip bytes from the stream + * Skip bytes from the stream. * * @param count Number of bytes to skip * @throws IOException @@ -916,10 +793,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads bytes from the stream + * Reads bytes from the stream. * * @param count Number of bytes to read - * @param name + * @param name Name * @return Array of read bytes * @throws IOException */ @@ -942,6 +819,13 @@ public class SWFInputStream implements AutoCloseable { return ret; } + /** + * Reads ZLIB compressed bytes from the stream. + * @param count Number of bytes to read + * @param name Name + * @return + * @throws IOException + */ public byte[] readBytesZlib(long count, String name) throws IOException { if (count == 0) { return BYTE_ARRAY_EMPTY; @@ -953,10 +837,24 @@ public class SWFInputStream implements AutoCloseable { return uncompressByteArray(data); } + /** + * Uncompresses byte array. + * @param data Data + * @return Uncompressed data + * @throws IOException + */ public static byte[] uncompressByteArray(byte[] data) throws IOException { return uncompressByteArray(data, 0, data.length); } + /** + * Uncompresses byte array. + * @param data Data + * @param offset Offset + * @param length Length + * @return Uncompressed data + * @throws IOException + */ public static byte[] uncompressByteArray(byte[] data, int offset, int length) throws IOException { InflaterInputStream dis = new InflaterInputStream(new ByteArrayInputStream(data, offset, length)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -969,9 +867,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one EncodedU32 (Encoded unsigned 32bit value) value from the stream + * Reads one EncodedU32 (Encoded unsigned 32bit value) value from the stream. * - * @param name + * @param name Name * @return U32 value * @throws IOException */ @@ -1002,15 +900,13 @@ public class SWFInputStream implements AutoCloseable { return result; } - private int bitPos = 0; - private int tempByte = 0; /** - * Reads UB[nBits] (Unsigned-bit value) value from the stream + * Reads UB[nBits] (Unsigned-bit value) value from the stream. * * @param nBits Number of bits which represent value - * @param name + * @param name Name * @return Unsigned value * @throws IOException */ @@ -1025,7 +921,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads UB[nBits] (Unsigned-bit value) value from the stream + * Reads UB[nBits] (Unsigned-bit value) value from the stream. * * @param nBits Number of bits which represent value * @return Unsigned value @@ -1054,10 +950,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads SB[nBits] (Signed-bit value) value from the stream + * Reads SB[nBits] (Signed-bit value) value from the stream. * * @param nBits Number of bits which represent value - * @param name + * @param name Name * @return Signed value * @throws IOException */ @@ -1072,7 +968,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads SB[nBits] (Signed-bit value) value from the stream + * Reads SB[nBits] (Signed-bit value) value from the stream. * * @param nBits Number of bits which represent value * @return Signed value @@ -1088,10 +984,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads FB[nBits] (Signed fixed-point bit value) value from the stream + * Reads FB[nBits] (Signed fixed-point bit value) value from the stream. * * @param nBits Number of bits which represent value - * @param name + * @param name Name * @return Fixed-point value * @throws IOException */ @@ -1107,9 +1003,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one RECT value from the stream + * Reads one RECT value from the stream. * - * @param name + * @param name Name * @return RECT value * @throws IOException */ @@ -1127,6 +1023,13 @@ public class SWFInputStream implements AutoCloseable { return ret; } + /** + * Dumps tag. + * @param out Output stream + * @param tag Tag + * @param index Index + * @param level Level + */ private static void dumpTag(PrintStream out, Tag tag, int index, int level) { StringBuilder sb = new StringBuilder(); sb.append(Helper.formatHex((int) tag.getPos(), 8)); @@ -1151,24 +1054,57 @@ public class SWFInputStream implements AutoCloseable { } } + /** + * Close the stream. + */ @Override public void close() { } + /** + * Tag resolution task. + */ private class TagResolutionTask implements Callable { + /** + * Tag stub + */ private final TagStub tag; + /** + * Dump info + */ private final DumpInfo dumpInfo; + /** + * Level + */ private final int level; + /** + * Parallel + */ private final boolean parallel; + /** + * Skip unusual tags + */ private final boolean skipUnusualTags; + /** + * Lazy loading + */ private final boolean lazy; + /** + * Constructs a new TagResolutionTask. + * @param tag Tag stub + * @param dumpInfo Dump info + * @param level Level + * @param parallel Parallel + * @param skipUnusualTags Skip unusual tags + * @param lazy Lazy loading + */ public TagResolutionTask(TagStub tag, DumpInfo dumpInfo, int level, boolean parallel, boolean skipUnusualTags, boolean lazy) { this.tag = tag; this.dumpInfo = dumpInfo; @@ -1178,6 +1114,11 @@ public class SWFInputStream implements AutoCloseable { this.lazy = lazy; } + /** + * Call. + * @return Tag + * @throws Exception + */ @Override public Tag call() throws Exception { DumpInfo di = dumpInfo; @@ -1197,14 +1138,14 @@ public class SWFInputStream implements AutoCloseable { /** * Reads list of tags from the stream. Reading ends with End tag(=0) or end - * of the stream. Optionally can skip AS1/2 tags when file is AS3 + * of the stream. Optionally can skip AS1/2 tags when file is AS3. * - * @param timelined - * @param level - * @param parallel - * @param skipUnusualTags - * @param parseTags - * @param lazy + * @param timelined Timelined object + * @param level Level + * @param parallel Parallel + * @param skipUnusualTags Skip unusual tags + * @param parseTags Parse tags + * @param lazy Lazy loading * @return List of tags * @throws IOException * @throws java.lang.InterruptedException @@ -1296,6 +1237,17 @@ public class SWFInputStream implements AutoCloseable { return tags; } + /** + * Resolves tag. + * @param tag Tag stub + * @param level Level + * @param parallel Parallel + * @param skipUnusualTags Skip unusual tags + * @param lazy Lazy loading + * @param logErrors Log errors + * @return Tag + * @throws InterruptedException + */ public static Tag resolveTag(TagStub tag, int level, boolean parallel, boolean skipUnusualTags, boolean lazy, boolean logErrors) throws InterruptedException { Tag ret; @@ -1604,15 +1556,15 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one Tag from the stream with optional resolving (= reading tag - * content) + * content). * - * @param timelined - * @param level - * @param pos - * @param resolve - * @param parallel - * @param skipUnusualTags - * @param lazy + * @param timelined Timelined object + * @param level Level + * @param pos Position + * @param resolve Resolve tag + * @param parallel Parallel + * @param skipUnusualTags Skip unusual tags + * @param lazy Lazy loading * @return Tag or null when End tag * @throws IOException * @throws java.lang.InterruptedException @@ -1698,7 +1650,7 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one Action from the stream + * Reads one Action from the stream. * * @return Action or null when ActionEndFlag or end of the stream * @throws IOException @@ -1939,9 +1891,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MATRIX value from the stream + * Reads one MATRIX value from the stream. * - * @param name + * @param name Name * @return MATRIX value * @throws IOException */ @@ -1972,9 +1924,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CXFORMWITHALPHA value from the stream + * Reads one CXFORMWITHALPHA value from the stream. * - * @param name + * @param name Name * @return CXFORMWITHALPHA value * @throws IOException */ @@ -2003,9 +1955,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CXFORM value from the stream + * Reads one CXFORM value from the stream. * - * @param name + * @param name Name * @return CXFORM value * @throws IOException */ @@ -2032,9 +1984,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CLIPEVENTFLAGS value from the stream + * Reads one CLIPEVENTFLAGS value from the stream. * - * @param name + * @param name Name * @return CLIPEVENTFLAGS value * @throws IOException */ @@ -2069,11 +2021,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CLIPACTIONRECORD value from the stream + * Reads one CLIPACTIONRECORD value from the stream. * - * @param swf - * @param tag - * @param name + * @param swf SWF + * @param tag Tag + * @param name Name * @param parentClipActions * @return CLIPACTIONRECORD value * @throws IOException @@ -2089,11 +2041,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CLIPACTIONS value from the stream + * Reads one CLIPACTIONS value from the stream. * - * @param swf - * @param tag - * @param name + * @param swf SWF + * @param tag Tag + * @param name Name * @return CLIPACTIONS value * @throws IOException */ @@ -2112,9 +2064,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one COLORMATRIXFILTER value from the stream + * Reads one COLORMATRIXFILTER value from the stream. * - * @param name + * @param name Name * @return COLORMATRIXFILTER value * @throws IOException */ @@ -2130,9 +2082,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one RGBA value from the stream + * Reads one RGBA value from the stream. * - * @param name + * @param name Name * @return RGBA value * @throws IOException */ @@ -2148,9 +2100,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one RGBA value from the stream + * Reads one RGBA value from the stream. * - * @param name + * @param name Name * @return RGBA value * @throws IOException */ @@ -2165,9 +2117,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one ARGB value from the stream + * Reads one ARGB value from the stream. * - * @param name + * @param name Name * @return ARGB value * @throws IOException */ @@ -2183,9 +2135,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one ARGB value from the stream + * Reads one ARGB value from the stream. * - * @param name + * @param name Name * @return ARGB value * @throws IOException */ @@ -2200,9 +2152,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one RGB value from the stream + * Reads one RGB value from the stream. * - * @param name + * @param name Name * @return RGB value * @throws IOException */ @@ -2217,9 +2169,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one RGB value from the stream + * Reads one RGB value from the stream. * - * @param name + * @param name Name * @return RGB value * @throws IOException */ @@ -2234,9 +2186,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one CONVOLUTIONFILTER value from the stream + * Reads one CONVOLUTIONFILTER value from the stream. * - * @param name + * @param name Name * @return CONVOLUTIONFILTER value * @throws IOException */ @@ -2260,9 +2212,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one BLURFILTER value from the stream + * Reads one BLURFILTER value from the stream. * - * @param name + * @param name Name * @return BLURFILTER value * @throws IOException */ @@ -2278,9 +2230,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one DROPSHADOWFILTER value from the stream + * Reads one DROPSHADOWFILTER value from the stream. * - * @param name + * @param name Name * @return DROPSHADOWFILTER value * @throws IOException */ @@ -2302,9 +2254,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GLOWFILTER value from the stream + * Reads one GLOWFILTER value from the stream. * - * @param name + * @param name Name * @return GLOWFILTER value * @throws IOException */ @@ -2324,9 +2276,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one BEVELFILTER value from the stream + * Reads one BEVELFILTER value from the stream. * - * @param name + * @param name Name * @return BEVELFILTER value * @throws IOException */ @@ -2350,9 +2302,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GRADIENTGLOWFILTER value from the stream + * Reads one GRADIENTGLOWFILTER value from the stream. * - * @param name + * @param name Name * @return GRADIENTGLOWFILTER value * @throws IOException */ @@ -2383,9 +2335,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GRADIENTBEVELFILTER value from the stream + * Reads one GRADIENTBEVELFILTER value from the stream. * - * @param name + * @param name Name * @return GRADIENTBEVELFILTER value * @throws IOException */ @@ -2416,9 +2368,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads list of FILTER values from the stream + * Reads list of FILTER values from the stream. * - * @param name + * @param name Name * @return List of FILTER values * @throws IOException */ @@ -2434,9 +2386,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FILTER value from the stream + * Reads one FILTER value from the stream. * - * @param name + * @param name Name * @return FILTER value * @throws IOException */ @@ -2475,11 +2427,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads list of BUTTONRECORD values from the stream + * Reads list of BUTTONRECORD values from the stream. * - * @param swf - * @param buttonTag - * @param name + * @param swf SWF + * @param buttonTag ButtonTag + * @param name Name * @return List of BUTTONRECORD values * @throws IOException */ @@ -2495,11 +2447,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one BUTTONRECORD value from the stream + * Reads one BUTTONRECORD value from the stream. * - * @param swf - * @param tag - * @param name + * @param swf SWF + * @param tag ButtonTag + * @param name Name * @return BUTTONRECORD value * @throws IOException */ @@ -2538,11 +2490,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads list of BUTTONCONDACTION values from the stream + * Reads list of BUTTONCONDACTION values from the stream. * - * @param swf - * @param tag - * @param name + * @param swf SWF + * @param tag Tag + * @param name Name * @return List of BUTTONCONDACTION values * @throws IOException */ @@ -2559,11 +2511,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one BUTTONCONDACTION value from the stream + * Reads one BUTTONCONDACTION value from the stream. * - * @param swf - * @param tag - * @param name + * @param swf SWF + * @param tag Tag + * @param name Name * @return BUTTONCONDACTION value * @throws IOException */ @@ -2576,10 +2528,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GRADRECORD value from the stream + * Reads one GRADRECORD value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return GRADRECORD value * @throws IOException */ @@ -2598,10 +2550,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GRADIENT value from the stream + * Reads one GRADIENT value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return GRADIENT value * @throws IOException */ @@ -2621,10 +2573,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FOCALGRADIENT value from the stream + * Reads one FOCALGRADIENT value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return FOCALGRADIENT value * @throws IOException */ @@ -2644,10 +2596,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FILLSTYLE value from the stream + * Reads one FILLSTYLE value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return FILLSTYLE value * @throws IOException */ @@ -2688,10 +2640,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one FILLSTYLEARRAY value from the stream + * Reads one FILLSTYLEARRAY value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return FILLSTYLEARRAY value * @throws IOException */ @@ -2712,10 +2664,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one LINESTYLE value from the stream + * Reads one LINESTYLE value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return LINESTYLE value * @throws IOException */ @@ -2733,10 +2685,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one LINESTYLE2 value from the stream + * Reads one LINESTYLE2 value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return LINESTYLE2 value * @throws IOException */ @@ -2766,10 +2718,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one LINESTYLEARRAY value from the stream + * Reads one LINESTYLEARRAY value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param name + * @param name Name * @return LINESTYLEARRAY value * @throws IOException */ @@ -2796,10 +2748,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SHAPERECORD value from the stream + * Reads one SHAPERECORD value from the stream. * - * @param fillBits - * @param lineBits + * @param fillBits Fill bits + * @param lineBits Line bits * @param shapeNum 1 in DefineShape, 2 in DefineShape2... * @return SHAPERECORD value * @throws IOException @@ -2881,11 +2833,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SHAPE value from the stream + * Reads one SHAPE value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param morphShape - * @param name + * @param morphShape Is this a morph shape + * @param name Name * @return SHAPE value * @throws IOException */ @@ -2900,11 +2852,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SHAPEWITHSTYLE value from the stream + * Reads one SHAPEWITHSTYLE value from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param morphShape - * @param name + * @param morphShape Is this a morph shape + * @param name Name * @return SHAPEWITHSTYLE value * @throws IOException */ @@ -2921,11 +2873,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads list of SHAPERECORDs from the stream + * Reads list of SHAPERECORDs from the stream. * * @param shapeNum 1 in DefineShape, 2 in DefineShape2... - * @param fillBits - * @param lineBits + * @param fillBits Fill bits + * @param lineBits Line bits * @return SHAPERECORDs array * @throws IOException */ @@ -2950,9 +2902,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SOUNDINFO value from the stream + * Reads one SOUNDINFO value from the stream. * - * @param name + * @param name Name * @return SOUNDINFO value * @throws IOException */ @@ -2987,9 +2939,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one SOUNDENVELOPE value from the stream + * Reads one SOUNDENVELOPE value from the stream. * - * @param name + * @param name Name * @return SOUNDENVELOPE value * @throws IOException */ @@ -3004,11 +2956,11 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one GLYPHENTRY value from the stream + * Reads one GLYPHENTRY value from the stream. * - * @param glyphBits - * @param advanceBits - * @param name + * @param glyphBits Glyph bits + * @param advanceBits Advance bits + * @param name Name * @return GLYPHENTRY value * @throws IOException */ @@ -3022,12 +2974,12 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one TEXTRECORD value from the stream + * Reads one TEXTRECORD value from the stream. * - * @param defineTextNum - * @param glyphBits - * @param advanceBits - * @param name + * @param defineTextNum 1 in DefineText, 2 in DefineText2... + * @param glyphBits Glyph bits + * @param advanceBits Advance bits + * @param name Name * @return TEXTRECORD value * @throws IOException */ @@ -3074,9 +3026,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHGRADRECORD value from the stream + * Reads one MORPHGRADRECORD value from the stream. * - * @param name + * @param name Name * @return MORPHGRADRECORD value * @throws IOException */ @@ -3092,9 +3044,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHGRADIENT value from the stream + * Reads one MORPHGRADIENT value from the stream. * - * @param name + * @param name Name * @return MORPHGRADIENT value * @throws IOException */ @@ -3120,7 +3072,7 @@ public class SWFInputStream implements AutoCloseable { *

* This is undocumented feature * - * @param name + * @param name Name * @return MORPHGRADIENT value * @throws IOException */ @@ -3141,9 +3093,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHFILLSTYLE value from the stream + * Reads one MORPHFILLSTYLE value from the stream. * - * @param name + * @param name Name * @return MORPHFILLSTYLE value * @throws IOException */ @@ -3182,9 +3134,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHFILLSTYLEARRAY value from the stream + * Reads one MORPHFILLSTYLEARRAY value from the stream. * - * @param name + * @param name Name * @return MORPHFILLSTYLEARRAY value * @throws IOException */ @@ -3205,9 +3157,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHLINESTYLE value from the stream + * Reads one MORPHLINESTYLE value from the stream. * - * @param name + * @param name Name * @return MORPHLINESTYLE value * @throws IOException */ @@ -3223,9 +3175,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHLINESTYLE2 value from the stream + * Reads one MORPHLINESTYLE2 value from the stream. * - * @param name + * @param name Name * @return MORPHLINESTYLE2 value * @throws IOException */ @@ -3257,10 +3209,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one MORPHLINESTYLEARRAY value from the stream + * Reads one MORPHLINESTYLEARRAY value from the stream. * * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape2 - * @param name + * @param name Name * @return MORPHLINESTYLEARRAY value * @throws IOException */ @@ -3287,10 +3239,10 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one KERNINGRECORD value from the stream + * Reads one KERNINGRECORD value from the stream. * - * @param fontFlagsWideCodes - * @param name + * @param fontFlagsWideCodes Font flags wide codes + * @param name Name * @return KERNINGRECORD value * @throws IOException */ @@ -3310,9 +3262,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one LANGCODE value from the stream + * Reads one LANGCODE value from the stream. * - * @param name + * @param name Name * @return LANGCODE value * @throws IOException */ @@ -3325,9 +3277,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one ZONERECORD value from the stream + * Reads one ZONERECORD value from the stream. * - * @param name + * @param name Name * @return ZONERECORD value * @throws IOException */ @@ -3347,9 +3299,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one ZONEDATA value from the stream + * Reads one ZONEDATA value from the stream. * - * @param name + * @param name Name * @return ZONEDATA value * @throws IOException */ @@ -3363,9 +3315,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one PIX15 value from the stream + * Reads one PIX15 value from the stream. * - * @param name + * @param name Name * @return PIX15 value * @throws IOException */ @@ -3381,9 +3333,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one PIX15 value from the stream + * Reads one PIX15 value from the stream. * - * @param name + * @param name Name * @return PIX15 value * @throws IOException */ @@ -3398,9 +3350,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one PIX24 value from the stream + * Reads one PIX24 value from the stream. * - * @param name + * @param name Name * @return PIX24 value * @throws IOException */ @@ -3416,9 +3368,9 @@ public class SWFInputStream implements AutoCloseable { } /** - * Reads one PIX24 value from the stream + * Reads one PIX24 value from the stream. * - * @param name + * @param name Name * @return PIX24 value * @throws IOException */ @@ -3435,10 +3387,10 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one COLORMAPDATA value from the stream * - * @param colorTableSize - * @param bitmapWidth - * @param bitmapHeight - * @param name + * @param colorTableSize Color table size + * @param bitmapWidth Bitmap width + * @param bitmapHeight Bitmap height + * @param name Name * @return COLORMAPDATA value * @throws IOException */ @@ -3470,10 +3422,10 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one BITMAPDATA value from the stream * - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @param name + * @param bitmapFormat Bitmap format + * @param bitmapWidth Bitmap width + * @param bitmapHeight Bitmap height + * @param name Name * @return COLORMAPDATA value * @throws IOException */ @@ -3514,10 +3466,10 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one BITMAPDATA value from the stream * - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight - * @param name + * @param bitmapFormat Bitmap format + * @param bitmapWidth Bitmap width + * @param bitmapHeight Bitmap height + * @param name Name * @return COLORMAPDATA value * @throws IOException */ @@ -3537,10 +3489,10 @@ public class SWFInputStream implements AutoCloseable { /** * Reads one ALPHACOLORMAPDATA value from the stream * - * @param colorTableSize - * @param bitmapWidth - * @param bitmapHeight - * @param name + * @param colorTableSize Color table size + * @param bitmapWidth Bitmap width + * @param bitmapHeight Bitmap height + * @param name Name * @return ALPHACOLORMAPDATA value * @throws IOException */ @@ -3569,10 +3521,20 @@ public class SWFInputStream implements AutoCloseable { return ret; } + /** + * Gets number of available bytes in the stream. + * @return Number of available bytes + * @throws IOException + */ public int available() throws IOException { return is.available(); } + /** + * Gets number of available bits in the stream. + * @return Number of available bits + * @throws IOException + */ public long availableBits() throws IOException { if (bitPos > 0) { return available() * 8 + (8 - bitPos); @@ -3580,6 +3542,11 @@ public class SWFInputStream implements AutoCloseable { return available() * 8; } + /** + * Gets base stream. + * @return Base stream + * @throws IOException + */ public MemoryInputStream getBaseStream() throws IOException { int pos = (int) is.getPos(); MemoryInputStream mis = new MemoryInputStream(is.getAllRead(), 0, pos + is.available()); @@ -3587,6 +3554,12 @@ public class SWFInputStream implements AutoCloseable { return mis; } + /** + * Gets limited stream. + * @param limit Limit + * @return Limited stream + * @throws IOException + */ public SWFInputStream getLimitedStream(int limit) throws IOException { SWFInputStream sis = new SWFInputStream(swf, is.getAllRead(), startingPos, (int) (is.getPos() + limit)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java index 2ba956dbd..334280e90 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java @@ -23,64 +23,12 @@ import com.jpexs.decompiler.flash.amf.amf3.ObjectTypeSerializeHandler; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.tags.DefineBitsLosslessTag; import com.jpexs.decompiler.flash.tags.Tag; -import com.jpexs.decompiler.flash.types.ALPHABITMAPDATA; -import com.jpexs.decompiler.flash.types.ARGB; -import com.jpexs.decompiler.flash.types.BITMAPDATA; -import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; -import com.jpexs.decompiler.flash.types.BUTTONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; -import com.jpexs.decompiler.flash.types.CLIPACTIONS; -import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; -import com.jpexs.decompiler.flash.types.CXFORM; -import com.jpexs.decompiler.flash.types.CXFORMWITHALPHA; -import com.jpexs.decompiler.flash.types.FILLSTYLE; -import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.FOCALGRADIENT; -import com.jpexs.decompiler.flash.types.GLYPHENTRY; -import com.jpexs.decompiler.flash.types.GRADIENT; -import com.jpexs.decompiler.flash.types.GRADRECORD; -import com.jpexs.decompiler.flash.types.KERNINGRECORD; -import com.jpexs.decompiler.flash.types.LANGCODE; -import com.jpexs.decompiler.flash.types.LINESTYLE; -import com.jpexs.decompiler.flash.types.LINESTYLE2; -import com.jpexs.decompiler.flash.types.LINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.MATRIX; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE; -import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY; -import com.jpexs.decompiler.flash.types.MORPHFOCALGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADIENT; -import com.jpexs.decompiler.flash.types.MORPHGRADRECORD; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2; -import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY; -import com.jpexs.decompiler.flash.types.PIX15; -import com.jpexs.decompiler.flash.types.PIX24; -import com.jpexs.decompiler.flash.types.RECT; -import com.jpexs.decompiler.flash.types.RGB; -import com.jpexs.decompiler.flash.types.RGBA; -import com.jpexs.decompiler.flash.types.SHAPE; -import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; -import com.jpexs.decompiler.flash.types.SOUNDENVELOPE; -import com.jpexs.decompiler.flash.types.SOUNDINFO; -import com.jpexs.decompiler.flash.types.TEXTRECORD; -import com.jpexs.decompiler.flash.types.ZONEDATA; -import com.jpexs.decompiler.flash.types.ZONERECORD; -import com.jpexs.decompiler.flash.types.filters.BEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.BLURFILTER; -import com.jpexs.decompiler.flash.types.filters.COLORMATRIXFILTER; -import com.jpexs.decompiler.flash.types.filters.CONVOLUTIONFILTER; -import com.jpexs.decompiler.flash.types.filters.DROPSHADOWFILTER; -import com.jpexs.decompiler.flash.types.filters.FILTER; -import com.jpexs.decompiler.flash.types.filters.GLOWFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTBEVELFILTER; -import com.jpexs.decompiler.flash.types.filters.GRADIENTGLOWFILTER; -import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; -import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord; -import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord; +import com.jpexs.decompiler.flash.types.*; +import com.jpexs.decompiler.flash.types.filters.*; +import com.jpexs.decompiler.flash.types.shaperecords.*; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.utf8.Utf8Helper; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -91,30 +39,52 @@ import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; /** - * Class for writing data into SWF file + * Class for writing data into SWF file. * * @author JPEXS */ public class SWFOutputStream extends OutputStream { + /** + * Output stream + */ private final OutputStream os; + /** + * SWF version + */ private final int version; + /** + * Current position in the stream + */ private long pos = 0; + /** + * Current bit position in the stream + */ private int bitPos = 0; + /** + * Temporary byte for writing bits + */ private int tempByte = 0; + /** + * Charset for writing strings. (SWF version 5 and lower is not using UTF-8) + */ private String charset; + /** + * Gets current position in the stream. + * @return Current position in the stream + */ public long getPos() { return pos; } /** - * Constructor + * Constructs new SWFOutputStream. * * @param os OutputStream for writing data * @param version Version of SWF @@ -126,9 +96,9 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes byte to the stream + * Writes byte to the stream. * - * @param b byte to write + * @param b Byte to write * @throws IOException */ @Override @@ -138,6 +108,11 @@ public class SWFOutputStream extends OutputStream { pos++; } + /** + * Writes byte array to the stream. + * @param b The data. + * @throws IOException + */ @Override public void write(byte[] b) throws IOException { alignByte(); @@ -145,6 +120,13 @@ public class SWFOutputStream extends OutputStream { pos += b.length; } + /** + * Writes byte array to the stream. + * @param b The data. + * @param off The start offset in the data. + * @param len The number of bytes to write. + * @throws IOException + */ @Override public void write(byte[] b, int off, int len) throws IOException { alignByte(); @@ -152,12 +134,21 @@ public class SWFOutputStream extends OutputStream { pos += len; } + /** + * Writes ByteArrayRange to the stream. + * @param b The data. + * @throws IOException + */ public void write(ByteArrayRange b) throws IOException { alignByte(); os.write(b.getArray(), b.getPos(), b.getLength()); pos += b.getLength(); } + /** + * Aligns to byte position. + * @throws IOException + */ private void alignByte() throws IOException { if (bitPos > 0) { bitPos = 0; @@ -167,7 +158,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes UI8 (Unsigned 8bit integer) value to the stream + * Writes UI8 (Unsigned 8bit integer) value to the stream. * * @param value UI8 value to write * @throws IOException @@ -181,7 +172,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes null terminated string value to the stream + * Writes null terminated string value to the stream. * * @param value String value * @throws IOException @@ -204,7 +195,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes netstring (length + string) value to the stream + * Writes netstring (length + string) value to the stream. * * @param value String value * @throws IOException @@ -216,7 +207,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes UI32 (Unsigned 32bit integer) value to the stream + * Writes UI32 (Unsigned 32bit integer) value to the stream. * * @param value UI32 value * @throws IOException @@ -233,7 +224,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes UI16 (Unsigned 16bit integer) value to the stream + * Writes UI16 (Unsigned 16bit integer) value to the stream. * * @param value UI16 value * @throws IOException @@ -248,7 +239,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SI32 (Signed 32bit integer) value to the stream + * Writes SI32 (Signed 32bit integer) value to the stream. * * @param value SI32 value * @throws IOException @@ -262,7 +253,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SI16 (Signed 16bit integer) value to the stream + * Writes SI16 (Signed 16bit integer) value to the stream. * * @param value SI16 value * @throws IOException @@ -277,7 +268,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SI8 (Signed 8bit integer) value to the stream + * Writes SI8 (Signed 8bit integer) value to the stream. * * @param value SI8 value * @throws IOException @@ -291,7 +282,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FIXED (Fixed point 16.16) value to the stream + * Writes FIXED (Fixed point 16.16) value to the stream. * * @param value FIXED value * @throws IOException @@ -302,7 +293,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FIXED8 (Fixed point 8.8) value to the stream + * Writes FIXED8 (Fixed point 8.8) value to the stream. * * @param value FIXED8 value * @throws IOException @@ -312,6 +303,11 @@ public class SWFOutputStream extends OutputStream { writeSI16(valueInt); } + /** + * Writes long value to the stream. + * @param value The value. + * @throws IOException + */ private void writeLong(long value) throws IOException { byte[] writeBuffer = new byte[8]; writeBuffer[3] = (byte) (value >>> 56); @@ -326,7 +322,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes DOUBLE (double precision floating point value) value to the stream + * Writes DOUBLE (double precision floating point value) value to the stream. * * @param value DOUBLE value * @throws IOException @@ -336,7 +332,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FLOAT (single precision floating point value) value to the stream + * Writes FLOAT (single precision floating point value) value to the stream. * * @param value FLOAT value * @throws IOException @@ -346,7 +342,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FLOAT16 (16bit floating point value) value to the stream + * Writes FLOAT16 (16bit floating point value) value to the stream. * * @param value FLOAT16 value * @throws IOException @@ -361,7 +357,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes EncodedU32 (Encoded unsigned 32bit value) value to the stream + * Writes EncodedU32 (Encoded unsigned 32bit value) value to the stream. * * @param value U32 value * @throws IOException @@ -383,7 +379,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Flushes data to underlying stream + * Flushes data to underlying stream. * * @throws IOException */ @@ -398,7 +394,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Closes the stream + * Closes the stream. * * @throws IOException */ @@ -409,7 +405,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes UB[nBits] (Unsigned-bit value) value to the stream + * Writes UB[nBits] (Unsigned-bit value) value to the stream. * * @param nBits Number of bits which represent value * @param value Unsigned value to write @@ -422,18 +418,37 @@ public class SWFOutputStream extends OutputStream { writeNBInternal(nBits, value, "UB"); } + /** + * Checks if value fits in SB[nBits] (Signed-bit value). + * @param nBits Number of bits + * @param value Value + * @return True if value fits in SB[nBits] + */ public static boolean fitsInSB(int nBits, long value) { long min = -1L << (nBits - 1); long max = (1L << (nBits - 1)) - 1; return value >= min && value <= max; } + /** + * Checks if value fits in UB[nBits] (Unsigned-bit value). + * @param nBits Number of bits + * @param value Value + * @return True if value fits in UB[nBits] + */ public static boolean fitsInUB(int nBits, long value) { long min = 0; long max = (1L << nBits) - 1; return value >= min && value <= max; } + /** + * Writes NB[nBits] (Bit value) value to the stream. + * @param nBits Number of bits which represent value + * @param value Value to write + * @param type Type of value + * @throws IOException + */ private void writeNBInternal(int nBits, long value, String type) throws IOException { for (int bit = 0; bit < nBits; bit++) { int nb = (int) ((value >> (nBits - 1 - bit)) & 1); @@ -448,7 +463,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SB[nBits] (Signed-bit value) value to the stream + * Writes SB[nBits] (Signed-bit value) value to the stream. * * @param nBits Number of bits which represent value * @param value Signed value to write @@ -462,7 +477,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FB[nBits] (Signed fixed-point bit value) value to the stream + * Writes FB[nBits] (Signed fixed-point bit value) value to the stream. * * @param nBits Number of bits which represent value * @param value Double value to write @@ -477,7 +492,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes RECT value to the stream + * Writes RECT value to the stream. * * @param value RECT value * @throws IOException @@ -510,6 +525,11 @@ public class SWFOutputStream extends OutputStream { alignByte(); } + /** + * Truncates value to 31 bits. + * @param value Value + * @return Truncated value + */ private int truncateTo31Bit(int value) { if (value > 0x3fffffff) { value = 0x3fffffff; @@ -521,7 +541,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes list of Tag values to the stream + * Writes list of Tag values to the stream. * * @param tags List of tag values * @throws IOException @@ -533,7 +553,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Calculates number of bits needed for representing signed value + * Calculates number of bits needed for representing signed value. * * @param v Signed value * @return Number of bits @@ -550,7 +570,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Calculates number of bits needed for representing signed values + * Calculates number of bits needed for representing signed values. * * @param first First Signed value * @param params Next Signed values @@ -566,7 +586,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Calculates number of bits needed for representing unsigned value + * Calculates number of bits needed for representing unsigned value. * * @param value Unsigned value * @return Number of bits @@ -589,6 +609,12 @@ public class SWFOutputStream extends OutputStream { return nBits; } + /** + * Calculates number of bits needed for representing unsigned values. + * @param first First Unsigned value + * @param params Next Unsigned values + * @return Number of bits + */ public static int getNeededBitsU(int first, int... params) { int nBits = 0; nBits = enlargeBitCountU(nBits, first); @@ -598,6 +624,11 @@ public class SWFOutputStream extends OutputStream { return nBits; } + /** + * Calculates number of bits needed for representing unsigned value. + * @param value Unsigned value + * @return Number of bits + */ public static int unsignedSize(final int value) { final int val = (value < 0) ? -value - 1 : value; @@ -612,7 +643,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Calculates number of bits needed for representing fixed-point value + * Calculates number of bits needed for representing fixed-point value. * * @param value Fixed-point value * @return Number of bits @@ -625,6 +656,12 @@ public class SWFOutputStream extends OutputStream { return getNeededBitsS(k) + 16; } + /** + * Enlarges bit count for signed values. + * @param currentBitCount Current bit count + * @param value Value + * @return New bit count + */ public static int enlargeBitCountS(int currentBitCount, int value) { if (value == 0) { return currentBitCount; @@ -636,6 +673,12 @@ public class SWFOutputStream extends OutputStream { return currentBitCount; } + /** + * Enlarges bit count for unsigned values. + * @param currentBitCount Current bit count + * @param value Value + * @return New bit count + */ public static int enlargeBitCountU(int currentBitCount, int value) { if (value == 0) { return currentBitCount; @@ -648,7 +691,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MATRIX value to the stream + * Writes MATRIX value to the stream. * * @param value MATRIX value * @throws IOException @@ -699,7 +742,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CXFORM value to the stream + * Writes CXFORM value to the stream. * * @param value CXFORM value * @throws IOException @@ -738,7 +781,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CXFORMWITHALPHA value to the stream + * Writes CXFORMWITHALPHA value to the stream. * * @param value CXFORMWITHALPHA value * @throws IOException @@ -781,7 +824,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CLIPEVENTFLAGS value to the stream + * Writes CLIPEVENTFLAGS value to the stream. * * @param value CLIPEVENTFLAGS value * @throws IOException @@ -813,7 +856,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CLIPACTIONRECORD value to the stream + * Writes CLIPACTIONRECORD value to the stream. * * @param value CLIPACTIONRECORD value * @throws IOException @@ -833,7 +876,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CLIPACTIONS value to the stream + * Writes CLIPACTIONS value to the stream. * * @param value CLIPACTIONS value * @throws IOException @@ -852,7 +895,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes COLORMATRIXFILTER value to the stream + * Writes COLORMATRIXFILTER value to the stream. * * @param value COLORMATRIXFILTER value * @throws IOException @@ -864,7 +907,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes RGBA value to the stream + * Writes RGBA value to the stream. * * @param value RGBA value * @throws IOException @@ -877,7 +920,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes ARGB value to the stream + * Writes ARGB value to the stream. * * @param value ARGB value * @throws IOException @@ -890,7 +933,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes ARGB value to the stream + * Writes ARGB value to the stream. * * @param value ARGB value * @throws IOException @@ -903,7 +946,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes RGB value to the stream + * Writes RGB value to the stream. * * @param value RGB value * @throws IOException @@ -915,7 +958,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes CONVOLUTIONFILTER value to the stream + * Writes CONVOLUTIONFILTER value to the stream. * * @param value CONVOLUTIONFILTER value * @throws IOException @@ -937,7 +980,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes BLURFILTER value to the stream + * Writes BLURFILTER value to the stream. * * @param value BLURFILTER value * @throws IOException @@ -950,7 +993,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes DROPSHADOWFILTER value to the stream + * Writes DROPSHADOWFILTER value to the stream. * * @param value DROPSHADOWFILTER value * @throws IOException @@ -969,7 +1012,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GLOWFILTER value to the stream + * Writes GLOWFILTER value to the stream. * * @param value GLOWFILTER value * @throws IOException @@ -986,7 +1029,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes BEVELFILTER value to the stream + * Writes BEVELFILTER value to the stream. * * @param value BEVELFILTER value * @throws IOException @@ -1007,7 +1050,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GRADIENTGLOWFILTER value to the stream + * Writes GRADIENTGLOWFILTER value to the stream. * * @param value GRADIENTGLOWFILTER value * @throws IOException @@ -1033,7 +1076,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GRADIENTBEVELFILTER value to the stream + * Writes GRADIENTBEVELFILTER value to the stream. * * @param value GRADIENTBEVELFILTER value * @throws IOException @@ -1059,7 +1102,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes list of FILTER values to the stream + * Writes list of FILTER values to the stream. * * @param list List of FILTER values * @throws IOException @@ -1072,7 +1115,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FILTER value to the stream + * Writes FILTER value to the stream. * * @param value FILTER value * @throws IOException @@ -1106,7 +1149,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes list of BUTTONRECORD values to the stream + * Writes list of BUTTONRECORD values to the stream. * * @param list List of BUTTONRECORD values * @param inDefineButton2 Whether write inside of DefineButton2Tag or not @@ -1120,7 +1163,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes BUTTONRECORD value to the stream + * Writes BUTTONRECORD value to the stream. * * @param value BUTTONRECORD value * @param inDefineButton2 Whether write inside of DefineButton2Tag or not @@ -1149,7 +1192,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes list of BUTTONCONDACTION values to the stream + * Writes list of BUTTONCONDACTION values to the stream. * * @param list List of BUTTONCONDACTION values * @throws IOException @@ -1161,7 +1204,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes BUTTONCONDACTION value to the stream + * Writes BUTTONCONDACTION value to the stream. * * @param value BUTTONCONDACTION value * @param isLast True if it is last on the list @@ -1192,7 +1235,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FILLSTYLE value to the stream + * Writes FILLSTYLE value to the stream. * * @param value FILLSTYLE value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1229,7 +1272,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FILLSTYLEARRAY value to the stream + * Writes FILLSTYLEARRAY value to the stream. * * @param value FILLSTYLEARRAY value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1253,7 +1296,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes FOCALGRADIENT value to the stream + * Writes FOCALGRADIENT value to the stream. * * @param value FILLSTYLEARRAY value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1270,7 +1313,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GRADIENT value to the stream + * Writes GRADIENT value to the stream. * * @param value GRADIENT value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1286,7 +1329,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GRADRECORD value to the stream + * Writes GRADRECORD value to the stream. * * @param value GRADRECORD value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1302,7 +1345,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes LINESTYLE value to the stream + * Writes LINESTYLE value to the stream. * * @param value LINESTYLE value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1318,7 +1361,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes LINESTYLE2 value to the stream + * Writes LINESTYLE2 value to the stream. * * @param value LINESTYLE2 value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1346,7 +1389,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes LINESTYLEARRAY value to the stream + * Writes LINESTYLEARRAY value to the stream. * * @param value FILLSTYLEARRAY value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1380,7 +1423,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SHAPE value to the stream + * Writes SHAPE value to the stream. * * @param value SHAPE value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1393,6 +1436,10 @@ public class SWFOutputStream extends OutputStream { writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum); } + /** + * Calculates SHAPE fill and line bits. + * @param value SHAPE value + */ private void calculateSHAPEFillLineBits(SHAPE value) { int numFillBits = 0; int numLineBits = 0; @@ -1424,7 +1471,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SHAPEWITHSTYLE value to the stream + * Writes SHAPEWITHSTYLE value to the stream. * * @param value SHAPEWITHSTYLE value * @param shapeNum 1 in DefineShape, 2 in DefineShape2,... @@ -1440,7 +1487,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SHAPERECORDs value to the stream + * Writes SHAPERECORDs value to the stream. * * @param value SHAPERECORDS value * @param fillBits @@ -1540,7 +1587,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SOUNDINFO value to the stream + * Writes SOUNDINFO value to the stream. * * @param value SOUNDINFO value * @throws IOException @@ -1571,7 +1618,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes SOUNDENVELOPE value to the stream + * Writes SOUNDENVELOPE value to the stream. * * @param value SOUNDENVELOPE value * @throws IOException @@ -1583,7 +1630,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes TEXTRECORD value to the stream + * Writes TEXTRECORD value to the stream. * * @param value TEXTRECORD value * @param defineTextNum @@ -1625,7 +1672,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes GLYPHENTRY value to the stream + * Writes GLYPHENTRY value to the stream. * * @param value GLYPHENTRY value * @param glyphBits @@ -1638,7 +1685,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHFILLSTYLE value to the stream + * Writes MORPHFILLSTYLE value to the stream. * * @param value MORPHFILLSTYLE value * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... @@ -1675,7 +1722,7 @@ public class SWFOutputStream extends OutputStream { } /** - * WritesMORPH FILLSTYLEARRAY value to the stream + * WritesMORPH FILLSTYLEARRAY value to the stream. * * @param value MORPHFILLSTYLEARRAY value * @param morphShapeNum 1 on DefineMorphShape, 2 on DefineMorphShape @@ -1695,7 +1742,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHGRADIENT value to the stream + * Writes MORPHGRADIENT value to the stream. * * @param value MORPHGRADIENT value * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... @@ -1734,7 +1781,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHGRADRECORD value to the stream + * Writes MORPHGRADRECORD value to the stream. * * @param value MORPHGRADRECORD value * @throws IOException @@ -1747,7 +1794,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHLINESTYLE value to the stream + * Writes MORPHLINESTYLE value to the stream. * * @param value LINESTYLE value * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... @@ -1762,7 +1809,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHLINESTYLE2 value to the stream + * Writes MORPHLINESTYLE2 value to the stream. * * @param value MORPHLINESTYLE2 value * @param shapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... @@ -1792,7 +1839,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes MORPHLINESTYLEARRAY value to the stream + * Writes MORPHLINESTYLEARRAY value to the stream. * * @param value MORPHFILLSTYLEARRAY value * @param morphShapeNum 1 in DefineMorphShape, 2 in DefineMorphShape2,... @@ -1826,7 +1873,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes KERNINGRECORD value to the stream + * Writes KERNINGRECORD value to the stream. * * @param value KERNINGRECORD value * @param fontFlagsWideCodes @@ -1844,7 +1891,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes LANGCODE value to the stream + * Writes LANGCODE value to the stream. * * @param value LANGCODE value * @throws IOException @@ -1854,7 +1901,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes ZONERECORD value to the stream + * Writes ZONERECORD value to the stream. * * @param value ZONERECORD value * @throws IOException @@ -1870,7 +1917,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes ZONEDATA value to the stream + * Writes ZONEDATA value to the stream. * * @param value ZONEDATA value * @throws IOException @@ -1880,12 +1927,23 @@ public class SWFOutputStream extends OutputStream { writeUI16(value.range); } + /** + * Writes ZLIB compressed data to the stream. + * @param data Data to compress + * @throws IOException + */ public void writeBytesZlib(byte[] data) throws IOException { DeflaterOutputStream deflater = new DeflaterOutputStream(this, new Deflater(9)); deflater.write(data); deflater.finish(); } + /** + * Compresses byte array using ZLIB. + * @param data Data to compress + * @return Compressed data + * @throws IOException + */ public static byte[] compressByteArray(byte[] data) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DeflaterOutputStream deflater = new DeflaterOutputStream(baos, new Deflater(9)); @@ -1895,12 +1953,12 @@ public class SWFOutputStream extends OutputStream { } /** - * Reads one BITMAPDATA value from the stream + * Reads one BITMAPDATA value from the stream. * - * @param value - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight + * @param value BITMAPDATA value + * @param bitmapFormat Format of the bitmap + * @param bitmapWidth Width of the bitmap + * @param bitmapHeight Height of the bitmap * @throws IOException */ public void writeBITMAPDATA(BITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { @@ -1927,12 +1985,12 @@ public class SWFOutputStream extends OutputStream { } /** - * Reads one ALPHABITMAPDATA value from the stream + * Reads one ALPHABITMAPDATA value from the stream. * - * @param value - * @param bitmapFormat - * @param bitmapWidth - * @param bitmapHeight + * @param value ALPHABITMAPDATA value + * @param bitmapFormat Format of the bitmap + * @param bitmapWidth Width of the bitmap + * @param bitmapHeight Height of the bitmap * @throws IOException */ public void writeALPHABITMAPDATA(ALPHABITMAPDATA value, int bitmapFormat, int bitmapWidth, int bitmapHeight) throws IOException { @@ -1946,7 +2004,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes PIX24 value to the stream + * Writes PIX24 value to the stream. * * @param value PIX24 value * @throws IOException @@ -1959,7 +2017,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes PIX24 value to the stream + * Writes PIX24 value to the stream. * * @param value PIX24 value * @throws IOException @@ -1972,7 +2030,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes PIX15 value to the stream + * Writes PIX15 value to the stream. * * @param value PIX15 value * @throws IOException @@ -1985,7 +2043,7 @@ public class SWFOutputStream extends OutputStream { } /** - * Writes PIX15 value to the stream + * Writes PIX15 value to the stream. * * @param value PIX15 value * @throws IOException @@ -1999,9 +2057,9 @@ public class SWFOutputStream extends OutputStream { /** * Writes AMF3 encoded value. Warning: Correct serializer needs to be passed - * as second parameter when using IExternalizable + * as second parameter when using IExternalizable. * - * @param value + * @param value AMF3 encoded value * @param serializers Map className=>Serializer for classes implementing * IExternalizable * @throws IOException @@ -2014,9 +2072,9 @@ public class SWFOutputStream extends OutputStream { /** * Writes AMF3 encoded value. Warning: When the object implements - * IExternalizable, you need to pass serializer as second parameter + * IExternalizable, you need to pass serializer as second parameter. * - * @param value + * @param value AMF3 encoded value * @throws IOException * @throws NoSerializerExistsException */ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java index cdaebd04f..d648da7c6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFSearch.java @@ -16,11 +16,8 @@ */ package com.jpexs.decompiler.flash; -import com.jpexs.helpers.Helper; -import com.jpexs.helpers.MemoryInputStream; -import com.jpexs.helpers.PosMarkedInputStream; -import com.jpexs.helpers.ProgressListener; -import com.jpexs.helpers.Searchable; +import com.jpexs.helpers.*; + import java.io.IOException; import java.io.InputStream; import java.util.HashSet; @@ -29,43 +26,82 @@ import java.util.Map; import java.util.Set; /** - * + * SWF search class. * @author JPEXS */ public class SWFSearch { + /** + * Searchable object + */ protected Searchable s; + /** + * No check for validity + */ private final boolean noCheck; + /** + * Search mode + */ private final SearchMode searchMode; + /** + * Already processed + */ private boolean processed = false; + /** + * Progress listeners + */ private final Set listeners = new HashSet<>(); + /** + * SWF streams + */ private final Map swfStreams = new LinkedHashMap<>(); + /** + * Constructs SWF search object. + * @param s Searchable object + * @param noCheck No check for validity + * @param searchMode Search mode + */ public SWFSearch(Searchable s, boolean noCheck, SearchMode searchMode) { this.s = s; this.noCheck = noCheck; this.searchMode = searchMode; } + /** + * Adds progress listener. + * @param l + */ public void addProgressListener(ProgressListener l) { listeners.add(l); } + /** + * Removes progress listener. + * @param l + */ public void removeProgressListener(ProgressListener l) { listeners.remove(l); } + /** + * Sets progress. + * @param p Progress + */ private void setProgress(int p) { for (ProgressListener l : listeners) { l.progress(p); } } + /** + * Processes SWF search. + */ public void process() { Map ret; ret = s.search(new ProgressListener() { @@ -144,6 +180,13 @@ public class SWFSearch { processed = true; } + /** + * Gets SWF stream. + * @param listener Progress listener + * @param address Address + * @return SWF stream + * @throws IOException + */ public MemoryInputStream get(ProgressListener listener, long address) throws IOException { if (!processed) { return null; @@ -154,10 +197,18 @@ public class SWFSearch { return swfStreams.get(address); } + /** + * Gets list of addresses. + * @return List of addresses + */ public Set getAddresses() { return swfStreams.keySet(); } + /** + * Gets number of SWF streams. + * @return Number of SWF streams + */ public int length() { if (!processed) { return 0; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SearchMode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SearchMode.java index fee639a6e..df546e791 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SearchMode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SearchMode.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; /** - * + * Search mode for searching in SWF file. * @author JPEXS */ public enum SearchMode { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index 5eeed8274..01fd81438 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; + import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -28,71 +29,167 @@ import java.util.List; import java.util.Map; /** - * + * Local data for source generator. * @author JPEXS */ public class SourceGeneratorLocalData implements Serializable { + /** + * Map of variable name to register number. + */ public HashMap registerVars; + /** + * In function level. + */ public Integer inFunction; + /** + * In method. + */ public Boolean inMethod; + /** + * For in level. + */ public Integer forInLevel; - // TODO: handle AVM2 separately + //TODO: handle AVM2 separately + /** + * List of AVM2 exceptions. + */ public List exceptions = new ArrayList<>(); + /** + * List of finally Ids + */ public List finallyCatches = new ArrayList<>(); + /** + * List of finally opened loops + */ public List> finallyOpenedLoops = new ArrayList<>(); + /** + * Counter of finally uses + */ public Map finallyCounter = new HashMap<>(); + /** + * Register number for finally block + */ public int finallyRegister = -1; + /** + * Current class base name + */ public String currentClassBaseName; //FIXME! Suffixed or not? + /** + * Super class name + */ public String superClass = null; + /** + * Super package name + */ public DottedChain superPkg = null; + /** + * Activation register number + */ public int activationReg = 0; + /** + * Call stack + */ public List callStack = new ArrayList<>(); + /** + * MethodBody trait usages. Map of MethodBody to list of used trait indexes. + */ public Map> traitUsages = new HashMap<>(); + /** + * Current package + */ public DottedChain pkg = DottedChain.TOPLEVEL; + /** + * Scope stack + */ public List scopeStack = new ArrayList<>(); + /** + * Current script + */ public ScriptInfo currentScript; + /** + * Current script index + */ public int scriptIndex; + /** + * Is in sub method + */ public boolean subMethod = false; + /** + * Current private namespace id + */ public int privateNs = 0; + /** + * Current protected namespace id + */ public int protectedNs = 0; + /** + * Is in static method + */ public boolean isStatic = false; + /** + * Opened loop ids + */ public List openedLoops = new ArrayList<>(); + /** + * Opened loop ids for catch blocks + */ public List> catchesOpenedLoops = new ArrayList<>(); + + /** + * Temp registers used in catch blocks + */ public List catchesTempRegs = new ArrayList<>(); + /** + * Document class + */ public String documentClass; + /** + * Is second run + */ public boolean secondRun = false; + /** + * Gets full class name. + * @return Full class name + */ public String getFullClass() { return pkg == null ? currentClassBaseName : pkg.addWithSuffix(currentClassBaseName).toRawString(); } + /** + * Constructs new SourceGeneratorLocalData. + * @param registerVars Map of variable name to register number + * @param inFunction In function level + * @param inMethod In method + * @param forInLevel For in level + */ public SourceGeneratorLocalData(HashMap registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) { this.registerVars = registerVars; this.inFunction = inFunction; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SwfOpenException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SwfOpenException.java index e4c8d7811..7ef1e0494 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SwfOpenException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SwfOpenException.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash; import java.io.IOException; /** - * + * Exception thrown when SWF file cannot be opened. * @author JPEXS */ public class SwfOpenException extends IOException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/TagRemoveListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/TagRemoveListener.java index c55ca601d..a5b236198 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/TagRemoveListener.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/TagRemoveListener.java @@ -19,10 +19,14 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.tags.Tag; /** - * + * Listener for tag removal. * @author JPEXS */ public interface TagRemoveListener { + /** + * Called when a tag is removed. + * @param tag Removed tag + */ public void tagRemoved(Tag tag); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/UrlResolver.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/UrlResolver.java index 89115db0f..f9fde6380 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/UrlResolver.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/UrlResolver.java @@ -17,10 +17,15 @@ package com.jpexs.decompiler.flash; /** - * + * URL resolver interface. * @author JPEXS */ public interface UrlResolver { + /** + * Resolves URL to SWF object. + * @param url URL + * @return SWF object or null if not valid + */ public SWF resolveUrl(String url); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ValueTooLargeException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ValueTooLargeException.java index 5403295b8..e9b64c6f0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ValueTooLargeException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ValueTooLargeException.java @@ -17,24 +17,43 @@ package com.jpexs.decompiler.flash; /** - * + * Exception thrown when a value is too large for a specific type. * @author JPEXS */ public class ValueTooLargeException extends IllegalArgumentException { + /** + * Type of the value + */ private final String type; + /** + * Value that is too large + */ private final Object value; + /** + * Constructs a new ValueTooLargeException with the specified type and value. + * @param type Type of the value + * @param value Value that is too large + */ public ValueTooLargeException(String type, Object value) { super("Value is too large for " + type + ": " + value); this.type = type; this.value = value; } + /** + * Gets the type of the value. + * @return Type of the value + */ public String getType() { return type; } + /** + * Gets the value that is too large. + * @return Value that is too large + */ public Object getValue() { return value; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Version.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Version.java index d54355769..a3474aba1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Version.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/Version.java @@ -17,18 +17,33 @@ package com.jpexs.decompiler.flash; /** - * + * FFDec version information. * @author JPEXS */ public class Version { + /** + * Git tag name + */ public String tagName; + /** + * Version name + */ public String versionName; + /** + * Release date + */ public String releaseDate; + /** + * Is this a prerelease version? + */ public boolean prerelease; + /** + * Description + */ public String description; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java index 6a0086f6a..8fc6141c3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ZippedBundle.java @@ -20,12 +20,8 @@ import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; import com.jpexs.helpers.ReReadableInputStream; import com.jpexs.helpers.streams.SeekableInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; + +import java.io.*; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -35,31 +31,65 @@ import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; /** - * + * Bundle implementation for ZIP files. * @author JPEXS */ public class ZippedBundle implements Bundle { + /** + * + */ protected Set keySet = new HashSet<>(); + /** + * File input stream for the ZIP file. + */ protected FileInputStream fis; + /** + * Re-readable input stream for the ZIP file. + */ protected ReReadableInputStream is; + /** + * File name of the ZIP file. + */ protected File filename; + /** + * Constructs a new ZippedBundle from an input stream. + * @param is Input stream + * @throws IOException + */ public ZippedBundle(InputStream is) throws IOException { this(is, null); } + /** + * Constructs a new ZippedBundle from a file. + * @param filename File + * @throws IOException + */ public ZippedBundle(File filename) throws IOException { this(null, filename); } + /** + * Constructs a new ZippedBundle from an input stream and a file. + * @param is Input stream + * @param filename File + * @throws IOException + */ protected ZippedBundle(InputStream is, File filename) throws IOException { initBundle(is, filename); } + /** + * Initializes the bundle. + * @param is Input stream + * @param filename File + * @throws IOException + */ protected void initBundle(InputStream is, File filename) throws IOException { if (filename != null) { fis = new FileInputStream(filename); @@ -80,16 +110,30 @@ public class ZippedBundle implements Bundle { } } + /** + * Gets the number of entries in the bundle. + * @return + */ @Override public int length() { return keySet.size(); } + /** + * Gets the keys in the bundle. + * @return + */ @Override public Set getKeys() { return keySet; } + /** + * Gets the input stream for a key. + * @param key Key + * @return Input stream + * @throws IOException + */ @Override public SeekableInputStream getOpenable(String key) throws IOException { if (!keySet.contains(key)) { @@ -115,6 +159,11 @@ public class ZippedBundle implements Bundle { //return cachedSWFs.get(key); } + /** + * Gets all input streams in the bundle. + * @return Map of key to input stream + * @throws IOException + */ @Override public Map getAll() throws IOException { Map ret = new HashMap<>(); @@ -124,16 +173,32 @@ public class ZippedBundle implements Bundle { return ret; } + /** + * Gets the extension of the bundle. + * @return Extension + */ @Override public String getExtension() { return "zip"; } + /** + * Gets whether the bundle is read-only. + * @return Whether the bundle is read-only + */ @Override public boolean isReadOnly() { return this.filename == null || !this.filename.canWrite(); } + + /** + * Replaces the input stream for a key. + * @param key Key + * @param swfIs New input stream + * @return Whether the operation was successful + * @throws IOException + */ @Override public boolean putOpenable(String key, InputStream swfIs) throws IOException { if (this.isReadOnly()) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 2997715e9..c37bd31b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -16,11 +16,8 @@ */ package com.jpexs.decompiler.flash.abc; -import com.jpexs.decompiler.flash.AppResources; -import com.jpexs.decompiler.flash.DeobfuscationListener; -import com.jpexs.decompiler.flash.EndOfStreamException; import com.jpexs.decompiler.flash.EventListener; -import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.*; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation; @@ -28,24 +25,8 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.types.ABCException; -import com.jpexs.decompiler.flash.abc.types.ClassInfo; -import com.jpexs.decompiler.flash.abc.types.InstanceInfo; -import com.jpexs.decompiler.flash.abc.types.MetadataInfo; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.abc.types.NamespaceSet; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; -import com.jpexs.decompiler.flash.abc.types.ValueKind; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import com.jpexs.decompiler.flash.abc.types.traits.TraitType; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.abc.types.*; +import com.jpexs.decompiler.flash.abc.types.traits.*; import com.jpexs.decompiler.flash.abc.usages.MultinameUsageDetector; import com.jpexs.decompiler.flash.abc.usages.Usage; import com.jpexs.decompiler.flash.abc.usages.multinames.DefinitionUsage; @@ -63,92 +44,165 @@ import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.helpers.Helper; import com.jpexs.helpers.utf8.Utf8PrintWriter; + import java.io.File; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -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; /** - * + * ABC structure. * @author JPEXS */ public class ABC implements Openable { + /** + * ABC version. + */ public ABCVersion version = new ABCVersion(46, 16); + /** + * Constant pool. + */ public AVM2ConstantPool constants = new AVM2ConstantPool(); + /** + * List of method info + */ public List method_info = new ArrayList<>(); + /** + * List of metadata + */ public List metadata_info = new ArrayList<>(); + /** + * List of instance info + */ public List instance_info = new ArrayList<>(); + /** + * List of class info + */ public List class_info = new ArrayList<>(); + /** + * List of script info + */ public List script_info = new ArrayList<>(); + /** + * List of method bodies + */ public List bodies = new ArrayList<>(); + /** + * ABC method indexing + */ private ABCMethodIndexing abcMethodIndexing; + /* + * ABC minor version with decimal support + */ public static final int MINORwithDECIMAL = 17; + /** + * List of listeners + */ protected Set listeners = new HashSet<>(); + /** + * Logger + */ private static final Logger logger = Logger.getLogger(ABC.class.getName()); + /** + * Deobfuscation + */ private AVM2Deobfuscation deobfuscation; + /* + * Parent tag + */ @Internal public ABCContainerTag parentTag; - /* Map from multiname index of namespace value to namespace name**/ + /** + * Map from multiname index of namespace value to namespace name + */ private Map namespaceMap; + /** + * File + */ private String file; + /** + * File title + */ private String fileTitle; + /** + * Openable list + */ private OpenableList openableList; + /** + * Whether this ABC is standalone openable + */ private boolean isOpenable = false; + /** + * Data size + */ private long dataSize = 0L; + /** + * Change listeners + */ private List changeListeners = new ArrayList<>(); + /** + * Constructs ABC. + * @param tag + */ public ABC(ABCContainerTag tag) { this.parentTag = tag; this.deobfuscation = null; } + /** + * Adds change listener. + * @param listener + */ public void addChangeListener(Runnable listener) { changeListeners.add(listener); } + /** + * Removes change listener. + * @param listener + */ public void removeChangeListener(Runnable listener) { changeListeners.remove(listener); } + /** + * Fires changed event. + */ public void fireChanged() { for (Runnable r : changeListeners) { r.run(); } } + /** + * Gets openable. + * @return + */ @Override public Openable getOpenable() { if (isOpenable) { @@ -157,10 +211,18 @@ public class ABC implements Openable { return parentTag.getSwf(); } + /** + * Gets SWF. + * @return + */ public SWF getSwf() { return parentTag.getSwf(); } + /** + * Gets list of ABC containers. + * @return + */ public List getAbcTags() { Openable openable = getOpenable(); if (openable instanceof SWF) { @@ -169,17 +231,32 @@ public class ABC implements Openable { return new ArrayList<>(); } + /** + * Adds method body. + * @param body + * @return + */ public int addMethodBody(MethodBody body) { bodies.add(body); abcMethodIndexing = null; return bodies.size() - 1; } + /** + * Adds method info. + * @param mi + * @return + */ public int addMethodInfo(MethodInfo mi) { method_info.add(mi); return method_info.size() - 1; } + /** + * Deletes class. + * @param class_info Class index + * @param d Deletion flag + */ public void deleteClass(int class_info, boolean d) { ABC abc = this; ClassInfo classInfo = abc.class_info.get(class_info); @@ -200,7 +277,7 @@ public class ABC implements Openable { } /** - * Gets id of metadata/add metadata + * Gets id of metadata/add metadata. * * @param newMetadata * @param add Add if not found? @@ -222,6 +299,13 @@ public class ABC implements Openable { return -1; } + /** + * Adds method to class. + * @param classId Class index + * @param name Method name + * @param isStatic Whether method is static + * @return + */ public TraitMethodGetterSetter addMethod(int classId, String name, boolean isStatic) { Multiname multiname = new Multiname(); multiname.kind = Multiname.QNAME; @@ -255,24 +339,48 @@ public class ABC implements Openable { return trait; } + /** + * Adds event listener. + * @param listener + */ public void addEventListener(EventListener listener) { listeners.add(listener); } + /** + * Removes event listener. + * @param listener + */ public void removeEventListener(EventListener listener) { listeners.remove(listener); } + /** + * Informs listeners. + * @param event + * @param data + */ protected void informListeners(String event, Object data) { for (EventListener listener : listeners) { listener.handleEvent(event, data); } } + /** + * Removes traps (deobfuscation). + * @return + * @throws InterruptedException + */ public int removeTraps() throws InterruptedException { return removeTraps(null); } + /** + * Removes traps (deobfuscation). + * @param listener Listener + * @return + * @throws InterruptedException + */ public int removeTraps(DeobfuscationListener listener) throws InterruptedException { int rem = 0; for (int s = 0; s < script_info.size(); s++) { @@ -284,10 +392,21 @@ public class ABC implements Openable { return rem; } + /** + * Removes dead code. + * @return + * @throws InterruptedException + */ public int removeDeadCode() throws InterruptedException { return removeDeadCode(null); } + /** + * Removes dead code. + * @param listener Listener + * @return + * @throws InterruptedException + */ public int removeDeadCode(DeobfuscationListener listener) throws InterruptedException { int rem = 0; for (MethodBody body : bodies) { @@ -296,6 +415,10 @@ public class ABC implements Openable { return rem; } + /** + * Gets namespace name string usages. + * @return Set of string indexes + */ public Set getNsStringUsages() { Set ret = new HashSet<>(); for (int n = 1; n < constants.getNamespaceCount(); n++) { @@ -304,6 +427,11 @@ public class ABC implements Openable { return ret; } + /** + * Gets traits string usages. + * @param ret Result + * @param traits Traits + */ public void getTraitStringUsages(Set ret, Traits traits) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -320,6 +448,10 @@ public class ABC implements Openable { } } + /** + * Gets string usages. + * @return + */ public Set getStringUsages() { Set ret = new HashSet<>(); @@ -349,6 +481,12 @@ public class ABC implements Openable { return ret; } + /** + * Gets string usage type. + * @param ret Result - map of string index to usage type + * @param strIndex String index + * @param usageType Usage type + */ private void setStringUsageType(Map ret, int strIndex, String usageType) { if (ret.containsKey(strIndex)) { if (!"name".equals(usageType)) { @@ -365,6 +503,11 @@ public class ABC implements Openable { } } + /** + * Gets string usage types. + * @param ret Result - map of string index to usage type + * @param traits Traits + */ private void getStringUsageTypes(Map ret, Traits traits) { for (Trait t : traits.traits) { int strIndex = constants.getMultiname(t.name_index).name_index; @@ -415,12 +558,21 @@ public class ABC implements Openable { } } + /** + * Gets string usage types. + * @param ret Result - map of string index to usage type + */ public void getStringUsageTypes(Map ret) { for (ScriptInfo script : script_info) { getStringUsageTypes(ret, script.traits); } } + /** + * Renames multiname. + * @param multinameIndex + * @param newname + */ public void renameMultiname(int multinameIndex, String newname) { if (multinameIndex <= 0 || multinameIndex >= constants.getMultinameCount()) { throw new IllegalArgumentException("Multiname with index " + multinameIndex + " does not exist"); @@ -436,6 +588,14 @@ public class ABC implements Openable { } } + /** + * Deobfuscates identifiers. + * @param stringUsageTypes Map of string index to usage type + * @param stringUsages Set of string indexes + * @param namesMap Map of old name to new name + * @param renameType Rename type + * @param doClasses Whether to deobfuscate classes + */ public void deobfuscateIdentifiers(Map stringUsageTypes, Set stringUsages, HashMap namesMap, RenameType renameType, boolean doClasses) { Set namespaceUsages = getNsStringUsages(); AVM2Deobfuscation deobfuscation = getDeobfuscation(); @@ -527,10 +687,18 @@ public class ABC implements Openable { } } + /** + * Checks whether the ABC has decimal support. + * @return + */ public boolean hasDecimalSupport() { return version.minor >= MINORwithDECIMAL; } + /** + * Sets decimal support. + * @param val + */ public void setDecimalSupport(boolean val) { if (val) { if (version.minor != MINORwithDECIMAL) { @@ -543,14 +711,28 @@ public class ABC implements Openable { } } + /** + * Checks minimum version. + * @param minMajor + * @param minMinor + * @return + */ private boolean minVersionCheck(int minMajor, int minMinor) { return version.compareTo(new ABCVersion(minMajor, minMinor)) >= 0; } + /** + * Checks whether the ABC has float support. + * @return + */ public boolean hasFloatSupport() { return minVersionCheck(47, 16); } + /** + * Sets float support. + * @param val + */ public void setFloatSupport(boolean val) { if (val) { if (version.major < 47) { @@ -563,14 +745,34 @@ public class ABC implements Openable { } } + /** + * Checks whether the ABC has exception support. + * @return + */ public boolean hasExceptionSupport() { return version.compareTo(new ABCVersion(46, 15)) > 0; } + /** + * Constructs ABC. + * @param ais ABC input stream + * @param swf SWF + * @param tag ABC container tag + * @throws IOException + */ public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag) throws IOException { this(ais, swf, tag, null, null); } + /** + * Constructs ABC. + * @param ais ABC input stream + * @param swf SWF + * @param tag ABC container tag + * @param file File + * @param fileTitle File title + * @throws IOException + */ public ABC(ABCInputStream ais, SWF swf, ABCContainerTag tag, String file, String fileTitle) throws IOException { this.parentTag = tag; this.file = file; @@ -594,6 +796,12 @@ public class ABC implements Openable { SWFDecompilerPlugin.fireAbcParsed(this, swf); } + /** + * Reads ABC from input stream. + * @param ais ABC input stream + * @param swf SWF + * @throws IOException + */ private void read(ABCInputStream ais, SWF swf) throws IOException { int minor_version = ais.readU16("minor_version"); int major_version = ais.readU16("major_version"); @@ -820,6 +1028,11 @@ public class ABC implements Openable { } } + /** + * Saves ABC to stream. + * @param os Output stream + * @throws IOException + */ public void saveToStream(OutputStream os) throws IOException { ABCOutputStream aos = new ABCOutputStream(os); aos.writeU16(version.minor); @@ -934,22 +1147,47 @@ public class ABC implements Openable { dataSize = aos.getPosition(); } + /** + * Finds method info. + * @param methodInfo Method info + * @return MethodBody or null + */ public MethodBody findBody(MethodInfo methodInfo) { return getMethodIndexing().findMethodBody(methodInfo); } + /** + * Finds method info. + * @param methodInfo Method info index + * @return MethodBody or null + */ public MethodBody findBody(int methodInfo) { return getMethodIndexing().findMethodBody(methodInfo); } + /** + * Finds method body index. + * @param methodInfo Method info + * @return Method body index or -1 + */ public int findBodyIndex(MethodInfo methodInfo) { return getMethodIndexing().findMethodBodyIndex(methodInfo); } + /** + * Finds method body index. + * @param methodInfo Method info index + * @return Method body index or -1 + */ public int findBodyIndex(int methodInfo) { return getMethodIndexing().findMethodBodyIndex(methodInfo); } + /** + * Finds body of class initializer by class. + * @param classNameWithSuffix Class name with suffix + * @return MethodBody or null + */ public MethodBody findBodyClassInitializerByClass(String classNameWithSuffix) { for (int i = 0; i < instance_info.size(); i++) { if (classNameWithSuffix.equals(constants.getMultiname(instance_info.get(i).name_index).getName(constants, null, true, true))) { @@ -963,6 +1201,11 @@ public class ABC implements Openable { return null; } + /** + * Finds body of instance initializer by class. + * @param classNameWithSuffix Class name with suffix + * @return MethodBody or null + */ public MethodBody findBodyInstanceInitializerByClass(String classNameWithSuffix) { for (int i = 0; i < instance_info.size(); i++) { if (classNameWithSuffix.equals(constants.getMultiname(instance_info.get(i).name_index).getName(constants, null, true, true))) { @@ -976,6 +1219,12 @@ public class ABC implements Openable { return null; } + /** + * Finds body by class and name. + * @param classNameWithSuffix Class name with suffix + * @param methodNameWithSuffix Method name with suffix + * @return MethodBody or null + */ public MethodBody findBodyByClassAndName(String classNameWithSuffix, String methodNameWithSuffix) { for (int i = 0; i < instance_info.size(); i++) { if (classNameWithSuffix.equals(constants.getMultiname(instance_info.get(i).name_index).getName(constants, null, true, true))) { @@ -1009,6 +1258,12 @@ public class ABC implements Openable { return null; } + /** + * Checks whether the trait id is static. + * @param classIndex Class index + * @param traitId Trait id + * @return True if static + */ public boolean isStaticTraitId(int classIndex, int traitId) { if (classIndex == -1) { return true; @@ -1021,6 +1276,12 @@ public class ABC implements Openable { } } + /** + * Finds trait by trait id. + * @param classIndex Class index + * @param traitId Trait id + * @return Trait or null + */ public Trait findTraitByTraitId(int classIndex, int traitId) { if (classIndex == -1) { return null; @@ -1039,6 +1300,12 @@ public class ABC implements Openable { } } + /** + * Finds method id by trait id. + * @param classIndex Class index + * @param traitId Trait id + * @return Method id or -1 + */ public int findMethodIdByTraitId(int classIndex, int traitId) { if (classIndex == -1) { return -1; @@ -1072,6 +1339,10 @@ public class ABC implements Openable { } } + /** + * Gets namespace map. + * @return Map from namespace name trait DottedChain. + */ private Map getNamespaceMap() { if (namespaceMap == null) { Map map = new HashMap<>(); @@ -1093,6 +1364,10 @@ public class ABC implements Openable { return namespaceMap; } + /** + * Gets deobfuscation object. + * @return AVM2Deobfuscation + */ private AVM2Deobfuscation getDeobfuscation() { if (deobfuscation == null) { deobfuscation = new AVM2Deobfuscation(getSwf(), constants); @@ -1101,6 +1376,10 @@ public class ABC implements Openable { return deobfuscation; } + /** + * Gets method indexing object. + * @return ABCMethodIndexing + */ public final ABCMethodIndexing getMethodIndexing() { if (abcMethodIndexing == null) { abcMethodIndexing = new ABCMethodIndexing(this); @@ -1109,10 +1388,18 @@ public class ABC implements Openable { return abcMethodIndexing; } + /** + * Resets method indexing. + */ public void resetMethodIndexing() { abcMethodIndexing = null; } + /** + * Converts namespace value to name. + * @param valueStr Namespace value + * @return Namespace name as DottedChain + */ public DottedChain nsValueToName(String valueStr) { if (valueStr == null) { return DottedChain.EMPTY; @@ -1130,6 +1417,12 @@ public class ABC implements Openable { } } + /** + * Gets script packs. + * @param packagePrefix Package prefix to search + * @param allAbcs List of all ABCs + * @return List of ScriptPack + */ public List getScriptPacks(String packagePrefix, List allAbcs) { List ret = new ArrayList<>(); for (int i = 0; i < script_info.size(); i++) { @@ -1140,6 +1433,10 @@ public class ABC implements Openable { return ret; } + /** + * Dump ABC to output stream. + * @param os + */ public void dump(OutputStream os) { Utf8PrintWriter output; output = new Utf8PrintWriter(os); @@ -1164,6 +1461,11 @@ public class ABC implements Openable { } } + /** + * Finds multiname definition. + * @param multinameIndex Multiname index + * @return List of MultinameUsage + */ public List findMultinameDefinition(int multinameIndex) { List usages = findMultinameUsage(multinameIndex, false); List ret = new ArrayList<>(); @@ -1175,6 +1477,11 @@ public class ABC implements Openable { return ret; } + /** + * Finds multiname usage of namespace. + * @param namespaceIndex Namespace index + * @return List of MultinameUsage + */ public List findMultinameUsageOfNamespace(int namespaceIndex) { List ret = new ArrayList<>(); for (int multinameIndex = 1; multinameIndex < constants.getMultinameCount(); multinameIndex++) { @@ -1185,6 +1492,12 @@ public class ABC implements Openable { return ret; } + /** + * Finds multiname usage. + * @param multinameIndex Multiname index + * @param exactMatch Whether to match exactly + * @return List of MultinameUsage + */ public List findMultinameUsage(int multinameIndex, boolean exactMatch) { MultinameUsageDetector det = new MultinameUsageDetector(); List retUsage = det.findMultinameUsage(this, multinameIndex, exactMatch); @@ -1198,6 +1511,7 @@ public class ABC implements Openable { /** * Gets colliding usages of multinames. For example same name * consts/vars/methods or same class names. Mostly in obfuscated files. + * @return Set of MultinameUsage */ public Set getCollidingMultinameUsages() { //Reset @@ -1270,6 +1584,12 @@ public class ABC implements Openable { } } + /** + * Finds method info by name in class. + * @param classId Class id + * @param methodNameWithSuffix Method name with suffix + * @return Method info index or -1 + */ public int findMethodInfoByName(int classId, String methodNameWithSuffix) { if (classId > -1) { for (Trait t : instance_info.get(classId).instance_traits.traits) { @@ -1283,6 +1603,12 @@ public class ABC implements Openable { return -1; } + /** + * Finds method body by name in class. + * @param classId Class id + * @param methodNameWithSuffix Method name with suffix + * @return Method body index or -1 + */ public int findMethodBodyByName(int classId, String methodNameWithSuffix) { if (classId > -1) { for (Trait t : instance_info.get(classId).instance_traits.traits) { @@ -1296,16 +1622,32 @@ public class ABC implements Openable { return -1; } + /** + * Finds method body by method name in class. + * @param className Class name + * @param methodName Method name + * @return Method body index or -1 + */ public int findMethodBodyByName(String className, String methodName) { int classId = findClassByName(className); return findMethodBodyByName(classId, methodName); } + /** + * Finds class by name. + * @param name Class name + * @return Class index or -1 + */ public int findClassByName(DottedChain name) { String str = name == null ? null : name.toRawString(); return findClassByName(str); } + /** + * Finds class by name. + * @param nameWithSuffix Class name with suffix + * @return Class index or -1 + */ public int findClassByName(String nameWithSuffix) { for (int c = 0; c < instance_info.size(); c++) { if (instance_info.get(c).deleted) { @@ -1319,6 +1661,12 @@ public class ABC implements Openable { return -1; } + /** + * Finds script packs by path. + * @param name Name + * @param allAbcs List of all ABCs + * @return List of ScriptPack + */ public List findScriptPacksByPath(String name, List allAbcs) { List ret = new ArrayList<>(); List allPacks = getScriptPacks(null, allAbcs); // todo: honfika: use filter parameter @@ -1351,6 +1699,12 @@ public class ABC implements Openable { } + /** + * Finds script pack by path. + * @param name Name + * @param allAbcs List of all ABCs + * @return ScriptPack or null + */ public ScriptPack findScriptPackByPath(String name, List allAbcs) { List packs = getScriptPacks(null, allAbcs); for (ScriptPack en : packs) { @@ -1361,6 +1715,14 @@ public class ABC implements Openable { return null; } + /** + * Gets global trait id. + * @param type Trait type + * @param isStatic Whether static + * @param classIndex Class index + * @param index Trait index + * @return Global trait id + */ public int getGlobalTraitId(TraitType type, boolean isStatic, int classIndex, int index) { if (type == TraitType.INITIALIZER) { if (!isStatic) { @@ -1385,6 +1747,11 @@ public class ABC implements Openable { } } + /** + * Removes class from traits. + * @param traits Traits + * @param index Trait index + */ private void removeClassFromTraits(Traits traits, int index) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -1398,6 +1765,12 @@ public class ABC implements Openable { } } + /** + * Moves class in traits. + * @param traits Traits + * @param oldIndex Old index + * @param newIndex New index + */ private void moveClassInTraits(Traits traits, int oldIndex, int newIndex) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -1409,6 +1782,13 @@ public class ABC implements Openable { } } + /** + * Moves class index. + * @param oldIndex Old index + * @param newIndex New index + * @param currentIndex Current index + * @return New index + */ private int moveClassIndex(int oldIndex, int newIndex, int currentIndex) { if (newIndex > oldIndex) { newIndex--; @@ -1425,6 +1805,11 @@ public class ABC implements Openable { return currentIndex; } + /** + * Moves class. + * @param oldIndex Old index + * @param newIndex New index + */ public void moveClass(int oldIndex, int newIndex) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { @@ -1452,6 +1837,12 @@ public class ABC implements Openable { class_info.add(newIndex, ci); } + /** + * Adds class. + * @param ci Class info + * @param ii Instance info + * @param index Class index + */ public void addClass(ClassInfo ci, InstanceInfo ii, int index) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { @@ -1474,6 +1865,11 @@ public class ABC implements Openable { class_info.add(index, ci); } + /** + * Adds class in traits. + * @param traits Traits + * @param index Class index + */ private void addClassInTraits(Traits traits, int index) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -1487,6 +1883,10 @@ public class ABC implements Openable { } } + /** + * Reorganizes classes. + * @param classIndexMap Map from old index to new index + */ public void reorganizeClasses(Map classIndexMap) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { @@ -1518,6 +1918,11 @@ public class ABC implements Openable { } } + /** + * Reorganizes classes in traits. + * @param traits Traits + * @param classIndexMap Map from old index to new index + */ private void reorganizeClassesInTraits(Traits traits, Map classIndexMap) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -1531,6 +1936,10 @@ public class ABC implements Openable { } } + /** + * Removes class. + * @param index Class index + */ public void removeClass(int index) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { @@ -1553,6 +1962,11 @@ public class ABC implements Openable { class_info.remove(index); } + /** + * Removes method from traits. + * @param traits Traits + * @param index Method index + */ private void removeMethodFromTraits(Traits traits, int index) { for (Trait t : traits.traits) { if (t instanceof TraitClass) { @@ -1575,6 +1989,10 @@ public class ABC implements Openable { } } + /** + * Removes method. + * @param index Method index + */ public void removeMethod(int index) { int bindex = -1; @@ -1625,12 +2043,26 @@ public class ABC implements Openable { method_info.remove(index); } + /** + * Replaces script pack. + * @param replacer Replacer + * @param pack Script pack + * @param as ActionScript + * @param dependencies Dependencies + * @return True if the pack is simple (= not compound) + * @throws As3ScriptReplaceException + * @throws IOException + * @throws InterruptedException + */ public boolean replaceScriptPack(As3ScriptReplacerInterface replacer, ScriptPack pack, String as, List dependencies) throws As3ScriptReplaceException, IOException, InterruptedException { replacer.replaceScript(pack, as, dependencies); ((Tag) parentTag).setModified(true); return pack.isSimple; } + /** + * Packs methods. + */ private void packMethods() { Set newFunctionsToDelete = new LinkedHashSet<>(); Map newFunctionsUsage = new HashMap<>(); @@ -1690,6 +2122,10 @@ public class ABC implements Openable { } } + /** + * Packs traits. + * @param traits Traits + */ private void packTraits(Traits traits) { for (int i = traits.traits.size() - 1; i >= 0; i--) { Trait t = traits.traits.get(i); @@ -1704,6 +2140,9 @@ public class ABC implements Openable { } } + /** + * Packs ABC. + */ public void pack() { for (ScriptInfo script : script_info) { packTraits(script.traits); @@ -1734,7 +2173,7 @@ public class ABC implements Openable { /** * Merges second ABC to this one. * - * @param secondABC + * @param secondABC Second ABC */ public void mergeABC(ABC secondABC) { Map mergeStringMap = new HashMap<>(); @@ -1760,22 +2199,22 @@ public class ABC implements Openable { /** * Merges second ABC to this one. Gets mapping of indices. * - * @param secondABC - * @param mergeStringMap - * @param mergeIntMap - * @param mergeUIntMap - * @param mergeDoubleMap - * @param mergeFloatMap - * @param mergeFloat4Map - * @param mergeDecimalMap - * @param mergeNamespaceMap - * @param mergeNamespaceSetMap - * @param mergeMultinameMap - * @param mergeMethodInfoMap - * @param mergeMethodBodyMap - * @param mergeClassIndexMap - * @param mergeMetaDataMap - * @param mergeScriptInfoMap + * @param secondABC Second ABC + * @param mergeStringMap String index mapping + * @param mergeIntMap Int index mapping + * @param mergeUIntMap UInt index mapping + * @param mergeDoubleMap Double index mapping + * @param mergeFloatMap Float index mapping + * @param mergeFloat4Map Float4 index mapping + * @param mergeDecimalMap Decimal index mapping + * @param mergeNamespaceMap Namespace index mapping + * @param mergeNamespaceSetMap Namespace set index mapping + * @param mergeMultinameMap Multiname index mapping + * @param mergeMethodInfoMap Method info index mapping + * @param mergeMethodBodyMap Method body index mapping + * @param mergeClassIndexMap Class index mapping + * @param mergeMetaDataMap Metadata index mapping + * @param mergeScriptInfoMap Script info index mapping */ public void mergeABC(ABC secondABC, Map mergeStringMap, @@ -2004,6 +2443,23 @@ public class ABC implements Openable { ((Tag) parentTag).setModified(true); } + /** + * Merges traits. + * @param secondTraits Second traits + * @param mergeMultinameMap Multiname index mapping + * @param mergeStringMap String index mapping + * @param mergeIntMap Int index mapping + * @param mergeUIntMap UInt index mapping + * @param mergeDoubleMap Double index mapping + * @param mergeFloatMap Float index mapping + * @param mergeFloat4Map Float4 index mapping + * @param mergeDecimalMap Decimal index mapping + * @param mergeNamespaceMap Namespace index mapping + * @param mergeMetaDataMap Metadata index mapping + * @param mergeMethodInfoMap Method info index mapping + * @param mergeClassIndexMap Class index mapping + * @return Merged traits + */ private Traits mergeTraits(Traits secondTraits, Map mergeMultinameMap, Map mergeStringMap, Map mergeIntMap, @@ -2037,6 +2493,14 @@ public class ABC implements Openable { return newTraits; } + /** + * Merges trait. + * @param secondTrait Second trait + * @param mergeMultinameMap Multiname index mapping + * @param mergeMethodInfoMap Method info index mapping + * @param mergeMetaDataMap Metadata index mapping + * @return Merged trait + */ private TraitMethodGetterSetter mergeTrait(TraitMethodGetterSetter secondTrait, Map mergeMultinameMap, Map mergeMethodInfoMap, Map mergeMetaDataMap) { TraitMethodGetterSetter newTrait = secondTrait.clone(); newTrait.method_info = mergeMethodInfoMap.get(secondTrait.method_info); @@ -2047,6 +2511,21 @@ public class ABC implements Openable { return newTrait; } + /** + * Merges trait. + * @param secondTrait Second trait + * @param mergeMultinameMap Multiname index mapping + * @param mergeStringMap String index mapping + * @param mergeIntMap Int index mapping + * @param mergeUIntMap UInt index mapping + * @param mergeDoubleMap Double index mapping + * @param mergeFloatMap Float index mapping + * @param mergeFloat4Map Float4 index mapping + * @param mergeDecimalMap Decimal index mapping + * @param mergeNamespaceMap Namespace index mapping + * @param mergeMetaDataMap Metadata index mapping + * @return Merged trait + */ private TraitSlotConst mergeTrait(TraitSlotConst secondTrait, Map mergeMultinameMap, Map mergeStringMap, Map mergeIntMap, @@ -2110,6 +2589,14 @@ public class ABC implements Openable { return newTrait; //TODO } + /** + * Merges trait. + * @param secondTrait Second trait + * @param mergeMultinameMap Multiname index mapping + * @param mergeMethodInfoMap Method info index mapping + * @param mergeMetaDataMap Metadata index mapping + * @return Merged trait + */ private TraitFunction mergeTrait(TraitFunction secondTrait, Map mergeMultinameMap, Map mergeMethodInfoMap, Map mergeMetaDataMap) { TraitFunction newTrait = secondTrait.clone(); newTrait.method_info = mergeMethodInfoMap.get(secondTrait.method_info); @@ -2120,6 +2607,14 @@ public class ABC implements Openable { return newTrait; } + /** + * Merges trait. + * @param secondTrait Second trait + * @param mergeClassMap Class index mapping + * @param mergeMultinameMap Multiname index mapping + * @param mergeMetaDataMap Metadata index mapping + * @return Merged trait + */ private TraitClass mergeTrait(TraitClass secondTrait, Map mergeClassMap, Map mergeMultinameMap, Map mergeMetaDataMap) { TraitClass newTrait = secondTrait.clone(); newTrait.class_info = mergeClassMap.get(secondTrait.class_info); @@ -2130,6 +2625,11 @@ public class ABC implements Openable { return newTrait; } + /** + * Finds custom namespace name of namespace. + * @param link_ns_index Namespace index + * @return Custom namespace name + */ public DottedChain findCustomNsOfNamespace(int link_ns_index) { Namespace ns = constants.getNamespace(link_ns_index); if (ns.kind != Namespace.KIND_NAMESPACE && ns.kind != Namespace.KIND_PACKAGE_INTERNAL) { @@ -2143,6 +2643,11 @@ public class ABC implements Openable { return getSwf().getAbcIndex().nsValueToName(name); } + /** + * Finds custom namespace name of multiname. + * @param m Multiname + * @return Custom namespace name + */ public DottedChain findCustomNsOfMultiname(Multiname m) { int nskind = m.getSimpleNamespaceKind(constants); if (nskind != Namespace.KIND_NAMESPACE && nskind != Namespace.KIND_PACKAGE_INTERNAL) { @@ -2156,22 +2661,36 @@ public class ABC implements Openable { return getSwf().getAbcIndex().nsValueToName(name); } + /** + * Clears packs cache. + */ public void clearPacksCache() { for (ScriptInfo si : script_info) { si.clearPacksCache(); } } + /** + * Frees resources. + */ public void free() { deobfuscation = null; abcMethodIndexing = null; } + /** + * Gets file. + * @return File or null + */ @Override public String getFile() { return file; } + /** + * Gets file title. + * @return File title or file when null or null + */ @Override public String getFileTitle() { if (fileTitle != null) { @@ -2180,6 +2699,10 @@ public class ABC implements Openable { return file; } + /** + * Gets title or short file name. + * @return Title or short file name + */ @Override public String getTitleOrShortFileName() { if (fileTitle != null) { @@ -2188,6 +2711,11 @@ public class ABC implements Openable { return new File(file).getName(); } + /** + * Gets short path title. + * (Include path from parents like DefineBinaryData) + * @return Short path title + */ @Override public String getShortPathTitle() { if (openableList != null) { @@ -2198,11 +2726,19 @@ public class ABC implements Openable { return getTitleOrShortFileName(); } + /** + * Gets short file name. + * @return Short file name + */ @Override public String getShortFileName() { return new File(getTitleOrShortFileName()).getName(); } + /** + * Gets full path title. + * @return Full path title + */ @Override public String getFullPathTitle() { if (openableList != null) { @@ -2213,38 +2749,66 @@ public class ABC implements Openable { return getFileTitle(); } + /** + * Gets modified flag. + * @return + */ @Override public boolean isModified() { return getSwf().isModified(); //?? } + /** + * Sets openable list. + * @param openableList Openable list + */ @Override public void setOpenableList(OpenableList openableList) { this.openableList = openableList; getSwf().setOpenableList(openableList); //dummySwf } + /** + * Gets openable list. + * @return Openable list + */ @Override public OpenableList getOpenableList() { return openableList; } + /** + * To string. + * @return + */ @Override public String toString() { return getTitleOrShortFileName(); } + /** + * Saves ABC to stream. + * @param os Output stream + * @throws IOException + */ @Override public void saveTo(OutputStream os) throws IOException { saveToStream(os); } + /** + * Sets file. + * @param file File + */ @Override public void setFile(String file) { this.file = file; fileTitle = null; } + /** + * Clears modified flag. + */ @Override public void clearModified() { getSwf().clearModified(); @@ -2258,6 +2822,10 @@ public class ABC implements Openable { } } + /** + * Checks whether the ABC has versioned API. + * @return True if the ABC has versioned API + */ public boolean isApiVersioned() { //assuming all traits are versioned for (ScriptInfo si : script_info) { @@ -2268,10 +2836,17 @@ public class ABC implements Openable { return false; } + /** + * Gets data size. + * @return Data size + */ public long getDataSize() { return dataSize; } + /** + * Clears all caches. + */ public void clearAllCaches() { resetMethodIndexing(); getSwf().clearAbcListCache(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java index 562b72e0b..9f61807f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java @@ -18,47 +18,61 @@ package com.jpexs.decompiler.flash.abc; import com.jpexs.decompiler.flash.EndOfStreamException; import com.jpexs.decompiler.flash.SWFInputStream; -import com.jpexs.decompiler.flash.abc.types.Decimal; -import com.jpexs.decompiler.flash.abc.types.Float4; -import com.jpexs.decompiler.flash.abc.types.InstanceInfo; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.abc.types.ValueKind; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.abc.types.*; +import com.jpexs.decompiler.flash.abc.types.traits.*; import com.jpexs.decompiler.flash.dumpview.DumpInfo; import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecial; import com.jpexs.decompiler.flash.dumpview.DumpInfoSpecialType; import com.jpexs.helpers.MemoryInputStream; import com.jpexs.helpers.utf8.Utf8Helper; + import java.io.ByteArrayOutputStream; import java.io.IOException; /** - * + * ABC input stream. * @author JPEXS */ public class ABCInputStream implements AutoCloseable { + /** + * Class has protected namespace + */ private static final int CLASS_PROTECTED_NS = 8; + /** + * Trait has metadata + */ private static final int ATTR_METADATA = 4; + /** + * Input stream + */ private final MemoryInputStream is; + /** + * Buffer output stream + */ private ByteArrayOutputStream bufferOs = null; + /** + * Debug read + */ public static final boolean DEBUG_READ = false; + /** + * Dump info + */ public DumpInfo dumpInfo; + /** + * String data buffer + */ private byte[] stringDataBuffer = new byte[256]; + /** + * Starts buffering. + */ public void startBuffer() { if (bufferOs == null) { bufferOs = new ByteArrayOutputStream(); @@ -67,6 +81,10 @@ public class ABCInputStream implements AutoCloseable { } } + /** + * Stops buffering and returns buffered bytes. + * @return Buffered bytes + */ public byte[] stopBuffer() { if (bufferOs == null) { return SWFInputStream.BYTE_ARRAY_EMPTY; @@ -76,12 +94,16 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Creates new ABC input stream + * @param is Input stream + */ public ABCInputStream(MemoryInputStream is) { this.is = is; } /** - * Sets position in bytes in the stream + * Sets position in bytes in the stream. * * @param pos Number of bytes * @throws java.io.IOException @@ -90,10 +112,23 @@ public class ABCInputStream implements AutoCloseable { is.seek(pos); } + /** + * Creates new dump level. + * @param name Name + * @param type Type + * @return New DumpInfo + */ public DumpInfo newDumpLevel(String name, String type) { return newDumpLevel(name, type, DumpInfoSpecialType.NONE); } + /** + * Creates new dump level. + * @param name Name + * @param type Type + * @param specialType Special type + * @return New DumpInfo + */ public DumpInfo newDumpLevel(String name, String type, DumpInfoSpecialType specialType) { if (dumpInfo != null) { long startByte = is.getPos(); @@ -108,10 +143,17 @@ public class ABCInputStream implements AutoCloseable { return dumpInfo; } + /** + * Ends dump level. + */ public void endDumpLevel() { endDumpLevel(null); } + /** + * Ends dump level. + * @param value Value + */ public void endDumpLevel(Object value) { if (dumpInfo != null) { dumpInfo.lengthBytes = is.getPos() - dumpInfo.startByte; @@ -120,6 +162,10 @@ public class ABCInputStream implements AutoCloseable { } } + /** + * Ends dump level until specified dump info. + * @param di Dump info + */ public void endDumpLevelUntil(DumpInfo di) { if (di != null) { while (dumpInfo != null && dumpInfo != di) { @@ -128,6 +174,11 @@ public class ABCInputStream implements AutoCloseable { } } + /** + * Reads byte from the stream. + * @return Byte + * @throws IOException + */ private int readInternal() throws IOException { int i = is.read(); if (i == -1) { @@ -144,6 +195,12 @@ public class ABCInputStream implements AutoCloseable { return i; } + /** + * Reads byte from the stream. + * @param name Name + * @return Byte + * @throws IOException + */ public int read(String name) throws IOException { newDumpLevel(name, "byte"); int ret = readInternal(); @@ -151,6 +208,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads bytes from the stream. + * @param b Bytes + * @return Number of bytes read + * @throws IOException + */ private int read(byte[] b) throws IOException { int currBytesRead = is.read(b); if (DEBUG_READ) { @@ -174,6 +237,12 @@ public class ABCInputStream implements AutoCloseable { return currBytesRead; } + /** + * Reads U8 from the stream. + * @param name Name + * @return U8 + * @throws IOException + */ public int readU8(String name) throws IOException { newDumpLevel(name, "U8"); int ret = readInternal(); @@ -181,6 +250,11 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads U32 from the stream. + * @return U32 + * @throws IOException + */ private long readU32Internal() throws IOException { int i; long ret = 0; @@ -198,6 +272,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads U32 from the stream. + * @param name Name + * @return U32 + * @throws IOException + */ public long readU32(String name) throws IOException { newDumpLevel(name, "U32"); long ret = readU32Internal(); @@ -205,12 +285,23 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads U30 from the stream. + * @return U30 + * @throws IOException + */ private int readU30Internal() throws IOException { long u32 = readU32Internal(); //no bits above bit 30 return (int) (u32 & 0x3FFFFFFF); } + /** + * Reads U30 from the stream. + * @param name Name + * @return U30 + * @throws IOException + */ public int readU30(String name) throws IOException { newDumpLevel(name, "U30"); int ret = readU30Internal(); @@ -218,6 +309,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads S24 from the stream. + * @param name Name + * @return S24 + * @throws IOException + */ public int readS24(String name) throws IOException { newDumpLevel(name, "S24"); int ret = (readInternal()) + (readInternal() << 8) + (readInternal() << 16); @@ -230,6 +327,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads U16 from the stream. + * @param name Name + * @return U16 + * @throws IOException + */ public int readU16(String name) throws IOException { newDumpLevel(name, "U16"); int ret = (readInternal()) + (readInternal() << 8); @@ -237,6 +340,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads S32 from the stream. + * @param name Name + * @return S32 + * @throws IOException + */ public int readS32(String name) throws IOException { int i; long ret = 0; @@ -262,10 +371,20 @@ public class ABCInputStream implements AutoCloseable { return (int) ret; } + /** + * Gets available bytes in the stream. + * @return Available bytes + * @throws IOException + */ public int available() throws IOException { return is.available(); } + /** + * Reads long from the stream. + * @return Long + * @throws IOException + */ private long readLong() throws IOException { safeRead(8, stringDataBuffer); byte[] readBuffer = stringDataBuffer; @@ -279,6 +398,12 @@ public class ABCInputStream implements AutoCloseable { + ((readBuffer[0] & 255))); } + /** + * Reads double from the stream. + * @param name Name + * @return Double + * @throws IOException + */ public double readDouble(String name) throws IOException { newDumpLevel(name, "Double"); long el = readLong(); @@ -287,12 +412,24 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Safely reads bytes from the stream. + * @param count Count + * @param data Data + * @throws IOException + */ private void safeRead(int count, byte[] data) throws IOException { for (int i = 0; i < count; i++) { data[i] = (byte) readInternal(); } } + /** + * Reads namespace from the stream. + * @param name Name + * @return Namespace + * @throws IOException + */ public Namespace readNamespace(String name) throws IOException { newDumpLevel(name, "Namespace"); int kind = read("kind"); @@ -307,6 +444,12 @@ public class ABCInputStream implements AutoCloseable { return new Namespace(kind, name_index); } + /** + * Reads multiname from the stream. + * @param name Name + * @return Multiname + * @throws IOException + */ public Multiname readMultiname(String name) throws IOException { int kind = readU8("kind"); Multiname result = null; @@ -344,6 +487,12 @@ public class ABCInputStream implements AutoCloseable { return result; } + /** + * Reads method info from the stream. + * @param name Name + * @return Method info + * @throws IOException + */ public MethodInfo readMethodInfo(String name) throws IOException { newDumpLevel(name, "method_info"); int param_count = readU30("param_count"); @@ -376,6 +525,12 @@ public class ABCInputStream implements AutoCloseable { return new MethodInfo(param_types, ret_type, name_index, flags, optional, param_names); } + /** + * Reads trait from the stream. + * @param name Name + * @return Trait + * @throws IOException + */ public Trait readTrait(String name) throws IOException { newDumpLevel(name, "Trait"); long pos = getPosition(); @@ -437,6 +592,12 @@ public class ABCInputStream implements AutoCloseable { return trait; } + /** + * Reads traits from the stream. + * @param name Name + * @return Traits + * @throws IOException + */ public Traits readTraits(String name) throws IOException { newDumpLevel(name, "Traits"); int count = readU30("count"); @@ -448,6 +609,12 @@ public class ABCInputStream implements AutoCloseable { return traits; } + /** + * Reads bytes from the stream. + * @param count Count + * @return Bytes + * @throws IOException + */ private byte[] readBytesInternal(int count) throws IOException { byte[] ret = new byte[count]; for (int i = 0; i < count; i++) { @@ -456,6 +623,14 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads bytes from the stream. + * @param count Count + * @param name Name + * @param specialType Special type + * @return Bytes + * @throws IOException + */ public byte[] readBytes(int count, String name, DumpInfoSpecialType specialType) throws IOException { newDumpLevel(name, "Bytes", specialType); byte[] ret = readBytesInternal(count); @@ -463,6 +638,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads decimal from the stream. + * @param name Name + * @return Decimal + * @throws IOException + */ public Decimal readDecimal(String name) throws IOException { newDumpLevel(name, "Decimal"); byte[] data = readBytesInternal(16); @@ -470,6 +651,12 @@ public class ABCInputStream implements AutoCloseable { return new Decimal(data); } + /** + * Reads float from the stream. + * @param name Name + * @return Float + * @throws IOException + */ public Float readFloat(String name) throws IOException { newDumpLevel(name, "Float"); int intBits = (readInternal()) + (readInternal() << 8); @@ -478,6 +665,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads float4 from the stream. + * @param name Name + * @return Float4 + * @throws IOException + */ public Float4 readFloat4(String name) throws IOException { newDumpLevel(name, "Float4"); float f1 = readFloat("value1"); @@ -489,6 +682,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads instance info from the stream. + * @param name Name + * @return Instance info + * @throws IOException + */ public InstanceInfo readInstanceInfo(String name) throws IOException { newDumpLevel(name, "instance_info"); InstanceInfo ret = new InstanceInfo(null); // do not create Traits in constructor @@ -509,6 +708,12 @@ public class ABCInputStream implements AutoCloseable { return ret; } + /** + * Reads string from the stream. + * @param name Name + * @return String + * @throws IOException + */ public String readString(String name) throws IOException { newDumpLevel(name, "String"); int length = readU30Internal(); @@ -529,14 +734,17 @@ public class ABCInputStream implements AutoCloseable { return r; } - - /*public void markStart(){ - bytesRead=0; - }*/ + /** + * Gets current position in the stream. + * @return Position + */ public long getPosition() { return is.getPos(); } + /** + * Closes the stream. + */ @Override public void close() { } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCMethodIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCMethodIndexing.java index fe1c3e5f3..8ed008369 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCMethodIndexing.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCMethodIndexing.java @@ -20,31 +20,42 @@ import com.jpexs.decompiler.flash.abc.types.ClassInfo; import com.jpexs.decompiler.flash.abc.types.InstanceInfo; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; +import com.jpexs.decompiler.flash.abc.types.traits.*; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** - * + * ABC method indexing. * @author JPEXS */ public class ABCMethodIndexing { + /** + * ABC + */ private final ABC abc; + /** + * Method body index for method info + */ private Map bodyIdxFromMethod = new HashMap<>(); + /** + * Constructs ABC method indexing. + * @param abc ABC + */ public ABCMethodIndexing(ABC abc) { this.abc = abc; createBodyIdxFromMethodIdxMap(abc); } + /** + * Creates body index from method index map. + * @param abc ABC + */ public final void createBodyIdxFromMethodIdxMap(ABC abc) { List bodies = abc.bodies; Map map = new HashMap<>(bodies.size()); @@ -56,6 +67,11 @@ public class ABCMethodIndexing { bodyIdxFromMethod = map; } + /** + * Finds method body index for method info. + * @param methodInfo Method info + * @return Method body index or -1 if not found + */ public int findMethodBodyIndex(MethodInfo methodInfo) { Integer bi = bodyIdxFromMethod.get(methodInfo); if (bi == null) { @@ -65,6 +81,11 @@ public class ABCMethodIndexing { return bi; } + /** + * Finds method body index for method info. + * @param methodInfo Method info index + * @return Method body index or -1 if not found + */ public int findMethodBodyIndex(int methodInfo) { if (methodInfo < 0 || methodInfo >= abc.method_info.size()) { return -1; @@ -74,6 +95,11 @@ public class ABCMethodIndexing { return findMethodBodyIndex(mi); } + /** + * Finds method body for method info. + * @param methodInfo Method info + * @return Method body or null if not found + */ public MethodBody findMethodBody(MethodInfo methodInfo) { int bi = findMethodBodyIndex(methodInfo); if (bi != -1) { @@ -83,6 +109,11 @@ public class ABCMethodIndexing { return null; } + /** + * Finds method body for method info. + * @param methodInfo Method info index + * @return Method body or null if not found + */ public MethodBody findMethodBody(int methodInfo) { int bi = findMethodBodyIndex(methodInfo); if (bi != -1) { @@ -92,6 +123,12 @@ public class ABCMethodIndexing { return null; } + /** + * Finds method traits. + * @param pack Script pack + * @param bodyIndex Method body index + * @return Method traits + */ public List findMethodTraits(ScriptPack pack, int bodyIndex) { int methodInfo = abc.bodies.get(bodyIndex).method_info; List traits = abc.script_info.get(pack.scriptIndex).traits.traits; @@ -104,6 +141,13 @@ public class ABCMethodIndexing { return resultTraits; } + /** + * Finds traits. + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info index + * @param result Result list + */ private static void findTraits(ABC abc, Trait trait, int methodInfo, List result) { if (trait instanceof TraitSlotConst) { TraitSlotConst tsc = (TraitSlotConst) trait; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOpenException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOpenException.java index 7aa6d1b05..1b35c98b9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOpenException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOpenException.java @@ -19,15 +19,24 @@ package com.jpexs.decompiler.flash.abc; import java.io.IOException; /** - * + * ABC open exception. * @author JPEXS */ public class ABCOpenException extends IOException { + /** + * Constructs a new ABCOpenException with the specified detail message. + * @param message Detail message + */ public ABCOpenException(String message) { super(message); } + /** + * Constructs a new ABCOpenException with the specified detail message and cause. + * @param message Detail message + * @param cause Cause + */ public ABCOpenException(String message, Throwable cause) { super(message, cause); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOutputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOutputStream.java index ccd0a14d1..d5d3b666d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOutputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCOutputStream.java @@ -16,57 +16,85 @@ */ package com.jpexs.decompiler.flash.abc; -import com.jpexs.decompiler.flash.abc.types.Decimal; -import com.jpexs.decompiler.flash.abc.types.Float4; -import com.jpexs.decompiler.flash.abc.types.InstanceInfo; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; -import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import com.jpexs.decompiler.flash.abc.types.traits.Traits; +import com.jpexs.decompiler.flash.abc.types.*; +import com.jpexs.decompiler.flash.abc.types.traits.*; import com.jpexs.helpers.utf8.Utf8Helper; + import java.io.IOException; import java.io.OutputStream; /** - * + * ABC output stream. * @author JPEXS */ public class ABCOutputStream extends OutputStream { + /** + * Output stream + */ private final OutputStream os; + + /** + * Current position + */ private long position = 0L; + /** + * Constructs ABC output stream. + * @param os Output stream + */ public ABCOutputStream(OutputStream os) { this.os = os; } + /** + * Returns current position. + * @return Current position + */ public long getPosition() { return position; } + /** + * Writes a byte to the output stream. + * @param b The byte to write. + * @throws IOException + */ @Override public void write(int b) throws IOException { os.write(b); position++; } + /** + * Writes a byte array to the output stream. + * @param data The data to write. + * @throws IOException + */ @Override public void write(byte[] data) throws IOException { os.write(data); position += data.length; } + /** + * Writes a byte array to the output stream. + * @param b The data to write. + * @param off The start offset in the data. + * @param len The number of bytes to write. + * @throws IOException + */ @Override public void write(byte[] b, int off, int len) throws IOException { os.write(b, off, len); position += len; } + /** + * Writes U30 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeU30(long value) throws IOException { writeS32(value); /*boolean loop = true; @@ -91,6 +119,11 @@ public class ABCOutputStream extends OutputStream { */ } + /** + * Writes U32 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeU32(long value) throws IOException { boolean loop = true; value &= 0xFFFFFFFFL; @@ -107,6 +140,11 @@ public class ABCOutputStream extends OutputStream { } while (loop); } + /** + * Writes S24 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeS24(long value) throws IOException { int ret = (int) (value & 0xff); write(ret); @@ -118,6 +156,11 @@ public class ABCOutputStream extends OutputStream { write(ret); } + /** + * Writes S32 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeS32(long value) throws IOException { boolean belowZero = value < 0; /*if (belowZero) { @@ -150,6 +193,11 @@ public class ABCOutputStream extends OutputStream { } while (loop); } + /** + * Writes long to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeLong(long value) throws IOException { byte[] writeBuffer = new byte[8]; writeBuffer[7] = (byte) (value >>> 56); @@ -163,14 +211,29 @@ public class ABCOutputStream extends OutputStream { write(writeBuffer); } + /** + * Writes double to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeDouble(double value) throws IOException { writeLong(Double.doubleToLongBits(value)); } + /** + * Writes float to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeFloat(float value) throws IOException { writeU16(Float.floatToIntBits(value)); } + /** + * Writes float4 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeFloat4(Float4 value) throws IOException { writeFloat(value.values[0]); writeFloat(value.values[1]); @@ -178,21 +241,41 @@ public class ABCOutputStream extends OutputStream { writeFloat(value.values[3]); } + /** + * Writes U8 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeU8(int value) throws IOException { write(value); } + /** + * Writes U16 to the output stream. + * @param value Value to write + * @throws IOException + */ public void writeU16(int value) throws IOException { write(value & 0xff); write((value >> 8) & 0xff); } + /** + * Writes String to the output stream. + * @param s String to write + * @throws IOException + */ public void writeString(String s) throws IOException { byte[] sbytes = Utf8Helper.getBytes(s); writeU30(sbytes.length); write(sbytes); } + /** + * Writes Namespace to the output stream. + * @param ns Namespace to write + * @throws IOException + */ public void writeNamespace(Namespace ns) throws IOException { write(ns.kind); boolean found = false; @@ -208,6 +291,11 @@ public class ABCOutputStream extends OutputStream { } } + /** + * Writes Multiname to the output stream. + * @param m Multiname to write + * @throws IOException + */ public void writeMultiname(Multiname m) throws IOException { writeU8(m.kind); if ((m.kind == Multiname.QNAME) || (m.kind == Multiname.QNAMEA)) { @@ -230,6 +318,11 @@ public class ABCOutputStream extends OutputStream { // kind==0x11,0x12 nothing CONSTANT_RTQNameL and CONSTANT_RTQNameLA. } + /** + * Writes MethodInfo to the output stream. + * @param mi MethodInfo to write + * @throws IOException + */ public void writeMethodInfo(MethodInfo mi) throws IOException { writeU30(mi.param_types.length); writeU30(mi.ret_type); @@ -253,6 +346,11 @@ public class ABCOutputStream extends OutputStream { } } + /** + * Writes Trait to the output stream. + * @param t Trait to write + * @throws IOException + */ public void writeTrait(Trait t) throws IOException { writeU30(t.name_index); write((t.kindFlags << 4) + t.kindType); @@ -288,6 +386,11 @@ public class ABCOutputStream extends OutputStream { } } + /** + * Writes Traits to the output stream. + * @param t Traits to write + * @throws IOException + */ public void writeTraits(Traits t) throws IOException { writeU30(t.traits.size()); for (int i = 0; i < t.traits.size(); i++) { @@ -295,6 +398,11 @@ public class ABCOutputStream extends OutputStream { } } + /** + * Writes InstanceInfo to the output stream. + * @param ii InstanceInfo to write + * @throws IOException + */ public void writeInstanceInfo(InstanceInfo ii) throws IOException { writeU30(ii.name_index); writeU30(ii.super_index); @@ -310,10 +418,20 @@ public class ABCOutputStream extends OutputStream { writeTraits(ii.instance_traits); } + /** + * Writes Decimal to the output stream. + * @param value Decimal to write + * @throws IOException + */ public void writeDecimal(Decimal value) throws IOException { write(value.data); } + /** + * Gets U30 byte length. + * @param value Value + * @return + */ public static int getU30ByteLength(long value) { boolean belowZero = value < 0; int bitcount = 0; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersion.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersion.java index 55702918b..f18b63246 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersion.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersion.java @@ -16,20 +16,43 @@ */ package com.jpexs.decompiler.flash.abc; +/** + * Represents ABC version + */ public class ABCVersion implements Comparable { + /** + * Major version + */ public int major = 46; + + /** + * Minor version + */ public int minor = 16; + /** + * Constructs new ABCVersion + */ public ABCVersion() { } + /** + * Constructs new ABCVersion + * @param major Major version + * @param minor Minor version + */ public ABCVersion(int major, int minor) { this.major = major; this.minor = minor; } + /** + * Compares ABCVersion with another ABCVersion + * @param o the object to be compared. + * @return Negative number if this version is lower, 0 if versions are equal, positive number if this version is higher + */ @Override public int compareTo(ABCVersion o) { if (major != o.major) { @@ -38,11 +61,19 @@ public class ABCVersion implements Comparable { return minor - o.minor; } + /** + * Returns string representation of ABCVersion + * @return + */ @Override public String toString() { return "" + major + "." + minor; } + /** + * Returns hash code of ABCVersion + * @return + */ @Override public int hashCode() { int hash = 7; @@ -51,6 +82,11 @@ public class ABCVersion implements Comparable { return hash; } + /** + * Equals method + * @param obj + * @return + */ @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersionRequirements.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersionRequirements.java index f923f2f84..c33cd98d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersionRequirements.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCVersionRequirements.java @@ -22,7 +22,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Target ABC version + * Target ABC version. * * @author JPEXS */ @@ -30,13 +30,34 @@ import java.lang.annotation.Target; @Target({ElementType.FIELD, ElementType.TYPE}) public @interface ABCVersionRequirements { + /** + * Minimum minor version. + * @return + */ int minMinor() default 0; + /** + * Maximum minor version. + * @return + */ + int maxMinor() default 0; + /** + * Maximum major version. + * @return + */ int maxMajor() default 0; + /** + * Minimum major version. + * @return + */ int minMajor() default 0; + /** + * Exact minor version. + * @return + */ int exactMinor() default 0; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 260029891..6ab85dc09 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -21,56 +21,90 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; -import com.jpexs.decompiler.flash.abc.types.ABCException; -import com.jpexs.decompiler.flash.abc.types.InstanceInfo; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.*; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; -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.*; /** - * + * AVM2 local data. * @author JPEXS */ public class AVM2LocalData extends BaseLocalData { + /** + * Whether the method is static + */ public Boolean isStatic; + /** + * Current class index + */ public Integer classIndex; + /** + * Local registers values + */ public HashMap localRegs; + /** + * Scope stack + */ public ScopeStack scopeStack; + /** + * Local scope stack + */ public ScopeStack localScopeStack; + /** + * Current method body + */ public MethodBody methodBody; + /** + * Current call stack + */ public List callStack; + /** + * Current ABC file + */ public ABC abc; + /** + * ABCIndexing + */ public AbcIndexing abcIndex; + /** + * Local register names + */ public HashMap localRegNames; + /** + * Local register types + */ public HashMap localRegTypes; + /** + * Fully qualified names + */ public List fullyQualifiedNames; + /** + * Parsed exceptions + */ public List parsedExceptions = new ArrayList<>(); + + /** + * Parsed exception ids + */ public List parsedExceptionIds = new ArrayList<>(); - //public Map> finallyJumps; /** * Mapped jumps from pushbyte xx part to apropriate lookupswitch branch */ @@ -81,56 +115,114 @@ public class AVM2LocalData extends BaseLocalData { */ public Map finallyJumpsToFinallyIndex = new HashMap<>(); + /** + * Mapping from finally exception index to default part + */ public Map finallyIndexToDefaultGraphPart = new HashMap<>(); - //exception index => switchPart + /** + * Mapping from exception index to switch part + */ public Map ignoredSwitches = new HashMap<>(); /** - * exception index -> switch defaultPart + * Mapping from exception index to switch defaultPart */ public Map defaultParts = new HashMap<>(); + /** + * Mapping from finally index to register index + */ public Map switchedRegs = new HashMap<>(); + /** + * Mapping from finally index push default part + */ public Map pushDefaultPart = new HashMap<>(); + /** + * Mapping from finally index to finally kind + * See AVM2Graph.FINALLY_KIND_* constants. + */ public Map finallyKinds = new HashMap<>(); /** - * exception index -> switch throw part + * Mapping from finally exception index to switch throw part */ public Map finallyThrowParts = new HashMap<>(); + /** + * Mapping from finally exception index to target part + */ public Map finallyTargetParts = new HashMap<>(); - //switchedPart -> index of nextpart + /** + * Mapping from switchedPart to index of nextpart + */ public Map defaultWays = new HashMap<>(); + /** + * Current script index + */ public Integer scriptIndex; + /** + * Local registers assignment ips. Maps register index to ip where it was assigned. + */ public HashMap localRegAssignmentIps; + /** + * Current instruction pointer + */ public Integer ip; + /** + * AVM2 code + */ public AVM2Code code; + /** + * Whether this has default to primitive + */ public boolean thisHasDefaultToPrimitive; + /** + * Mapping from setLocal position to getLocal positions + */ public Map> setLocalPosToGetLocalPos = new HashMap<>(); + /** + * Code stats + */ public CodeStats codeStats; + /** + * Indices of finally exceptions with double push + */ public Set finallyIndicesWithDoublePush = new HashSet<>(); + /** + * Whether we are in get loops + */ public boolean inGetLoops = false; + /** + * Set of seen methods + */ public Set seenMethods = new HashSet<>(); + /** + * Constructs a new AVM2LocalData + */ public AVM2LocalData() { } + /** + * Returns set of getLocal positions for given setLocal position + * @param setLocalPos SetLocal position + * @return Set of getLocal positions + */ public Set getSetLocalUsages(int setLocalPos) { if (setLocalPosToGetLocalPos == null) { return new HashSet<>(); @@ -141,6 +233,10 @@ public class AVM2LocalData extends BaseLocalData { return setLocalPosToGetLocalPos.get(setLocalPos); } + /** + * Constructs a new AVM2LocalData from another AVM2LocalData + * @param localData Another AVM2LocalData + */ public AVM2LocalData(AVM2LocalData localData) { allSwitchParts = localData.allSwitchParts; isStatic = localData.isStatic; @@ -181,18 +277,34 @@ public class AVM2LocalData extends BaseLocalData { seenMethods = localData.seenMethods; } + /** + * Returns constant pool + * @return Constant pool + */ public AVM2ConstantPool getConstants() { return abc.constants; } + /** + * Returns ABC method infos + * @return List of MethodInfo + */ public List getMethodInfo() { return abc.method_info; } + /** + * Returns ABC instance infos + * @return List of InstanceInfo + */ public List getInstanceInfo() { return abc.instance_info; } + /** + * Returns ABC script infos + * @return List of ScriptInfo + */ public List getScriptInfo() { return abc.script_info; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java index 10b82a390..1f3bd0ca9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ClassPath.java @@ -17,36 +17,64 @@ package com.jpexs.decompiler.flash.abc; import com.jpexs.decompiler.graph.DottedChain; + import java.io.Serializable; import java.util.Objects; /** - * + * Class path * @author JPEXS */ public class ClassPath implements Serializable { + /** + * Package name + */ public final DottedChain packageStr; + /** + * Class name + */ public final String className; + /** + * Namespace suffix + */ public final String namespaceSuffix; + /** + * Constructs a new class path + * @param packageStr Package name + * @param className Class name + * @param namespaceSuffix Namespace suffix + */ public ClassPath(DottedChain packageStr, String className, String namespaceSuffix) { this.packageStr = packageStr == null ? DottedChain.TOPLEVEL : packageStr; this.className = className; this.namespaceSuffix = namespaceSuffix; } + /** + * To string + * @return String + */ @Override public String toString() { return packageStr.add(className, namespaceSuffix).toPrintableString(true); } + /** + * To raw string + * @return Raw string + */ public String toRawString() { return packageStr.add(className, namespaceSuffix).toRawString(); } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 3; @@ -56,6 +84,11 @@ public class ClassPath implements Serializable { return hash; } + /** + * Equals + * @param obj + * @return True if equals + */ @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/CopyOutputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/CopyOutputStream.java index b1b0ff0f1..b35958a56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/CopyOutputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/CopyOutputStream.java @@ -21,30 +21,61 @@ import java.io.InputStream; import java.io.OutputStream; /** - * + * Output stream that copies data to another output stream. * @author JPEXS */ public class CopyOutputStream extends OutputStream { + /** + * Output stream to copy data to. + */ private final OutputStream os; + /** + * Input stream to compare data with. + */ private final InputStream is; + /** + * Position in the output stream. + */ private long pos = 0; + /** + * Size of the temporary buffer. + */ private final int TEMPSIZE = 5; + /** + * Temporary buffer. + */ private final int[] temp = new int[TEMPSIZE]; + /** + * Position in the temporary buffer. + */ private int tempPos = 0; + /** + * Number of bytes to ignore at the beginning. + */ public int ignoreFirst = 0; + /** + * Constructs a new CopyOutputStream. + * @param os Output stream to copy data to + * @param is Input stream to compare data with + */ public CopyOutputStream(OutputStream os, InputStream is) { this.os = os; this.is = is; } + /** + * Writes a byte to the output stream. + * @param b Byte to write + * @throws IOException If an I/O error occurs + */ @Override public void write(int b) throws IOException { temp[tempPos] = b; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/NotSameException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/NotSameException.java index 8ccbb6b57..8d91bb2e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/NotSameException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/NotSameException.java @@ -19,11 +19,15 @@ package com.jpexs.decompiler.flash.abc; import com.jpexs.helpers.Helper; /** - * + * Streams are not the same exception. * @author JPEXS */ public class NotSameException extends RuntimeException { + /** + * Constructs a new NotSameException with specified position. + * @param pos Position + */ public NotSameException(long pos) { super("Streams are not the same at pos " + Helper.formatHex((int) pos, 8)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/RenameType.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/RenameType.java index 8bf0b6109..56dca47a4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/RenameType.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/RenameType.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc; /** - * + * Rename type enum. * @author JPEXS */ public enum RenameType { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 37c0ca4fb..ddf66e402 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -16,31 +16,20 @@ */ package com.jpexs.decompiler.flash.abc; -import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; -import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.ConvertException; -import com.jpexs.decompiler.flash.abc.avm2.OffsetUpdater; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; -import com.jpexs.decompiler.flash.abc.types.ABCException; -import com.jpexs.decompiler.flash.abc.types.ConvertData; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.abc.types.ScriptInfo; +import com.jpexs.decompiler.flash.abc.types.*; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import com.jpexs.decompiler.flash.abc.types.traits.TraitFunction; -import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.exporters.settings.ScriptExportSettings; @@ -58,62 +47,91 @@ import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import com.jpexs.helpers.Path; + import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.*; +import java.util.concurrent.*; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * Script pack class. + * A script pack is a collection of traits that are in the same script. + * It can be a simple script pack (contains only one externally visible definition) + * or a compound script pack (contains more than one externally visible definitions). * @author JPEXS */ public class ScriptPack extends AS3ClassTreeItem { + /** + * Logger + */ private static final Logger logger = Logger.getLogger(ScriptPack.class.getName()); + /** + * ABC file + */ public final ABC abc; + /** + * All ABC files + */ public List allABCs; + /** + * Script index + */ public final int scriptIndex; + /** + * Trait indices + */ public final List traitIndices; + /** + * Class path + */ private final ClassPath path; /** - * Is the scriptpack simple? ScriptPack can be either simple or compound. + * Whether the scriptpack is simple. ScriptPack can be either simple or compound. * Compound = Contains more than one externally visible definitions. */ public boolean isSimple = false; + /** + * Whether the script initializer is empty + */ public boolean scriptInitializerIsEmpty = false; + /** + * Gets openable. + * @return Openable + */ @Override public Openable getOpenable() { return abc.getOpenable(); } + /** + * Gets class path. + * @return Class path + */ public ClassPath getClassPath() { return path; } + /** + * Constructs a new script pack. + * @param path Class path + * @param abc ABC file + * @param allAbcs All ABC files + * @param scriptIndex Script index + * @param traitIndices Trait indices + */ public ScriptPack(ClassPath path, ABC abc, List allAbcs, int scriptIndex, List traitIndices) { super(path.className, path.namespaceSuffix, path); this.abc = abc; @@ -123,6 +141,10 @@ public class ScriptPack extends AS3ClassTreeItem { this.allABCs = allAbcs; } + /** + * Gets path package. + * @return Dotted chain + */ public DottedChain getPathPackage() { DottedChain packageName = DottedChain.TOPLEVEL; for (int t : traitIndices) { @@ -135,6 +157,10 @@ public class ScriptPack extends AS3ClassTreeItem { return packageName; } + /** + * Gets public trait. + * @return Trait or null if not found + */ public Trait getPublicTrait() { for (int t : traitIndices) { Multiname name = abc.script_info.get(scriptIndex).traits.traits.get(t).getName(abc); @@ -146,6 +172,10 @@ public class ScriptPack extends AS3ClassTreeItem { return null; } + /** + * Gets path script name. + * @return Script name + */ public String getPathScriptName() { String scriptName = "script_" + scriptIndex; for (int t : traitIndices) { @@ -158,6 +188,12 @@ public class ScriptPack extends AS3ClassTreeItem { return scriptName; } + /** + * Gets export file. + * @param directory Directory + * @param extension Extension including dot + * @return File + */ public File getExportFile(String directory, String extension) { String scriptName = getPathScriptName(); @@ -167,6 +203,12 @@ public class ScriptPack extends AS3ClassTreeItem { return new File(fileName); } + /** + * Gets export file. + * @param directory Directory + * @param exportSettings Export settings + * @return File + */ public File getExportFile(String directory, ScriptExportSettings exportSettings) { if (exportSettings.singleFile) { return null; @@ -175,6 +217,16 @@ public class ScriptPack extends AS3ClassTreeItem { return getExportFile(directory, exportSettings.getFileExtension()); } + /** + * Converts the script pack. + * @param abcIndex Abc indexing + * @param writer Writer + * @param traits Traits + * @param convertData Convert data + * @param exportMode Export mode + * @param parallel Parallel + * @throws InterruptedException + */ public void convert(AbcIndexing abcIndex, final NulWriter writer, final List traits, final ConvertData convertData, final ScriptExportMode exportMode, final boolean parallel) throws InterruptedException { int sinit_index = abc.script_info.get(scriptIndex).init_index; @@ -208,6 +260,16 @@ public class ScriptPack extends AS3ClassTreeItem { } } + /** + * Append script to writer. + * @param abcIndex Abc indexing + * @param writer Writer + * @param traits Traits + * @param convertData Convert data + * @param exportMode Export mode + * @param parallel Parallel + * @throws InterruptedException + */ private void appendTo(AbcIndexing abcIndex, GraphTextWriter writer, List traits, ConvertData convertData, ScriptExportMode exportMode, boolean parallel) throws InterruptedException { boolean first = true; //script initializer @@ -269,6 +331,17 @@ public class ScriptPack extends AS3ClassTreeItem { } } + /** + * Converts the script pack to source. + * @param abcIndex Abc indexing + * @param writer Writer + * @param traits Traits + * @param convertData Convert data + * @param exportMode Export mode + * @param parallel Parallel + * @param ignoreFrameScripts Whether to ignore frame scripts + * @throws InterruptedException + */ public void toSource(AbcIndexing abcIndex, GraphTextWriter writer, final List traits, final ConvertData convertData, final ScriptExportMode exportMode, final boolean parallel, boolean ignoreFrameScripts) throws InterruptedException { writer.suspendMeasure(); int timeout = Configuration.decompilationTimeoutFile.get(); @@ -310,6 +383,16 @@ public class ScriptPack extends AS3ClassTreeItem { appendTo(abcIndex, writer, traits, convertData, exportMode, parallel); } + /** + * Exports the script pack. + * @param abcIndex Abc indexing + * @param file File + * @param exportSettings Export settings + * @param parallel Parallel + * @return File + * @throws IOException + * @throws InterruptedException + */ public File export(AbcIndexing abcIndex, File file, ScriptExportSettings exportSettings, boolean parallel) throws IOException, InterruptedException { if (!exportSettings.singleFile) { if (file.exists() && !Configuration.overwriteExistingFiles.get()) { @@ -336,6 +419,10 @@ public class ScriptPack extends AS3ClassTreeItem { return file; } + /** + * Hash code. + * @return Hash code + */ @Override public int hashCode() { int hash = 7; @@ -345,6 +432,11 @@ public class ScriptPack extends AS3ClassTreeItem { return hash; } + /** + * Equals. + * @param obj Object + * @return True if equals + */ @Override public boolean equals(Object obj) { if (obj == null) { @@ -363,6 +455,10 @@ public class ScriptPack extends AS3ClassTreeItem { return Objects.equals(path, other.path); } + /** + * Gets modified flag. + * @return True if modified + */ @Override public boolean isModified() { if (scriptIndex >= abc.script_info.size()) { @@ -371,6 +467,9 @@ public class ScriptPack extends AS3ClassTreeItem { return abc.script_info.get(scriptIndex).isModified(); } + /** + * Clears modified flag. + */ public void clearModified() { if (scriptIndex >= abc.script_info.size()) { return; @@ -378,10 +477,21 @@ public class ScriptPack extends AS3ClassTreeItem { abc.script_info.get(scriptIndex).setModified(false); } + + /** + * Label with address. + */ private class Label { + /** + * Address + */ public long addr; + /** + * Constructs a new label. + * @param addr Address + */ public Label(long addr) { this.addr = addr; } @@ -398,7 +508,12 @@ public class ScriptPack extends AS3ClassTreeItem { public void injectDebugInfo(File directoryPath) { injectDebugInfo(directoryPath, "main"); } - + + /** + * Injects debugfile, debugline instructions into the code. + * @param directoryPath Directory path + * @param swfHash SWF identifier + */ public void injectDebugInfo(File directoryPath, String swfHash) { Map> bodyToPosToLine = new HashMap<>(); Map> bodyLineToPos = new HashMap<>(); @@ -694,6 +809,11 @@ public class ScriptPack extends AS3ClassTreeItem { ((Tag) abc.parentTag).setModified(true); } + /** + * Injects P-code debugfile, debugline instructions into the code. + * @param abcIndex Abc indexing + * @param swfHash SWF identifier + */ public void injectPCodeDebugInfo(int abcIndex, String swfHash) { Map bodyToIdentifier = new HashMap<>(); @@ -779,6 +899,10 @@ public class ScriptPack extends AS3ClassTreeItem { ((Tag) abc.parentTag).setModified(true); } + /** + * Gets method ids. + * @param methodInfos Result list of MethodIds + */ public void getMethodInfos(List methodInfos) { int script_init = abc.script_info.get(scriptIndex).init_index; methodInfos.add(new MethodId(GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, -1, script_init)); @@ -790,6 +914,11 @@ public class ScriptPack extends AS3ClassTreeItem { } } + /** + * Deletes the script pack. + * @param abc ABC file + * @param d Whether to delete + */ public void delete(ABC abc, boolean d) { ScriptInfo si = abc.script_info.get(scriptIndex); if (isSimple) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 72e75c5c0..0fb1d8cec 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -20,264 +20,40 @@ import com.jpexs.decompiler.flash.EndOfStreamException; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.CopyOutputStream; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorGetSet; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorJumps; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorRegistersOld; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorSimpleOld; -import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.AVM2DeobfuscatorZeroJumpsNullPushes; +import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.*; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2VerifyErrorException; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2Graph; import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphSource; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2InstructionFlag; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.UnknownInstruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Lf64Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Li8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sf64Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si32Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Si8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi16Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.Sxi8Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitNotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewActivationIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewArrayIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewClassIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewObjectIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugFileIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallMethodIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropLexIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallStaticIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallSuperVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfEqIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfGtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfLtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNGtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNLtIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfNeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictNeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal0Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocal3Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal0Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal1Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocal3Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.BkptIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.BkptLineIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.DeletePropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindDefIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetDescendantsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetGlobalSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetOuterScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetScopeObjectIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNextIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.InitPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextNameIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NextValueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnValueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ReturnVoidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetGlobalSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSlotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.ThrowIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.TimestampIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.AddPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.ConvertMIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.ConvertMPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.DecLocalPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.DecrementPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.DividePIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.IncLocalPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.IncrementPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.ModuloPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.MultiplyPIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.NegatePIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.PushDNanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.PushDecimalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.SubtractPIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.deprecated.CoerceBIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.deprecated.CoerceDIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.deprecated.CoerceIIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.deprecated.CoerceUIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.ConvertF4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.ConvertFIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.Lf32x4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.PushFloat4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.PushFloatIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.Sf32x4Ins; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.UnPlusIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.AbsJumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.AddDIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.AllocIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.CallInterfaceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.CallSuperIdIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.CodeGenOpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.ConcatIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.DecodeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.DelDescendantsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.DeletePropertyLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.DoubleToAtomIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.InvalidIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.MarkIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.PrologueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.PushConstantIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.SendEnterIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.SetPropertyLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.SweepIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.VerifyOpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.VerifyPassIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.WbIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNamespaceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushWithIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ApplyTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertBIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertDIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertOIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertUIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.InstanceOfIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.IsTypeLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.types.TypeOfIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.CheckFilterIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.StoreNewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.types.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.*; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; -import com.jpexs.decompiler.flash.abc.types.ABCException; -import com.jpexs.decompiler.flash.abc.types.AssignedValue; -import com.jpexs.decompiler.flash.abc.types.ConvertData; -import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.flash.abc.types.MethodInfo; -import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.*; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.abc.types.traits.Traits; @@ -289,160 +65,221 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; -import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor; -import com.jpexs.decompiler.graph.Block; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.SecondPassException; -import com.jpexs.decompiler.graph.SimpleValue; -import com.jpexs.decompiler.graph.TranslateStack; -import com.jpexs.decompiler.graph.TypeItem; +import com.jpexs.decompiler.graph.*; import com.jpexs.decompiler.graph.model.ScriptEndItem; import com.jpexs.helpers.Helper; import com.jpexs.helpers.Reference; import com.jpexs.helpers.ReflectionTools; import com.jpexs.helpers.stat.Statistics; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * Class representing AVM2 code inside a method body. * @author JPEXS */ public class AVM2Code implements Cloneable { + /** + * Logger for this class + */ private static final Logger logger = Logger.getLogger(AVM2Code.class.getName()); + /** + * Debug mode - prints debug information. + */ private static final boolean DEBUG_MODE = false; - public static int toSourceLimit = -1; - - public List code; - + /** + * Debug testing whether same code is write to output stream. + */ public static boolean DEBUG_REWRITE = false; + /** + * Limit of toSource calls + */ + public static int toSourceLimit = -1; + + /** + * List of instructions in this code. + */ + public List code; + + /** + * U30 value (unsigned up to 30-bit integer) + */ public static final int OPT_U30 = 0x100; + /** + * U8 value (unsigned 8 bit integer) + */ public static final int OPT_U8 = 0x200; + /** + * S24 value (signed 24 bit integer) + */ public static final int OPT_S24 = 0x300; + /** + * Case offsets + */ public static final int OPT_CASE_OFFSETS = 0x400; + /** + * S8 value (signed 8 bit integer) + */ public static final int OPT_S8 = 0x500; + /** + * S16 value (signed 16 bit integer) + */ public static final int OPT_S16 = 0x600; + /** + * Multiname index data + */ public static final int DAT_MULTINAME_INDEX = OPT_U30 + 0x01; + /** + * Argument count data + */ public static final int DAT_ARG_COUNT = OPT_U30 + 0x02; + /** + * Method index data + */ public static final int DAT_METHOD_INDEX = OPT_U30 + 0x03; + /** + * String index data + */ public static final int DAT_STRING_INDEX = OPT_U30 + 0x04; + /** + * Debug type data + */ public static final int DAT_DEBUG_TYPE = OPT_U8 + 0x05; + /** + * Register index data + */ public static final int DAT_REGISTER_INDEX = OPT_U8 + 0x06; + /** + * Line number data + */ public static final int DAT_LINENUM = OPT_U30 + 0x07; + /** + * Local register index data + */ public static final int DAT_LOCAL_REG_INDEX = OPT_U30 + 0x08; + /** + * Slot index data + */ public static final int DAT_SLOT_INDEX = OPT_U30 + 0x09; + /** + * Scope index data + */ public static final int DAT_SCOPE_INDEX = OPT_U30 + 0x0A; + /** + * Offset data + */ public static final int DAT_OFFSET = OPT_S24 + 0x0B; + /** + * Exception index data + */ public static final int DAT_EXCEPTION_INDEX = OPT_U30 + 0x0C; + /** + * Class index data + */ public static final int DAT_CLASS_INDEX = OPT_U30 + 0x0D; + /** + * Integer index data + */ public static final int DAT_INT_INDEX = OPT_U30 + 0x0E; + /** + * Unsigned integer index data + */ public static final int DAT_UINT_INDEX = OPT_U30 + 0x0F; + /** + * Double index data + */ public static final int DAT_DOUBLE_INDEX = OPT_U30 + 0x10; + /** + * Decimal index data + */ public static final int DAT_DECIMAL_INDEX = OPT_U30 + 0x11; + /** + * Case base offset data + */ public static final int DAT_CASE_BASEOFFSET = OPT_S24 + 0x12; + /** + * Number context data + */ public static final int DAT_NUMBER_CONTEXT = OPT_U30 + 0x13; + /** + * Dispatch ID data + */ public static final int DAT_DISPATCH_ID = OPT_U30 + 0x14; + /** + * Float index data + */ public static final int DAT_FLOAT_INDEX = OPT_U30 + 0x15; + /** + * Float4 index data + */ public static final int DAT_FLOAT4_INDEX = OPT_U30 + 0x16; + /** + * Namespace index data + */ public static final int DAT_NAMESPACE_INDEX = OPT_U30 + 0x17; - public static String operandTypeSizeToString(int ot) { - int sizeType = ot & 0xff00; - switch (sizeType) { - case OPT_U30: - return "U30"; - case OPT_S16: - return "S16"; - case OPT_U8: - return "U8"; - case OPT_S8: - return "S8"; - case OPT_S24: - return "S24"; - case OPT_CASE_OFFSETS: - return "S24(=n), S24[n]"; - } - return ""; - } + /** + * Map of operand type identifiers + */ private static Map operandDataTypeIdentifiers = ReflectionTools.getConstNamesMap(AVM2Code.class, Integer.class, "^DAT_(.*)$"); - public static String operandTypeToString(int ot, boolean withTypeSize) { - String typeSize = operandTypeSizeToString(ot); - if (ot == OPT_CASE_OFFSETS) { - return "number" + (withTypeSize ? "(U30)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", ..."; - } - if (operandDataTypeIdentifiers.containsKey(ot)) { - String dataType = operandDataTypeIdentifiers.get(ot); - return dataType + (withTypeSize ? "(" + typeSize + ")" : ""); - } else { - return typeSize; - } - - } - + /** + * Instruction aliases array + */ private static final String[][] instructionAliasesArray = { - //first is original name, then aliases - {"getlocal0", "getlocal_0"}, - {"getlocal1", "getlocal_1"}, - {"getlocal2", "getlocal_2"}, - {"getlocal3", "getlocal_3"}, - {"setlocal0", "setlocal_0"}, - {"setlocal1", "setlocal_1"}, - {"setlocal2", "setlocal_2"}, - {"setlocal3", "setlocal_3"} + //first is original name, then aliases + {"getlocal0", "getlocal_0"}, + {"getlocal1", "getlocal_1"}, + {"getlocal2", "getlocal_2"}, + {"getlocal3", "getlocal_3"}, + {"setlocal0", "setlocal_0"}, + {"setlocal1", "setlocal_1"}, + {"setlocal2", "setlocal_2"}, + {"setlocal3", "setlocal_3"} }; + + /** + * Instruction aliases map + */ public static final Map instructionAliases = new HashMap<>(); static { @@ -453,268 +290,274 @@ public class AVM2Code implements Cloneable { } } + /** + * Instruction set + */ public static final InstructionDefinition[] instructionSet = new InstructionDefinition[256]; + /** + * All instruction set + */ public static final InstructionDefinition[] allInstructionSet = new InstructionDefinition[]{ - /*0x00*/null, - /*0x01*/ new BkptIns(), - /*0x02*/ new NopIns(), - /*0x03*/ new ThrowIns(), - /*0x04*/ new GetSuperIns(), - /*0x05*/ new SetSuperIns(), - /*0x06*/ new DXNSIns(), - /*0x07*/ new DXNSLateIns(), - /*0x08*/ new KillIns(), - /*0x09*/ new LabelIns(), - /*0x0A*/ new Lf32x4Ins(), - /*0x0B*/ new Sf32x4Ins(), - /*0x0C*/ new IfNLtIns(), - /*0x0D*/ new IfNLeIns(), - /*0x0E*/ new IfNGtIns(), - /*0x0F*/ new IfNGeIns(), - /*0x10*/ new JumpIns(), - /*0x11*/ new IfTrueIns(), - /*0x12*/ new IfFalseIns(), - /*0x13*/ new IfEqIns(), - /*0x14*/ new IfNeIns(), - /*0x15*/ new IfLtIns(), - /*0x16*/ new IfLeIns(), - /*0x17*/ new IfGtIns(), - /*0x18*/ new IfGeIns(), - /*0x19*/ new IfStrictEqIns(), - /*0x1A*/ new IfStrictNeIns(), - /*0x1B*/ new LookupSwitchIns(), - /*0x1C*/ new PushWithIns(), - /*0x1D*/ new PopScopeIns(), - /*0x1E*/ new NextNameIns(), - /*0x1F*/ new HasNextIns(), - /*0x20*/ new PushNullIns(), - /*0x21*/ new PushUndefinedIns(), - /*0x22*/ new PushFloatIns(), //major 47+ - /*0x22*/ new PushConstantIns(), //before major 47 - /*0x23*/ new NextValueIns(), - /*0x24*/ new PushByteIns(), - /*0x25*/ new PushShortIns(), - /*0x26*/ new PushTrueIns(), - /*0x27*/ new PushFalseIns(), - /*0x28*/ new PushNanIns(), - /*0x29*/ new PopIns(), - /*0x2A*/ new DupIns(), - /*0x2B*/ new SwapIns(), - /*0x2C*/ new PushStringIns(), - /*0x2D*/ new PushIntIns(), - /*0x2E*/ new PushUIntIns(), - /*0x2F*/ new PushDoubleIns(), - /*0x30*/ new PushScopeIns(), - /*0x31*/ new PushNamespaceIns(), - /*0x32*/ new HasNext2Ins(), - /*0x33*/ new PushDecimalIns(), //pushdecimal(minor 17), lix8 (internal-only) according to Tamarin - /*0x34*/ new PushDNanIns(), //pushdnan according to Flex SDK, lix16 (internal-only) according to Tamarin - /*0x35*/ new Li8Ins(), - /*0x36*/ new Li16Ins(), - /*0x37*/ new Li32Ins(), - /*0x38*/ new Lf32Ins(), - /*0x39*/ new Lf64Ins(), - /*0x3A*/ new Si8Ins(), - /*0x3B*/ new Si16Ins(), - /*0x3C*/ new Si32Ins(), - /*0x3D*/ new Sf32Ins(), - /*0x3E*/ new Sf64Ins(), - /*0x3F*/ null, - /*0x40*/ new NewFunctionIns(), - /*0x41*/ new CallIns(), - /*0x42*/ new ConstructIns(), - /*0x43*/ new CallMethodIns(), - /*0x44*/ new CallStaticIns(), - /*0x45*/ new CallSuperIns(), - /*0x46*/ new CallPropertyIns(), - /*0x47*/ new ReturnVoidIns(), - /*0x48*/ new ReturnValueIns(), - /*0x49*/ new ConstructSuperIns(), - /*0x4A*/ new ConstructPropIns(), - /*0x4B*/ new CallSuperIdIns(), - /*0x4C*/ new CallPropLexIns(), - /*0x4D*/ new CallInterfaceIns(), - /*0x4E*/ new CallSuperVoidIns(), - /*0x4F*/ new CallPropVoidIns(), - /*0x50*/ new Sxi1Ins(), - /*0x51*/ new Sxi8Ins(), - /*0x52*/ new Sxi16Ins(), - /*0x53*/ new ApplyTypeIns(), - /*0x54*/ new PushFloat4Ins(), //major 47+ - /*0x55*/ new NewObjectIns(), - /*0x56*/ new NewArrayIns(), - /*0x57*/ new NewActivationIns(), - /*0x58*/ new NewClassIns(), - /*0x59*/ new GetDescendantsIns(), - /*0x5A*/ new NewCatchIns(), - /*0x5B*/ new DelDescendantsIns(), //deldescendants according to Flex, findpropglobalstrict(internal-only) according to Tamarin - /*0x5C*/ //new FindPropGlobalIns(), //Tamarin (internal-only) - /*0x5D*/ new FindPropertyStrictIns(), - /*0x5E*/ new FindPropertyIns(), - /*0x5F*/ new FindDefIns(), - /*0x60*/ new GetLexIns(), - /*0x61*/ new SetPropertyIns(), - /*0x62*/ new GetLocalIns(), - /*0x63*/ new SetLocalIns(), - /*0x64*/ new GetGlobalScopeIns(), - /*0x65*/ new GetScopeObjectIns(), - /*0x66*/ new GetPropertyIns(), - /*0x67*/ new GetOuterScopeIns(), // new GetPropertyLateIns() - /*0x68*/ new InitPropertyIns(), - /*0x69*/ new SetPropertyLateIns(), - /*0x6A*/ new DeletePropertyIns(), - /*0x6B*/ new DeletePropertyLateIns(), - /*0x6C*/ new GetSlotIns(), - /*0x6D*/ new SetSlotIns(), - /*0x6E*/ new GetGlobalSlotIns(), - /*0x6F*/ new SetGlobalSlotIns(), - /*0x70*/ new ConvertSIns(), - /*0x71*/ new EscXElemIns(), - /*0x72*/ new EscXAttrIns(), - /*0x73*/ new ConvertIIns(), - /*0x74*/ new ConvertUIns(), - /*0x75*/ new ConvertDIns(), - /*0x76*/ new ConvertBIns(), - /*0x77*/ new ConvertOIns(), - /*0x78*/ new CheckFilterIns(), - /*0x79*/ new ConvertMIns(), //minor 17 (Flex) - /*0x79*/ new ConvertFIns(), //major 47+, SWF 15+ - /*0x7A*/ new ConvertMPIns(), //minor 17 (Flex) - /*0x7A*/ new UnPlusIns(), //major 47+, SWF 15+ - /*0x7B*/ new ConvertF4Ins(), //major 47+, SWF 15+ - /*0x7C*/ null, - /*0x7D*/ null, - /*0x7E*/ null, - /*0x7F*/ null, - /*0x80*/ new CoerceIns(), - /*0x81*/ new CoerceBIns(), - /*0x82*/ new CoerceAIns(), - /*0x83*/ new CoerceIIns(), - /*0x84*/ new CoerceDIns(), - /*0x85*/ new CoerceSIns(), - /*0x86*/ new AsTypeIns(), - /*0x87*/ new AsTypeLateIns(), - /*0x88*/ new CoerceUIns(), - /*0x89*/ new CoerceOIns(), - /*0x8A*/ null, - /*0x8B*/ null, - /*0x8C*/ null, - /*0x8D*/ null, - /*0x8E*/ null, - /*0x8F*/ new NegatePIns(), - /*0x90*/ new NegateIns(), - /*0x91*/ new IncrementIns(), - /*0x92*/ new IncLocalIns(), - /*0x93*/ new DecrementIns(), - /*0x94*/ new DecLocalIns(), - /*0x95*/ new TypeOfIns(), - /*0x96*/ new NotIns(), - /*0x97*/ new BitNotIns(), - /*0x98*/ null, - /*0x99*/ null, - /*0x9A*/ new ConcatIns(), - /*0x9B*/ new AddDIns(), - /*0x9C*/ new IncrementPIns(), - /*0x9D*/ new IncLocalPIns(), - /*0x9E*/ new DecrementPIns(), - /*0x9F*/ new DecLocalPIns(), - /*0xA0*/ new AddIns(), - /*0xA1*/ new SubtractIns(), - /*0xA2*/ new MultiplyIns(), - /*0xA3*/ new DivideIns(), - /*0xA4*/ new ModuloIns(), - /*0xA5*/ new LShiftIns(), - /*0xA6*/ new RShiftIns(), - /*0xA7*/ new URShiftIns(), - /*0xA8*/ new BitAndIns(), - /*0xA9*/ new BitOrIns(), - /*0xAA*/ new BitXorIns(), - /*0xAB*/ new EqualsIns(), - /*0xAC*/ new StrictEqualsIns(), - /*0xAD*/ new LessThanIns(), - /*0xAE*/ new LessEqualsIns(), - /*0xAF*/ new GreaterThanIns(), - /*0xB0*/ new GreaterEqualsIns(), - /*0xB1*/ new InstanceOfIns(), - /*0xB2*/ new IsTypeIns(), - /*0xB3*/ new IsTypeLateIns(), - /*0xB4*/ new InIns(), - /*0xB5*/ new AddPIns(), - /*0xB6*/ new SubtractPIns(), - /*0xB7*/ new MultiplyPIns(), - /*0xB8*/ new DividePIns(), - /*0xB9*/ new ModuloPIns(), - /*0xBA*/ null, - /*0xBB*/ null, - /*0xBC*/ null, - /*0xBD*/ null, - /*0xBE*/ null, - /*0xBF*/ null, - /*0xC0*/ new IncrementIIns(), - /*0xC1*/ new DecrementIIns(), - /*0xC2*/ new IncLocalIIns(), - /*0xC3*/ new DecLocalIIns(), - /*0xC4*/ new NegateIIns(), - /*0xC5*/ new AddIIns(), - /*0xC6*/ new SubtractIIns(), - /*0xC7*/ new MultiplyIIns(), - /*0xC8*/ null, - /*0xC9*/ null, - /*0xCA*/ null, - /*0xCB*/ null, - /*0xCC*/ null, - /*0xCD*/ null, - /*0xCE*/ null, - /*0xCF*/ null, - /*0xD0*/ new GetLocal0Ins(), - /*0xD1*/ new GetLocal1Ins(), - /*0xD2*/ new GetLocal2Ins(), - /*0xD3*/ new GetLocal3Ins(), - /*0xD4*/ new SetLocal0Ins(), - /*0xD5*/ new SetLocal1Ins(), - /*0xD6*/ new SetLocal2Ins(), - /*0xD7*/ new SetLocal3Ins(), - /*0xD8*/ null, - /*0xD9*/ null, - /*0xDA*/ null, - /*0xDB*/ null, - /*0xDC*/ null, - /*0xDD*/ null, - /*0xDE*/ null, - /*0xDF*/ null, - /*0xE0*/ null, - /*0xE1*/ null, - /*0xE2*/ null, - /*0xE3*/ null, - /*0xE4*/ null, - /*0xE5*/ null, - /*0xE6*/ null, - /*0xE7*/ null, - /*0xE8*/ null, - /*0xE9*/ null, - /*0xEA*/ null, - /*0xEB*/ null, - /*0xEC*/ null, - /*0xED*/ new InvalidIns(), - /*0xEE*/ new AbsJumpIns(), - /*0xEF*/ new DebugIns(), - /*0xF0*/ new DebugLineIns(), - /*0xF1*/ new DebugFileIns(), - /*0xF2*/ new BkptLineIns(), - /*0xF3*/ new TimestampIns(), - /*0xF4*/ null, - /*0xF5*/ new VerifyPassIns(), - /*0xF6*/ new AllocIns(), - /*0xF7*/ new MarkIns(), - /*0xF8*/ new WbIns(), - /*0xF9*/ new PrologueIns(), - /*0xFA*/ new SendEnterIns(), - /*0xFB*/ new DoubleToAtomIns(), - /*0xFC*/ new SweepIns(), - /*0xFD*/ new CodeGenOpIns(), - /*0xFE*/ new VerifyOpIns(), - /*0xFF*/ new DecodeIns() + /*0x00*/ null, + /*0x01*/ new BkptIns(), + /*0x02*/ new NopIns(), + /*0x03*/ new ThrowIns(), + /*0x04*/ new GetSuperIns(), + /*0x05*/ new SetSuperIns(), + /*0x06*/ new DXNSIns(), + /*0x07*/ new DXNSLateIns(), + /*0x08*/ new KillIns(), + /*0x09*/ new LabelIns(), + /*0x0A*/ new Lf32x4Ins(), + /*0x0B*/ new Sf32x4Ins(), + /*0x0C*/ new IfNLtIns(), + /*0x0D*/ new IfNLeIns(), + /*0x0E*/ new IfNGtIns(), + /*0x0F*/ new IfNGeIns(), + /*0x10*/ new JumpIns(), + /*0x11*/ new IfTrueIns(), + /*0x12*/ new IfFalseIns(), + /*0x13*/ new IfEqIns(), + /*0x14*/ new IfNeIns(), + /*0x15*/ new IfLtIns(), + /*0x16*/ new IfLeIns(), + /*0x17*/ new IfGtIns(), + /*0x18*/ new IfGeIns(), + /*0x19*/ new IfStrictEqIns(), + /*0x1A*/ new IfStrictNeIns(), + /*0x1B*/ new LookupSwitchIns(), + /*0x1C*/ new PushWithIns(), + /*0x1D*/ new PopScopeIns(), + /*0x1E*/ new NextNameIns(), + /*0x1F*/ new HasNextIns(), + /*0x20*/ new PushNullIns(), + /*0x21*/ new PushUndefinedIns(), + /*0x22*/ new PushFloatIns(), //major 47+ + /*0x22*/ new PushConstantIns(), //before major 47 + /*0x23*/ new NextValueIns(), + /*0x24*/ new PushByteIns(), + /*0x25*/ new PushShortIns(), + /*0x26*/ new PushTrueIns(), + /*0x27*/ new PushFalseIns(), + /*0x28*/ new PushNanIns(), + /*0x29*/ new PopIns(), + /*0x2A*/ new DupIns(), + /*0x2B*/ new SwapIns(), + /*0x2C*/ new PushStringIns(), + /*0x2D*/ new PushIntIns(), + /*0x2E*/ new PushUIntIns(), + /*0x2F*/ new PushDoubleIns(), + /*0x30*/ new PushScopeIns(), + /*0x31*/ new PushNamespaceIns(), + /*0x32*/ new HasNext2Ins(), + /*0x33*/ new PushDecimalIns(), //pushdecimal(minor 17), lix8 (internal-only) according to Tamarin + /*0x34*/ new PushDNanIns(), //pushdnan according to Flex SDK, lix16 (internal-only) according to Tamarin + /*0x35*/ new Li8Ins(), + /*0x36*/ new Li16Ins(), + /*0x37*/ new Li32Ins(), + /*0x38*/ new Lf32Ins(), + /*0x39*/ new Lf64Ins(), + /*0x3A*/ new Si8Ins(), + /*0x3B*/ new Si16Ins(), + /*0x3C*/ new Si32Ins(), + /*0x3D*/ new Sf32Ins(), + /*0x3E*/ new Sf64Ins(), + /*0x3F*/ null, + /*0x40*/ new NewFunctionIns(), + /*0x41*/ new CallIns(), + /*0x42*/ new ConstructIns(), + /*0x43*/ new CallMethodIns(), + /*0x44*/ new CallStaticIns(), + /*0x45*/ new CallSuperIns(), + /*0x46*/ new CallPropertyIns(), + /*0x47*/ new ReturnVoidIns(), + /*0x48*/ new ReturnValueIns(), + /*0x49*/ new ConstructSuperIns(), + /*0x4A*/ new ConstructPropIns(), + /*0x4B*/ new CallSuperIdIns(), + /*0x4C*/ new CallPropLexIns(), + /*0x4D*/ new CallInterfaceIns(), + /*0x4E*/ new CallSuperVoidIns(), + /*0x4F*/ new CallPropVoidIns(), + /*0x50*/ new Sxi1Ins(), + /*0x51*/ new Sxi8Ins(), + /*0x52*/ new Sxi16Ins(), + /*0x53*/ new ApplyTypeIns(), + /*0x54*/ new PushFloat4Ins(), //major 47+ + /*0x55*/ new NewObjectIns(), + /*0x56*/ new NewArrayIns(), + /*0x57*/ new NewActivationIns(), + /*0x58*/ new NewClassIns(), + /*0x59*/ new GetDescendantsIns(), + /*0x5A*/ new NewCatchIns(), + /*0x5B*/ new DelDescendantsIns(), //deldescendants according to Flex, findpropglobalstrict(internal-only) according to Tamarin + /*0x5C*/ //new FindPropGlobalIns(), //Tamarin (internal-only) + /*0x5D*/ new FindPropertyStrictIns(), + /*0x5E*/ new FindPropertyIns(), + /*0x5F*/ new FindDefIns(), + /*0x60*/ new GetLexIns(), + /*0x61*/ new SetPropertyIns(), + /*0x62*/ new GetLocalIns(), + /*0x63*/ new SetLocalIns(), + /*0x64*/ new GetGlobalScopeIns(), + /*0x65*/ new GetScopeObjectIns(), + /*0x66*/ new GetPropertyIns(), + /*0x67*/ new GetOuterScopeIns(), // new GetPropertyLateIns() + /*0x68*/ new InitPropertyIns(), + /*0x69*/ new SetPropertyLateIns(), + /*0x6A*/ new DeletePropertyIns(), + /*0x6B*/ new DeletePropertyLateIns(), + /*0x6C*/ new GetSlotIns(), + /*0x6D*/ new SetSlotIns(), + /*0x6E*/ new GetGlobalSlotIns(), + /*0x6F*/ new SetGlobalSlotIns(), + /*0x70*/ new ConvertSIns(), + /*0x71*/ new EscXElemIns(), + /*0x72*/ new EscXAttrIns(), + /*0x73*/ new ConvertIIns(), + /*0x74*/ new ConvertUIns(), + /*0x75*/ new ConvertDIns(), + /*0x76*/ new ConvertBIns(), + /*0x77*/ new ConvertOIns(), + /*0x78*/ new CheckFilterIns(), + /*0x79*/ new ConvertMIns(), //minor 17 (Flex) + /*0x79*/ new ConvertFIns(), //major 47+, SWF 15+ + /*0x7A*/ new ConvertMPIns(), //minor 17 (Flex) + /*0x7A*/ new UnPlusIns(), //major 47+, SWF 15+ + /*0x7B*/ new ConvertF4Ins(), //major 47+, SWF 15+ + /*0x7C*/ null, + /*0x7D*/ null, + /*0x7E*/ null, + /*0x7F*/ null, + /*0x80*/ new CoerceIns(), + /*0x81*/ new CoerceBIns(), + /*0x82*/ new CoerceAIns(), + /*0x83*/ new CoerceIIns(), + /*0x84*/ new CoerceDIns(), + /*0x85*/ new CoerceSIns(), + /*0x86*/ new AsTypeIns(), + /*0x87*/ new AsTypeLateIns(), + /*0x88*/ new CoerceUIns(), + /*0x89*/ new CoerceOIns(), + /*0x8A*/ null, + /*0x8B*/ null, + /*0x8C*/ null, + /*0x8D*/ null, + /*0x8E*/ null, + /*0x8F*/ new NegatePIns(), + /*0x90*/ new NegateIns(), + /*0x91*/ new IncrementIns(), + /*0x92*/ new IncLocalIns(), + /*0x93*/ new DecrementIns(), + /*0x94*/ new DecLocalIns(), + /*0x95*/ new TypeOfIns(), + /*0x96*/ new NotIns(), + /*0x97*/ new BitNotIns(), + /*0x98*/ null, + /*0x99*/ null, + /*0x9A*/ new ConcatIns(), + /*0x9B*/ new AddDIns(), + /*0x9C*/ new IncrementPIns(), + /*0x9D*/ new IncLocalPIns(), + /*0x9E*/ new DecrementPIns(), + /*0x9F*/ new DecLocalPIns(), + /*0xA0*/ new AddIns(), + /*0xA1*/ new SubtractIns(), + /*0xA2*/ new MultiplyIns(), + /*0xA3*/ new DivideIns(), + /*0xA4*/ new ModuloIns(), + /*0xA5*/ new LShiftIns(), + /*0xA6*/ new RShiftIns(), + /*0xA7*/ new URShiftIns(), + /*0xA8*/ new BitAndIns(), + /*0xA9*/ new BitOrIns(), + /*0xAA*/ new BitXorIns(), + /*0xAB*/ new EqualsIns(), + /*0xAC*/ new StrictEqualsIns(), + /*0xAD*/ new LessThanIns(), + /*0xAE*/ new LessEqualsIns(), + /*0xAF*/ new GreaterThanIns(), + /*0xB0*/ new GreaterEqualsIns(), + /*0xB1*/ new InstanceOfIns(), + /*0xB2*/ new IsTypeIns(), + /*0xB3*/ new IsTypeLateIns(), + /*0xB4*/ new InIns(), + /*0xB5*/ new AddPIns(), + /*0xB6*/ new SubtractPIns(), + /*0xB7*/ new MultiplyPIns(), + /*0xB8*/ new DividePIns(), + /*0xB9*/ new ModuloPIns(), + /*0xBA*/ null, + /*0xBB*/ null, + /*0xBC*/ null, + /*0xBD*/ null, + /*0xBE*/ null, + /*0xBF*/ null, + /*0xC0*/ new IncrementIIns(), + /*0xC1*/ new DecrementIIns(), + /*0xC2*/ new IncLocalIIns(), + /*0xC3*/ new DecLocalIIns(), + /*0xC4*/ new NegateIIns(), + /*0xC5*/ new AddIIns(), + /*0xC6*/ new SubtractIIns(), + /*0xC7*/ new MultiplyIIns(), + /*0xC8*/ null, + /*0xC9*/ null, + /*0xCA*/ null, + /*0xCB*/ null, + /*0xCC*/ null, + /*0xCD*/ null, + /*0xCE*/ null, + /*0xCF*/ null, + /*0xD0*/ new GetLocal0Ins(), + /*0xD1*/ new GetLocal1Ins(), + /*0xD2*/ new GetLocal2Ins(), + /*0xD3*/ new GetLocal3Ins(), + /*0xD4*/ new SetLocal0Ins(), + /*0xD5*/ new SetLocal1Ins(), + /*0xD6*/ new SetLocal2Ins(), + /*0xD7*/ new SetLocal3Ins(), + /*0xD8*/ null, + /*0xD9*/ null, + /*0xDA*/ null, + /*0xDB*/ null, + /*0xDC*/ null, + /*0xDD*/ null, + /*0xDE*/ null, + /*0xDF*/ null, + /*0xE0*/ null, + /*0xE1*/ null, + /*0xE2*/ null, + /*0xE3*/ null, + /*0xE4*/ null, + /*0xE5*/ null, + /*0xE6*/ null, + /*0xE7*/ null, + /*0xE8*/ null, + /*0xE9*/ null, + /*0xEA*/ null, + /*0xEB*/ null, + /*0xEC*/ null, + /*0xED*/ new InvalidIns(), + /*0xEE*/ new AbsJumpIns(), + /*0xEF*/ new DebugIns(), + /*0xF0*/ new DebugLineIns(), + /*0xF1*/ new DebugFileIns(), + /*0xF2*/ new BkptLineIns(), + /*0xF3*/ new TimestampIns(), + /*0xF4*/ null, + /*0xF5*/ new VerifyPassIns(), + /*0xF6*/ new AllocIns(), + /*0xF7*/ new MarkIns(), + /*0xF8*/ new WbIns(), + /*0xF9*/ new PrologueIns(), + /*0xFA*/ new SendEnterIns(), + /*0xFB*/ new DoubleToAtomIns(), + /*0xFC*/ new SweepIns(), + /*0xFD*/ new CodeGenOpIns(), + /*0xFE*/ new VerifyOpIns(), + /*0xFF*/ new DecodeIns() }; // endoflist @@ -736,8 +579,8 @@ public class AVM2Code implements Cloneable { } for (int i = 0; - i < instructionSet.length; - i++) { + i < instructionSet.length; + i++) { if (instructionSet[i] == null) { instructionSet[i] = new UnknownInstruction(i); } @@ -745,26 +588,99 @@ public class AVM2Code implements Cloneable { } - public static final String IDENTOPEN = "/*IDENTOPEN*/"; + /** + * To source call counter. + */ + private int toSourceCount = 0; - public static final String IDENTCLOSE = "/*IDENTCLOSE*/"; + /** + * Converts operand type to string. + * @param ot Operand type + * @return Operand type as string + */ + public static String operandTypeSizeToString(int ot) { + int sizeType = ot & 0xff00; + switch (sizeType) { + case OPT_U30: + return "U30"; + case OPT_S16: + return "S16"; + case OPT_U8: + return "U8"; + case OPT_S8: + return "S8"; + case OPT_S24: + return "S24"; + case OPT_CASE_OFFSETS: + return "S24(=n), S24[n]"; + } + return ""; + } + + /** + * Converts operand type to string. + * @param ot Operand type + * @param withTypeSize Whether to include type size + * @return Operand type as string + */ + public static String operandTypeToString(int ot, boolean withTypeSize) { + String typeSize = operandTypeSizeToString(ot); + if (ot == OPT_CASE_OFFSETS) { + return "number" + (withTypeSize ? "(U30)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", offset" + (withTypeSize ? "(S24)" : "") + ", ..."; + } + if (operandDataTypeIdentifiers.containsKey(ot)) { + String dataType = operandDataTypeIdentifiers.get(ot); + return dataType + (withTypeSize ? "(" + typeSize + ")" : ""); + } else { + return typeSize; + } + + } + + + /** + * Constructs AVM2Code object. + */ public AVM2Code() { code = new ArrayList<>(); } + /** + * Constructs AVM2Code object. + * @param capacity Capacity + */ public AVM2Code(int capacity) { code = new ArrayList<>(capacity); } + /** + * Constructs AVM2Code object. + * @param instructions List of instructions + */ public AVM2Code(ArrayList instructions) { code = instructions; } + /** + * Executes the code. + * @param arguments Local registers values + * @param constants Constant pool + * @return Result of the execution + * @throws AVM2ExecutionException + */ public Object execute(HashMap arguments, AVM2ConstantPool constants) throws AVM2ExecutionException { return execute(arguments, constants, null); } + /** + * Executes the code. + * @param arguments Local registers values + * @param constants Constant pool + * @param runtimeInfo Runtime information + * @return Result of the execution + * @throws AVM2ExecutionException + */ public Object execute(HashMap arguments, AVM2ConstantPool constants, AVM2RuntimeInfo runtimeInfo) throws AVM2ExecutionException { int pos = 0; LocalDataArea lda = new LocalDataArea(); @@ -803,10 +719,24 @@ public class AVM2Code implements Cloneable { return Undefined.INSTANCE; } + /** + * Calculates the line debug file/line info and sets it to the instructions. + * @param abc ABC + */ public void calculateDebugFileLine(ABC abc) { calculateDebugFileLine(null, 0, 0, abc, new HashSet<>(), new HashSet<>()); } + /** + * Calculates the line debug file/line info and sets it to the instructions. + * @param debugFile Debug file + * @param debugLine Debug line + * @param pos Position + * @param abc ABC + * @param seen Seen instructions + * @param seenMethods Seen methods + * @return True of seen. + */ private boolean calculateDebugFileLine(String debugFile, int debugLine, int pos, ABC abc, Set seen, Set seenMethods) { while (pos < code.size()) { AVM2Instruction ins = code.get(pos); @@ -886,7 +816,7 @@ public class AVM2Code implements Cloneable { /** * Removes nonexistent indices to constants from instruction operands. * - * @param constants + * @param constants Constant pool */ public void removeWrongIndices(AVM2ConstantPool constants) { //This is DANGEROUS as it may alter instruction size which may lead to incorrect jump offsets!!! @@ -911,6 +841,12 @@ public class AVM2Code implements Cloneable { }*/ } + /** + * Constructs AVM2Code object from ABC input stream. + * @param ais ABC input stream + * @param body Method body + * @throws IOException + */ public AVM2Code(ABCInputStream ais, MethodBody body) throws IOException { Map codeMap = new HashMap<>(); DumpInfo diParent = ais.dumpInfo; @@ -1127,21 +1063,40 @@ public class AVM2Code implements Cloneable { } } + /** + * Trim code list to size. + */ public void compact() { if (code instanceof ArrayList) { ((ArrayList) code).trimToSize(); } } + /** + * Sets instruction operand. + * @param ip Instruction pointer + * @param operandIndex Operand index + * @param value Value + * @param body Method body + */ public void setInstructionOperand(int ip, int operandIndex, int value, MethodBody body) { int oldVal = code.get(ip).operands[ip]; code.get(ip).operands[ip] = value; } + /** + * Gets code bytes. + * @return Code bytes + */ public byte[] getBytes() { return getBytes(null); } + /** + * Gets code bytes. + * @param origBytes Original bytes + * @return Code bytes + */ public byte[] getBytes(byte[] origBytes) { ByteArrayOutputStream bos = new ByteArrayOutputStream(); @@ -1162,6 +1117,9 @@ public class AVM2Code implements Cloneable { return bos.toByteArray(); } + /** + * Sets instruction addesses by their position. + */ public void markOffsets() { long address = 0; for (int i = 0; i < code.size(); i++) { @@ -1170,6 +1128,10 @@ public class AVM2Code implements Cloneable { } } + /** + * To string. + * @return String + */ @Override public String toString() { StringBuilder s = new StringBuilder(); @@ -1180,10 +1142,21 @@ public class AVM2Code implements Cloneable { return s.toString(); } + /** + * Converts code to ASM source. + * @param abc ABC + * @return ASM source + */ public String toASMSource(ABC abc) { return toASMSource(abc, abc.constants); } + /** + * Converts code to ASM source. + * @param abc ABC + * @param constants Constant pool + * @return ASM source + */ public String toASMSource(ABC abc, AVM2ConstantPool constants) { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toASMSource(abc, constants, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); @@ -1191,10 +1164,31 @@ public class AVM2Code implements Cloneable { return writer.toString(); } + /** + * Converts code to ASM source. + * @param abc ABC + * @param constants Constant pool + * @param info Method info + * @param body Method body + * @param exportMode Export mode + * @param writer Writer + * @return Writer + */ public GraphTextWriter toASMSource(ABC abc, AVM2ConstantPool constants, MethodInfo info, MethodBody body, ScriptExportMode exportMode, GraphTextWriter writer) { return toASMSource(abc, constants, info, body, new ArrayList<>(), exportMode, writer); } + /** + * Converts code to ASM source. + * @param abc ABC + * @param constants Constant pool + * @param info Method info + * @param body Method body + * @param outputMap Output map - list of ips + * @param exportMode Export mode + * @param writer Writer + * @return Writer + */ public GraphTextWriter toASMSource(ABC abc, AVM2ConstantPool constants, MethodInfo info, MethodBody body, List outputMap, ScriptExportMode exportMode, GraphTextWriter writer) { if (info != null) { @@ -1349,6 +1343,12 @@ public class AVM2Code implements Cloneable { return writer; } + /** + * Gets important offsets. + * @param body Method body + * @param tryEnds Whether to include try ends + * @return Important offsets + */ public Set getImportantOffsets(MethodBody body, boolean tryEnds) { Set ret = new HashSet<>(); if (body != null) { @@ -1368,6 +1368,12 @@ public class AVM2Code implements Cloneable { return ret; } + /** + * Gets instruction at specific address. + * @param address Address + * @return Instruction or null if not found + * @throws ConvertException + */ public AVM2Instruction adr2ins(long address) throws ConvertException { int pos = adr2pos(address, false); if (pos == code.size()) { @@ -1378,10 +1384,23 @@ public class AVM2Code implements Cloneable { return code.get(pos); } + /** + * Converts address to position. + * @param address Address + * @return Position + * @throws ConvertException + */ public int adr2pos(long address) throws ConvertException { return adr2pos(address, false); } + /** + * Converts address to position. + * @param address Address + * @param nearest Whether to find nearest position + * @return Position + * @throws ConvertException + */ public int adr2pos(long address, boolean nearest) throws ConvertException { int ret = adr2posNoEx(address); if (ret < 0) { @@ -1393,6 +1412,11 @@ public class AVM2Code implements Cloneable { return ret; } + /** + * Converts address to position without throwing an exception. + * @param address Address + * @return Position + */ private int adr2posNoEx(long address) { int min = 0; int max = code.size() - 1; @@ -1416,6 +1440,11 @@ public class AVM2Code implements Cloneable { return -min - 1; } + /** + * Converts position to address. + * @param pos Position + * @return Address + */ public long pos2adr(int pos) { if (pos == code.size()) { return getEndOffset(); @@ -1423,6 +1452,10 @@ public class AVM2Code implements Cloneable { return (int) code.get(pos).getAddress(); } + /** + * Gets end address after the last instruction. + * @return End address + */ public long getEndOffset() { if (code.isEmpty()) { return 0; @@ -1432,8 +1465,12 @@ public class AVM2Code implements Cloneable { return (int) (ins.getAddress() + ins.getBytesLength()); } - private int toSourceCount = 0; - + /** + * Gets local register names from debug info. + * @param abc ABC + * @param maxRegs Maximal register id + * @return Map from register index to name + */ public Map getLocalRegNamesFromDebug(ABC abc, int maxRegs) { Map regIndexToName = new HashMap<>(); Map regNameToIndex = new HashMap<>(); @@ -1473,6 +1510,11 @@ public class AVM2Code implements Cloneable { return regIndexToName; } + /** + * Gets position after debugline instruction and after jump instruction. + * @param ip Current position + * @return New position + */ public int getIpThroughJumpAndDebugLine(int ip) { if (code.isEmpty()) { return ip; @@ -1495,6 +1537,12 @@ public class AVM2Code implements Cloneable { return ip; } + /** + * Gets address after debugline instruction and after jump instruction. + * @param addr Current address + * @return New address + * @throws ConvertException + */ public long getAddrThroughJumpAndDebugLine(long addr) throws ConvertException { return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true))); } @@ -1674,6 +1722,10 @@ public class AVM2Code implements Cloneable { }*/ } + /** + * Gets number of registers used in the code. + * @return Number of registers + */ public int getRegisterCount() { int maxRegister = -1; for (AVM2Instruction ins : code) { @@ -1691,6 +1743,12 @@ public class AVM2Code implements Cloneable { return maxRegister + 1; } + /** + * Gets types of local registers. + * @param constants Constant pool + * @param fullyQualifiedNames Fully qualified names + * @return Map from register id to type + */ public HashMap getLocalRegTypes(AVM2ConstantPool constants, List fullyQualifiedNames) { HashMap ret = new HashMap<>(); AVM2Instruction prev = null; @@ -1708,17 +1766,36 @@ public class AVM2Code implements Cloneable { } + /** + * Slot class + */ private class Slot { + /** + * Scope + */ public final GraphTargetItem scope; + /** + * Multiname + */ public final Multiname multiname; + /** + * Constructs a new Slot. + * @param scope Scope + * @param multiname Multiname + */ public Slot(GraphTargetItem scope, Multiname multiname) { this.scope = scope; this.multiname = multiname; } + /** + * Equals. + * @param obj Object + * @return True if equal + */ @Override public boolean equals(Object obj) { if (obj instanceof Slot) { @@ -1729,6 +1806,10 @@ public class AVM2Code implements Cloneable { return false; } + /** + * Hash code. + * @return Hash code + */ @Override public int hashCode() { int hash = 7; @@ -1738,10 +1819,22 @@ public class AVM2Code implements Cloneable { } } + /** + * Initializes counter of toSource calls. + */ public void initToSource() { toSourceCount = 0; } + /** + * Handles declaration of registers. + * @param minreg Minimal register id + * @param assignment Assignment + * @param declaredRegisters Declared registers + * @param declaredSlots Declared slots + * @param reg Register id + * @return Assignment + */ private GraphTargetItem handleDeclareReg(int minreg, GraphTargetItem assignment, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, int reg) { //do not add declarations for reserved local registers like function arguments @@ -1794,6 +1887,13 @@ public class AVM2Code implements Cloneable { return assignment; } + /** + * Calculates index of property name in the slot list. + * @param list List of slots + * @param propertyName Property name + * @param abc ABC + * @return Index of property name in the slot list or -1 if not found + */ private int slotListIndexOf(List list, String propertyName, ABC abc) { int index = 0; for (Slot s : list) { @@ -1805,6 +1905,20 @@ public class AVM2Code implements Cloneable { return -1; } + /** + * Injects declarations of registers/slots/properties etc. + * @param level Level + * @param paramNames Parameter names + * @param items Items + * @param minreg Minimal register id + * @param declaredRegisters Declared registers + * @param declaredSlots Declared slots + * @param declaredSlotsDec Declared slots declarations + * @param declaredProperties Declared properties + * @param declaredPropsDec Declared properties declarations + * @param abc ABC + * @param body Method body + */ private void injectDeclarations(int level, List paramNames, List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, List declaredProperties, List declaredPropsDec, ABC abc, MethodBody body) { //boolean hasActivation = abc.method_info.get(body.method_info).flagNeed_activation(); Map traits = new LinkedHashMap<>(); @@ -2062,6 +2176,29 @@ public class AVM2Code implements Cloneable { }*/ } + /** + * Converts code to source - list of GraphTargetItems. + * @param callStack Call stack + * @param abcIndex ABC indexing + * @param thisHasDefaultToPrimitive True if this has default to primitive + * @param convertData Convert data + * @param path Path + * @param methodIndex Method index + * @param isStatic True if static + * @param scriptIndex Script index + * @param classIndex Class index + * @param abc ABC + * @param body Method body + * @param localRegNames Local register names + * @param scopeStack Scope stack + * @param initializerType Initializer type + * @param fullyQualifiedNames Fully qualified names + * @param initTraits Initialized traits + * @param staticOperation Static operation + * @param localRegAssigmentIps Local register assignment IPs + * @return List of GraphTargetItems + * @throws InterruptedException + */ public List toGraphTargetItems(List callStack, AbcIndexing abcIndex, boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, Traits initTraits, int staticOperation, HashMap localRegAssigmentIps) throws InterruptedException { initToSource(); List list; @@ -2254,6 +2391,12 @@ public class AVM2Code implements Cloneable { return list; } + /** + * Updates instruction byte count at given address. + * @param instructionAddress Instruction address + * @param byteDelta Byte delta + * @param body Method body + */ public void updateInstructionByteCountByAddr(long instructionAddress, int byteDelta, MethodBody body) { if (byteDelta != 0) { updateOffsets(new OffsetUpdater() { @@ -2280,11 +2423,22 @@ public class AVM2Code implements Cloneable { } } + /** + * Updates instruction byte count at given position. + * @param pos Position + * @param byteDelta Byte delta + * @param body Method body + */ public void updateInstructionByteCount(int pos, int byteDelta, MethodBody body) { AVM2Instruction instruction = code.get(pos); updateInstructionByteCountByAddr(instruction.getAddress(), byteDelta, body); } + /** + * Updates offsets (jumps) in the code with given updater. + * @param updater Offset updater + * @param body Method body + */ public void updateOffsets(OffsetUpdater updater, MethodBody body) { for (int i = 0; i < code.size(); i++) { AVM2Instruction ins = code.get(i); @@ -2316,6 +2470,12 @@ public class AVM2Code implements Cloneable { } } + /** + * Fixes jumps to invalid addresses. + * @param path Path + * @param body Method body + * @throws InterruptedException + */ public void fixJumps(final String path, MethodBody body) throws InterruptedException { if (code.isEmpty()) { return; @@ -2351,6 +2511,10 @@ public class AVM2Code implements Cloneable { removeIgnored(body); } + /** + * Checks for invalid offsets (jumps) in the code. + * @param body Method body + */ public void checkValidOffsets(MethodBody body) { updateOffsets(new OffsetUpdater() { @Override @@ -2370,6 +2534,11 @@ public class AVM2Code implements Cloneable { }, body); } + /** + * Removes instruction at given position. + * @param pos Position + * @param body Method body + */ public void removeInstruction(int pos, MethodBody body) { if ((pos < 0) || (pos >= code.size())) { throw new IndexOutOfBoundsException(); @@ -2422,9 +2591,9 @@ public class AVM2Code implements Cloneable { * newinstruction is jump, the offset operand must be handled properly by * caller. * - * @param pos - * @param instruction - * @param body + * @param pos Position + * @param instruction Instruction + * @param body Method body */ public void replaceInstruction(int pos, AVM2Instruction instruction, MethodBody body) { AVM2Instruction oldInstruction = code.get(pos); @@ -2463,7 +2632,7 @@ public class AVM2Code implements Cloneable { * If newinstruction is jump, the offset operand must be handled properly by * caller. All old jump offsets to pos are targeted before new instruction. * - * @param pos Position in the list + * @param pos Position * @param instruction Instruction False means before new instruction * @param body Method body (used for try handling) */ @@ -2476,7 +2645,7 @@ public class AVM2Code implements Cloneable { * If newinstruction is jump, the offset operand must be handled properly by * caller. * - * @param pos Position in the list + * @param pos Position * @param instruction Instruction * @param mapOffsetsAfterIns Map all jumps to the pos after new instruction? * False means before new instruction @@ -2550,6 +2719,19 @@ public class AVM2Code implements Cloneable { //checkValidOffsets(body); } + /** + * Removes traps (deobfuscation) + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @param abc ABC + * @param scriptIndex Script index + * @param classIndex Class index + * @param isStatic True if static + * @param path Path + * @return 1 + * @throws InterruptedException + */ public int removeTraps(Trait trait, int methodInfo, MethodBody body, ABC abc, int scriptIndex, int classIndex, boolean isStatic, String path) throws InterruptedException { SWFDecompilerPlugin.fireAvm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); try (Statistics s = new Statistics("AVM2DeobfuscatorGetSet")) { @@ -2570,12 +2752,27 @@ public class AVM2Code implements Cloneable { return 1; } + /** + * Handles register while walking code for stats. + * @param stats Code stats + * @param reg Register + */ private void handleRegister(CodeStats stats, int reg) { if (reg + 1 > stats.maxlocal) { stats.maxlocal = reg + 1; } } + /** + * Walks code for stats. + * @param stats Code stats + * @param pos Position + * @param stack Stack + * @param scope Scope + * @param abc ABC + * @param autoFill Auto fill + * @return + */ private boolean walkCode(CodeStats stats, int pos, int stack, int scope, ABC abc, boolean autoFill) { while (pos < code.size()) { AVM2Instruction ins = code.get(pos); @@ -2678,6 +2875,14 @@ public class AVM2Code implements Cloneable { return true; } + /** + * Gets stats. + * @param abc ABC + * @param body Method body + * @param initScope Initial scope + * @param autoFill Auto fill + * @return Code stats + */ public CodeStats getStats(ABC abc, MethodBody body, int initScope, boolean autoFill) { CodeStats stats = new CodeStats(this); stats.initscope = initScope; @@ -2719,8 +2924,11 @@ public class AVM2Code implements Cloneable { //stats.maxscope+=initScope; return stats; } - - // simplified version of getStats. This method calculates only the maxlocal value + /** + * Calculates maxlocal value. + * Simplified version of getStats. + * @return Code stats + */ public CodeStats getMaxLocal() { CodeStats stats = new CodeStats(); for (AVM2Instruction ins : code) { @@ -2741,6 +2949,13 @@ public class AVM2Code implements Cloneable { return stats; } + /** + * Visit code. + * @param ip Position + * @param lastIp Last position + * @param refs Map from position to list of references + * @throws InterruptedException + */ private void visitCode(int ip, int lastIp, HashMap> refs) throws InterruptedException { Queue toVisit = new LinkedList<>(); Queue toVisitLast = new LinkedList<>(); @@ -2803,6 +3018,12 @@ public class AVM2Code implements Cloneable { } } + /** + * Visits code. + * @param body Method body + * @return Map from position to list of references + * @throws InterruptedException + */ public HashMap> visitCode(MethodBody body) throws InterruptedException { HashMap> refs = new HashMap<>(); for (int i = 0; i < code.size(); i++) { @@ -2819,6 +3040,11 @@ public class AVM2Code implements Cloneable { return refs; } + /** + * Remove instructions that are marked as ignored. + * @param body Method body + * @throws InterruptedException + */ public void removeIgnored(MethodBody body) throws InterruptedException { //System.err.println("removing ignored..."); for (int i = 0; i < code.size(); i++) { @@ -2830,10 +3056,23 @@ public class AVM2Code implements Cloneable { //System.err.println("/ignored removed"); } + /** + * Removes dead code. + * @param body Method body + * @return Number of removed instructions + * @throws InterruptedException + */ public int removeDeadCode(MethodBody body) throws InterruptedException { return removeDeadCode(body, new Reference<>(-1)); } + /** + * Removes dead code. + * @param body Method body + * @param minChangedIpRef Minimum changed instruction position (as reference) + * @return Number of removed instructions + * @throws InterruptedException + */ public int removeDeadCode(MethodBody body, Reference minChangedIpRef) throws InterruptedException { HashMap> refs = visitCode(body); int cnt = 0; @@ -2868,6 +3107,10 @@ public class AVM2Code implements Cloneable { return cnt; } + /** + * Replaces jumps to exit instructions (return, throw) with exit instruction. + * @return True if modified + */ public boolean inlineJumpExit() { boolean modified = false; int csize = code.size(); @@ -2895,63 +3138,12 @@ public class AVM2Code implements Cloneable { return modified; } - private static int getMostCommonIp(AVM2GraphSource code, List branches) { - List> reachable = new ArrayList<>(); - for (int i = 0; i < branches.size(); i++) { - List r = new ArrayList<>(); - getReachableIps(code, branches.get(i), r); - } - - int commonLevel; - Map levelMap = new HashMap<>(); - for (List first : reachable) { - int maxclevel = 0; - Set visited = new HashSet<>(); - for (Integer p : first) { - if (visited.contains(p)) { - continue; - } - visited.add(p); - boolean common = true; - commonLevel = 1; - for (List r : reachable) { - if (r == first) { - continue; - } - if (r.contains(p)) { - commonLevel++; - } - } - if (commonLevel <= maxclevel) { - continue; - } - maxclevel = commonLevel; - if (levelMap.containsKey(p)) { - if (levelMap.get(p) > commonLevel) { - commonLevel = levelMap.get(p); - } - } - levelMap.put(p, commonLevel); - if (common) { - //return p; - } - } - } - for (int i = reachable.size() - 1; i >= 2; i--) { - for (Integer p : levelMap.keySet()) { - if (levelMap.get(p) == i) { - return p; - } - } - } - for (Integer p : levelMap.keySet()) { - if (levelMap.get(p) == branches.size()) { - return p; - } - } - return -1; - } - + /** + * Gets reachable positions. + * @param code AVM2 code + * @param ip Current position + * @param reachable Result - list of reachable positions + */ public static void getReachableIps(AVM2GraphSource code, int ip, List reachable) { do { if (reachable.contains(ip)) { @@ -2971,10 +3163,25 @@ public class AVM2Code implements Cloneable { } while (ip < code.size()); } + /** + * Checks if currentIp is direct ancestor. + * @param currentIp Current position + * @param ancestor Ancestor position + * @param refs Map from position to list of references + * @return True if currentIp is direct ancestor + */ public static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs) { return isDirectAncestor(currentIp, ancestor, refs, new ArrayList<>()); } + /** + * Checks if currentIp is direct ancestor. + * @param currentIp Current position + * @param ancestor Ancestor position + * @param refs Map from position to list of references + * @param visited List of visited positions + * @return True if currentIp is direct ancestor + */ private static boolean isDirectAncestor(int currentIp, int ancestor, HashMap> refs, List visited) { if (currentIp == -1) { return true; @@ -3007,6 +3214,14 @@ public class AVM2Code implements Cloneable { return false; } + /** + * Gets reachable positions prior the current position. + * @param currentIp Current position + * @param refs Map from position to list of references + * @param reachable Result - set of reachable positions + * @param visited List of visited positions + * @return True if visited does not contain currentIp + */ public static boolean getPreviousReachableIps(int currentIp, HashMap> refs, Set reachable, Set visited) { do { if (visited.contains(currentIp)) { @@ -3038,6 +3253,10 @@ public class AVM2Code implements Cloneable { return true; } + /** + * Clones AVM2 code. + * @return Cloned AVM2 code + */ @Override public AVM2Code clone() { try { @@ -3056,6 +3275,11 @@ public class AVM2Code implements Cloneable { } } + /** + * Marks virtual addresses. + * Virtual address is the address of the instruction before any modifications to the code + * like deobfuscation etc. + */ public void markVirtualAddresses() { for (AVM2Instruction ins : code) { ins.setVirtualAddress(ins.getAddress()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java index 6ebe00595..0f0fee2ac 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java @@ -19,11 +19,7 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.abc.ABCVersionRequirements; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.types.Decimal; -import com.jpexs.decompiler.flash.abc.types.Float4; -import com.jpexs.decompiler.flash.abc.types.Multiname; -import com.jpexs.decompiler.flash.abc.types.Namespace; -import com.jpexs.decompiler.flash.abc.types.NamespaceSet; +import com.jpexs.decompiler.flash.abc.types.*; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.types.annotations.Internal; @@ -32,88 +28,153 @@ import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.HashArrayList; import com.jpexs.helpers.utf8.Utf8PrintWriter; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.logging.Logger; /** - * + * AVM2 constant pool. * @author JPEXS */ public class AVM2ConstantPool implements Cloneable { + /** + * Logger + */ private static final Logger logger = Logger.getLogger(AVM2ConstantPool.class.getName()); + /** + * Constant pool of integers + */ @SWFField private HashArrayList constant_int = new HashArrayList<>(); + /** + * Constant pool of unsigned integers + */ @SWFField private HashArrayList constant_uint = new HashArrayList<>(); + /** + * Constant pool of doubles + */ @SWFField private HashArrayList constant_double = new HashArrayList<>(); + /** + * Constant pool of decimals + */ @SWFField @ABCVersionRequirements(exactMinor = 17) private HashArrayList constant_decimal = new HashArrayList<>(); + /** + * Constant pool of floats + */ @SWFField @SWFVersion(from = 16) @ABCVersionRequirements(minMajor = 47, minMinor = 16) private HashArrayList constant_float = new HashArrayList<>(); - /* Only for some versions */ + /** + * Constant pool of float4 + */ @SWFField @SWFVersion(from = 16) @ABCVersionRequirements(minMajor = 47, minMinor = 16) private HashArrayList constant_float4 = new HashArrayList<>(); + /** + * Constant pool of strings + */ @SWFField private HashArrayList constant_string = new HashArrayList<>(); + /** + * Constant pool of namespaces + */ @SWFField private HashArrayList constant_namespace = new HashArrayList<>(); + /** + * Constant pool of namespace sets + */ @SWFField private HashArrayList constant_namespace_set = new HashArrayList<>(); + /** + * Constant pool of multinames + */ @SWFField private HashArrayList constant_multiname = new HashArrayList<>(); + /** + * Constructs a new AVM2 constant pool. + */ public AVM2ConstantPool() { } + /** + * Cache of string to dottted chain conversion. + */ @Internal public Map dottedChainCache = new HashMap<>(); + /** + * Cache of multiname namespace to dotted chain conversion. + */ @Internal public Map multinameWithNamespaceCache = new HashMap<>(); + /** + * Gets cached multiname with namespace dottedchain. + * @param multiName Multiname + * @return Dotted chain + */ public DottedChain getCachedMultinameWithNamespace(Multiname multiName) { return multinameWithNamespaceCache.get(multiName); } + /** + * Caches multiname with namespace dotted chain. + * @param multiName Multiname + * @param multinameWithNamespace Dotted chain + */ public void cacheMultinameWithNamespace(Multiname multiName, DottedChain multinameWithNamespace) { multinameWithNamespaceCache.put(multiName, multinameWithNamespace); } + /** + * Clears cached multinames. + */ public void clearCachedMultinames() { multinameWithNamespaceCache.clear(); } + /** + * Gets cached dotted chains. + */ public void clearCachedDottedChains() { dottedChainCache.clear(); } + /** + * Ensures that list has at least one - null - element. + * @param list List + */ private void ensureDefault(List list) { if (list.isEmpty()) { list.add(null); } } + /** + * Ensures that list of integers has the initial capacity. + * @param capacity Capacity + */ public void ensureIntCapacity(int capacity) { constant_int.ensureCapacity(capacity); if (capacity > 0) { @@ -121,6 +182,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of namespaces has the initial capacity. + * @param capacity Capacity + */ public void ensureNamespaceCapacity(int capacity) { constant_namespace.ensureCapacity(capacity); if (capacity > 0) { @@ -128,6 +193,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of namespace sets has the initial capacity. + * @param capacity Capacity + */ public void ensureNamespaceSetCapacity(int capacity) { constant_namespace_set.ensureCapacity(capacity); if (capacity > 0) { @@ -135,6 +204,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of multinames has the initial capacity. + * @param capacity Capacity + */ public void ensureMultinameCapacity(int capacity) { constant_multiname.ensureCapacity(capacity); if (capacity > 0) { @@ -142,6 +215,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of unsigned integers has the initial capacity. + * @param capacity Capacity + */ public void ensureUIntCapacity(int capacity) { constant_uint.ensureCapacity(capacity); if (capacity > 0) { @@ -149,6 +226,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of doubles has the initial capacity. + * @param capacity Capacity + */ public void ensureDoubleCapacity(int capacity) { constant_double.ensureCapacity(capacity); if (capacity > 0) { @@ -156,6 +237,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of decimals has the initial capacity. + * @param capacity Capacity + */ public void ensureDecimalCapacity(int capacity) { constant_decimal.ensureCapacity(capacity); if (capacity > 0) { @@ -163,6 +248,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of floats has the initial capacity. + * @param capacity Capacity + */ public void ensureFloatCapacity(int capacity) { constant_float.ensureCapacity(capacity); if (capacity > 0) { @@ -170,6 +259,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of float4 has the initial capacity. + * @param capacity Capacity + */ public void ensureFloat4Capacity(int capacity) { constant_float4.ensureCapacity(capacity); if (capacity > 0) { @@ -177,6 +270,10 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Ensures that list of strings has the initial capacity. + * @param capacity Capacity + */ public void ensureStringCapacity(int capacity) { constant_string.ensureCapacity(capacity); if (capacity > 0) { @@ -184,6 +281,11 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Adds an integer to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addInt(int value) { ensureDefault(constant_int); value = (int) value; @@ -191,28 +293,54 @@ public class AVM2ConstantPool implements Cloneable { return constant_int.size() - 1; } + /** + * Adds a namespace to the constant pool. + * @param ns Namespace + * @return Index + */ public synchronized int addNamespace(Namespace ns) { ensureDefault(constant_namespace); constant_namespace.add(ns); return constant_namespace.size() - 1; } + /** + * Adds a namespace to the constant pool. + * @param kind Kind + * @param nameIndex Name index + * @return Index + */ public int addNamespace(int kind, int nameIndex) { return addNamespace(new Namespace(kind, nameIndex)); } + /** + * Adds a namespace set to the constant pool. + * @param nss Namespace set + * @return Index + */ public synchronized int addNamespaceSet(NamespaceSet nss) { ensureDefault(constant_namespace_set); constant_namespace_set.add(nss); return constant_namespace_set.size() - 1; } + /** + * Adds a multiname to the constant pool. + * @param m Multiname + * @return Index + */ public synchronized int addMultiname(Multiname m) { ensureDefault(constant_multiname); constant_multiname.add(m); return constant_multiname.size() - 1; } + /** + * Adds an unsigned integer to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addUInt(long value) { ensureDefault(constant_uint); value &= 0xffffffffL; @@ -220,86 +348,176 @@ public class AVM2ConstantPool implements Cloneable { return constant_uint.size() - 1; } + /** + * Adds a double to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addDouble(double value) { ensureDefault(constant_double); constant_double.add(value); return constant_double.size() - 1; } + /** + * Adds a decimal to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addDecimal(Decimal value) { ensureDefault(constant_decimal); constant_decimal.add(value); return constant_decimal.size() - 1; } + /** + * Adds a float to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addFloat(Float value) { ensureDefault(constant_float); constant_float.add(value); return constant_float.size() - 1; } + /** + * Adds a float4 to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addFloat4(Float4 value) { ensureDefault(constant_float4); constant_float4.add(value); return constant_float4.size() - 1; } + /** + * Adds a string to the constant pool. + * @param value Value + * @return Index + */ public synchronized int addString(String value) { ensureDefault(constant_string); constant_string.add(value); return constant_string.size() - 1; } + /** + * Sets an integer at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public long setInt(int index, int value) { constant_int.set(index, value); return value; } + /** + * Sets a namespace at the specified index. + * @param index Index + * @param ns Namespace + * @return Namespace + */ public Namespace setNamespace(int index, Namespace ns) { constant_namespace.set(index, ns); return ns; } + /** + * Sets a namespace set at the specified index. + * @param index Index + * @param nss Namespace set + * @return Namespace set + */ public NamespaceSet setNamespaceSet(int index, NamespaceSet nss) { constant_namespace_set.set(index, nss); return nss; } + /** + * Sets a multiname at the specified index. + * @param index Index + * @param m Multiname + * @return Multiname + */ public Multiname setMultiname(int index, Multiname m) { constant_multiname.set(index, m); return m; } + /** + * Sets an unsigned integer at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public long setUInt(int index, long value) { constant_uint.set(index, value); return value; } + /** + * Sets a double at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public double setDouble(int index, double value) { constant_double.set(index, value); return value; } + /** + * Sets a decimal at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public Decimal setDecimal(int index, Decimal value) { constant_decimal.set(index, value); return value; } + /** + * Sets a float at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public float setFloat(int index, float value) { constant_float.set(index, value); return value; } + /** + * Sets a float4 at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public Float4 setFloat4(int index, Float4 value) { constant_float4.set(index, value); return value; } + /** + * Sets a string at the specified index. + * @param index Index + * @param value Value + * @return Value + */ public String setString(int index, String value) { constant_string.set(index, value); return value; } + /** + * Gets an integer at the specified index. + * @param index Index + * @return Value + */ public int getInt(int index) { if (index == 0) { return 0; @@ -307,10 +525,20 @@ public class AVM2ConstantPool implements Cloneable { return constant_int.get(index); } + /** + * Gets a namespace at the specified index. + * @param index Index + * @return Namespace + */ public Namespace getNamespace(int index) { return constant_namespace.get(index); } + /** + * Gets a namespace set at the specified index. + * @param index Index + * @return Namespace set + */ public NamespaceSet getNamespaceSet(int index) { return constant_namespace_set.get(index); } @@ -321,7 +549,7 @@ public class AVM2ConstantPool implements Cloneable { * * @param cpool * @param index MULTINAME index - * @return + * @return QNAME index */ public int convertToQname(AVM2ConstantPool cpool, int index) { Multiname mx = cpool.getMultiname(index); @@ -339,10 +567,20 @@ public class AVM2ConstantPool implements Cloneable { return index; } + /** + * Gets a multiname at the specified index. + * @param index Index + * @return Multiname + */ public Multiname getMultiname(int index) { return constant_multiname.get(index); } + /** + * Gets an unsigned integer at the specified index. + * @param index Index + * @return Value + */ public long getUInt(int index) { if (index == 0) { return 0; @@ -350,6 +588,11 @@ public class AVM2ConstantPool implements Cloneable { return constant_uint.get(index); } + /** + * Gets a double at the specified index. + * @param index Index + * @return Value + */ public double getDouble(int index) { if (index == 0) { return 0; @@ -357,62 +600,129 @@ public class AVM2ConstantPool implements Cloneable { return constant_double.get(index); } + /** + * Gets a decimal at the specified index. + * @param index Index + * @return Value + */ public Decimal getDecimal(int index) { return constant_decimal.get(index); } + /** + * Gets a float at the specified index. + * @param index Index + * @return Value + */ public Float getFloat(int index) { return constant_float.get(index); } + /** + * Gets a float4 at the specified index. + * @param index Index + * @return Value + */ public Float4 getFloat4(int index) { return constant_float4.get(index); } + /** + * Gets a string at the specified index. + * @param index Index + * @return Value + */ public String getString(int index) { return constant_string.get(index); } + /** + * Gets the number of integers in the constant pool. + * @return Count + */ public int getIntCount() { return constant_int.size(); } + /** + * Gets the number of namespaces in the constant pool. + * @return Count + */ public int getNamespaceCount() { return constant_namespace.size(); } + /** + * Gets the number of namespace sets in the constant pool. + * @return Count + */ public int getNamespaceSetCount() { return constant_namespace_set.size(); } + /** + * Gets the number of multinames in the constant pool. + * @return Count + */ public int getMultinameCount() { return constant_multiname.size(); } + /** + * Gets the number of unsigned integers in the constant pool. + * @return Count + */ public int getUIntCount() { return constant_uint.size(); } + /** + * Gets the number of doubles in the constant pool. + * @return Count + */ public int getDoubleCount() { return constant_double.size(); } + /** + * Gets the number of decimals in the constant pool. + * @return Count + */ public int getDecimalCount() { return constant_decimal.size(); } + /** + * Gets the number of floats in the constant pool. + * @return Count + */ public int getFloatCount() { return constant_float.size(); } + /** + * Gets the number of float4s in the constant pool. + * @return Count + */ public int getFloat4Count() { return constant_float4.size(); } + /** + * Gets the number of strings in the constant pool. + * @return Count + */ public int getStringCount() { return constant_string.size(); } + /** + * Gets sub index of namespace with the specified namespace id. + * The namespaces that have the same name and kind are considered to be the same, + * so they have assigned a sub index to distinguish them. + * @param namespaceId Namespace id + * @return Sub index + */ public int getNamespaceSubIndex(int namespaceId) { Namespace ns = constant_namespace.get(namespaceId); int index = 0; @@ -424,6 +734,13 @@ public class AVM2ConstantPool implements Cloneable { return index; } + /** + * Gets the namespace id of the namespace with the specified kind, name index and sub index. + * @param kind Kind + * @param nameIndex Name index + * @param index Sub index + * @return Namespace id + */ private int getNamespaceId(int kind, int nameIndex, int index) { for (int n = 1; n < constant_namespace.size(); n++) { Namespace ns = constant_namespace.get(n); @@ -437,6 +754,14 @@ public class AVM2ConstantPool implements Cloneable { return -1; } + /** + * Gets the namespace id of the namespace with the specified kind, name and sub index. + * @param kind Kind + * @param nameIndex Name index + * @param index Sub index + * @param add Whether to add the namespace if it does not exist + * @return Namespace id + */ public int getNamespaceId(int kind, int nameIndex, int index, boolean add) { int id = getNamespaceId(kind, nameIndex, index); if (add && id == -1) { @@ -445,6 +770,14 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets the namespace id of the namespace with the specified kind, name and sub index. + * @param kind Kind + * @param name Name + * @param index Sub index + * @param add Whether to add the namespace if it does not exist + * @return Namespace id + */ public int getNamespaceId(int kind, String name, int index, boolean add) { int nameIndex = getStringId(name, add); if (nameIndex == -1) { @@ -454,6 +787,13 @@ public class AVM2ConstantPool implements Cloneable { return getNamespaceId(kind, nameIndex, index, add); } + /** + * Gets the namespace id of the namespace with the specified kind, name and sub index. + * @param kind Kind + * @param name Name + * @param index Sub index + * @return Namespace id + */ public int getNamespaceId(int kind, DottedChain name, int index, boolean add) { int nameIndex = getStringId(name, add); if (nameIndex == -1) { @@ -463,6 +803,12 @@ public class AVM2ConstantPool implements Cloneable { return getNamespaceId(kind, nameIndex, index, add); } + /** + * Gets decimal id. + * @param val Decimal + * @param add Whether to add the decimal if it does not exist + * @return Decimal id + */ public int getDecimalId(Decimal val, boolean add) { int id = getDecimalId(val); if (add && id == -1) { @@ -471,22 +817,52 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets decimal id. + * @param value Value + * @return Decimal id + */ private int getDecimalId(Decimal value) { return constant_decimal.indexOf(value); } + /** + * Gets Qname id. + * @param name Name + * @param namespaceKind Namespace kind + * @param namespaceName Namespace name + * @param add Whether to add the Qname if it does not exist + * @return Qname id + */ public int getQnameId(String name, int namespaceKind, String namespaceName, boolean add) { return getMultinameId(Multiname.createQName(false, getStringId(name, add), getNamespaceId(namespaceKind, namespaceName, 0, add)), add); } + /** + * Gets public Qname id. + * @param name Name + * @param add Whether to add the Qname if it does not exist + * @return Qname id + */ public int getPublicQnameId(String name, boolean add) { return getQnameId(name, Namespace.KIND_PACKAGE, "", add); } + /** + * Gets Multiname id. + * @param value Multiname + * @return Multiname id + */ private int getMultinameId(Multiname value) { return constant_multiname.indexOf(value); } + /** + * Gets Multiname id. + * @param val Multiname + * @param add Whether to add the Multiname if it does not exist + * @return Multiname id + */ public int getMultinameId(Multiname val, boolean add) { int id = getMultinameId(val); if (add && id == -1) { @@ -496,11 +872,11 @@ public class AVM2ConstantPool implements Cloneable { } /** - * Finds multiname index based on multiname in other constant pool + * Finds multiname index based on multiname in other constant pool. * - * @param val - * @param origConst - * @return + * @param val Value + * @param origConst Original constant pool + * @return List of multiname indexes */ public List getMultinameIds(Multiname val, AVM2ConstantPool origConst) { @@ -513,10 +889,21 @@ public class AVM2ConstantPool implements Cloneable { return ret; } + /** + * Gets string id. + * @param value Value + * @return String id + */ private int getStringId(String value) { return constant_string.indexOf(value); } + /** + * Gets string id. + * @param val Value + * @param add Whether to add the string if it does not exist + * @return String id + */ public int getStringId(String val, boolean add) { if (val == null) { return 0; @@ -528,6 +915,12 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets string id. + * @param val Value + * @param add Whether to add the string if it does not exist + * @return String id + */ public int getStringId(DottedChain val, boolean add) { if (val == null) { return 0; @@ -536,10 +929,21 @@ public class AVM2ConstantPool implements Cloneable { return getStringId(val.toRawString(), add); } + /** + * Gets integer id. + * @param value Value + * @return Integer id + */ private int getIntId(int value) { return constant_int.indexOf(value); } + /** + * Gets integer id. + * @param val Value + * @param add Whether to add the integer if it does not exist + * @return Integer id + */ public int getIntId(int val, boolean add) { int id = getIntId(val); if (add && id == -1) { @@ -548,6 +952,11 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets namespace set id. + * @param namespaces Namespaces + * @return Namespace set id + */ private int getNamespaceSetId(int[] namespaces) { loopi: for (int i = 1; i < constant_namespace_set.size(); i++) { @@ -572,6 +981,12 @@ public class AVM2ConstantPool implements Cloneable { return -1; } + /** + * Gets namespace set id. + * @param namespaces Namespaces + * @param add Whether to add the namespace set if it does not exist + * @return Namespace set id + */ public int getNamespaceSetId(int[] namespaces, boolean add) { int id = getNamespaceSetId(namespaces); if (add && id == -1) { @@ -580,10 +995,21 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets unsigned integer id. + * @param value Value + * @return Unsigned integer id + */ private int getUIntId(long value) { return constant_uint.indexOf(value); } + /** + * Gets unsigned integer id. + * @param val Value + * @param add Whether to add the unsigned integer if it does not exist + * @return Unsigned integer id + */ public int getUIntId(long val, boolean add) { int id = getUIntId(val); if (add && id == -1) { @@ -592,10 +1018,21 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets double id. + * @param value Value + * @return Double id + */ private int getDoubleId(double value) { return constant_double.indexOf(value); } + /** + * Gets double id. + * @param val Value + * @param add Whether to add the double if it does not exist + * @return Double id + */ public int getDoubleId(double val, boolean add) { int id = getDoubleId(val); if (add && id == -1) { @@ -604,10 +1041,21 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets float id. + * @param value Value + * @return Float id + */ private int getFloatId(float value) { return constant_float.indexOf(value); } + /** + * Gets float id. + * @param val Value + * @param add Whether to add the float if it does not exist + * @return Float id + */ public int getFloatId(float val, boolean add) { int id = getFloatId(val); if (add && id == -1) { @@ -616,10 +1064,21 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets float4 id. + * @param value Value + * @return Float4 id + */ private int getFloat4Id(Float4 value) { return constant_float4.indexOf(value); } + /** + * Gets float4 id. + * @param val Value + * @param add Whether to add the float4 if it does not exist + * @return Float4 id + */ public int getFloat4Id(Float4 val, boolean add) { int id = getFloat4Id(val); if (add && id == -1) { @@ -628,6 +1087,11 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Gets the string at the specified index as dotted chain. + * @param index Index + * @return Dotted chain + */ public DottedChain getDottedChain(int index) { String str = getString(index); DottedChain chain = dottedChainCache.get(str); @@ -639,6 +1103,10 @@ public class AVM2ConstantPool implements Cloneable { return chain; } + /** + * Dumps the constant pool. + * @param writer Writer + */ public void dump(Utf8PrintWriter writer) { for (int i = 1; i < constant_int.size(); i++) { writer.println("INT[" + i + "]=" + constant_int.get(i)); @@ -664,6 +1132,11 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Converts multiname to string. + * @param index Multiname index + * @return String + */ public String multinameToString(int index) { if (index == 0) { return "null"; @@ -671,6 +1144,11 @@ public class AVM2ConstantPool implements Cloneable { return constant_multiname.get(index).toString(this, new ArrayList<>()); } + /** + * Converts namespace to string. + * @param index Namespace index + * @return String + */ public String namespaceToString(int index) { if (index == 0) { return "null"; @@ -678,6 +1156,11 @@ public class AVM2ConstantPool implements Cloneable { return constant_namespace.get(index).toString(this); } + /** + * Converts namespace set to string. + * @param index Namespace set index + * @return String + */ public String namespaceSetToString(int index) { if (index == 0) { return "null"; @@ -685,6 +1168,10 @@ public class AVM2ConstantPool implements Cloneable { return constant_namespace_set.get(index).toString(this); } + /** + * Clones the constant pool. + * @return Cloned constant pool + */ @Override public AVM2ConstantPool clone() { try { @@ -707,6 +1194,11 @@ public class AVM2ConstantPool implements Cloneable { } } + /** + * Makes a push instruction for the specified value. + * @param ovalue Value + * @return Instruction + */ public AVM2Instruction makePush(Object ovalue) { if (ovalue instanceof Integer) { int value = (Integer) ovalue; @@ -740,19 +1232,19 @@ public class AVM2ConstantPool implements Cloneable { } /** - * Merges second constantpool into this one + * Merges second constantpool into this one. * - * @param secondPool - * @param stringMap - * @param intMap - * @param uintMap - * @param doubleMap - * @param floatMap - * @param float4Map - * @param decimalMap - * @param namespaceMap - * @param namespaceSetMap - * @param multinameMap + * @param secondPool Second constant pool + * @param stringMap String map + * @param intMap Integer map + * @param uintMap Unsigned integer map + * @param doubleMap Double map + * @param floatMap Float map + * @param float4Map Float4 map + * @param decimalMap Decimal map + * @param namespaceMap Namespace map + * @param namespaceSetMap Namespace set map + * @param multinameMap Multiname map */ public void merge(AVM2ConstantPool secondPool, Map stringMap, Map intMap, Map uintMap, Map doubleMap, Map floatMap, Map float4Map, Map decimalMap, Map namespaceMap, Map namespaceSetMap, Map multinameMap) { stringMap.put(0, 0); @@ -867,6 +1359,10 @@ public class AVM2ConstantPool implements Cloneable { } + /** + * Checks cyclic type names. + * A type name is cyclic if it references itself or any of its children. + */ public void checkCyclicTypeNames() { for (int i = 0; i < constant_multiname.size(); i++) { Multiname.checkTypeNameCyclic(this, i); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java index 96add38e6..bd3eed5e0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java @@ -21,42 +21,76 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.RenameType; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; import java.util.regex.Pattern; /** - * + * AVM2 deobfuscation. * @author JPEXS */ public class AVM2Deobfuscation { + /** + * Default size of random word. + */ private static final int DEFAULT_FOO_SIZE = 10; + /** + * Valid characters for first character of name. + */ public static final String VALID_FIRST_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$"; + /** + * Valid characters for next characters of name. + */ public static final String VALID_NEXT_CHARACTERS = VALID_FIRST_CHARACTERS + "0123456789"; + /** + * Valid characters for namespace. + */ public static final String VALID_NS_CHARACTERS = ".:"; + /** + * SWF file. + */ private final SWF swf; + /** + * AVM2 constant pool. + */ private final AVM2ConstantPool constants; + /** + * Usage types count. + */ private final Map usageTypesCount = new HashMap<>(); + /** + * Flash proxy namespace. + */ public static final DottedChain FLASH_PROXY = new DottedChain(new String[]{"flash", "utils", "flash_proxy"}); + /** + * Built-in namespace. + */ public static final DottedChain BUILTIN = new DottedChain(new String[]{"-"}); + /** + * Constructs AVM2 deobfuscation. + * @param swf SWF + * @param constants AVM2 constant pool + */ public AVM2Deobfuscation(SWF swf, AVM2ConstantPool constants) { this.swf = swf; this.constants = constants; } + /** + * Checks if string is valid namespace part. + * @param s String + * @return True if string is valid namespace part + */ private boolean isValidNSPart(String s) { boolean isValid = true; if (IdentifiersDeobfuscation.isReservedWord2(s)) { @@ -80,6 +114,11 @@ public class AVM2Deobfuscation { return isValid; } + /** + * Gets built-in namespace. + * @param ns Namespace + * @return Built-in namespace + */ public DottedChain builtInNs(String ns) { if (ns == null) { return null; @@ -93,6 +132,16 @@ public class AVM2Deobfuscation { return null; } + /** + * Generates random string. + * @param deobfuscated Deobfuscated names + * @param orig Original name + * @param firstUppercase First uppercase + * @param usageType Usage type + * @param renameType Rename type + * @param autoAdd Auto add + * @return Random string + */ private String fooString(HashMap deobfuscated, String orig, boolean firstUppercase, String usageType, RenameType renameType, boolean autoAdd) { if (usageType == null) { usageType = "name"; @@ -122,6 +171,15 @@ public class AVM2Deobfuscation { return ret; } + /** + * Deobfuscates package name. + * @param stringUsageTypes String usage types + * @param stringUsages String usages + * @param namesMap Names map + * @param strIndex String index + * @param renameType Rename type + * @return Deobfuscated package name + */ public int deobfuscatePackageName(Map stringUsageTypes, Set stringUsages, HashMap namesMap, int strIndex, RenameType renameType) { if (strIndex <= 0) { return strIndex; @@ -160,6 +218,17 @@ public class AVM2Deobfuscation { return strIndex; } + /** + * Deobfuscates name. + * @param stringUsageTypes String usage types + * @param stringUsages String usages + * @param namespaceUsages Namespace usages + * @param namesMap Names map + * @param strIndex String index + * @param firstUppercase First uppercase + * @param renameType Rename type + * @return Deobfuscated name string index + */ public int deobfuscateName(Map stringUsageTypes, Set stringUsages, Set namespaceUsages, HashMap namesMap, int strIndex, boolean firstUppercase, RenameType renameType) { if (strIndex <= 0) { return strIndex; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java index 416f03f63..8247c1866 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2FinalProcessLocalData.java @@ -18,27 +18,42 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.graph.Loop; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; /** - * + * AVM2 final process local data. * @author JPEXS */ public class AVM2FinalProcessLocalData extends FinalProcessLocalData { + /** + * Local register names - register number to name mapping. + */ public HashMap localRegNames; + + /** + * Set local position to get local position mapping. + */ public Map> setLocalPosToGetLocalPos = new HashMap<>(); + /** + * Constructs AVM2 final process local data. + * @param loops List of loops + * @param localRegNames Local register names - register number to name mapping + * @param setLocalPosToGetLocalPos Set local position to get local position mapping + */ public AVM2FinalProcessLocalData(List loops, HashMap localRegNames, Map> setLocalPosToGetLocalPos) { super(loops); this.localRegNames = localRegNames; this.setLocalPosToGetLocalPos = setLocalPosToGetLocalPos; } + /** + * Gets getlocal positions for setlocal position. + * @param setLocalPos Setlocal position + * @return Set of getlocal positions + */ public Set getSetLocalUsages(int setLocalPos) { if (setLocalPosToGetLocalPos == null) { return new HashSet<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Runtime.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Runtime.java index 2f9be652b..fc177ca7e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Runtime.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Runtime.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Type of AVM2 runtime enum. * @author JPEXS */ public enum AVM2Runtime { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2RuntimeInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2RuntimeInfo.java index 77f3a50eb..e9c05e6cc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2RuntimeInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2RuntimeInfo.java @@ -17,17 +17,32 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Info of AVM2 runtime. * @author JPEXS */ public class AVM2RuntimeInfo { + /** + * AVM2 runtime. + */ public AVM2Runtime runtime; + /** + * AVM2 version. + */ public int version; + /** + * Debug flag. + */ public boolean debug; + /** + * Constructs AVM2 runtime info. + * @param runtime AVM2 runtime + * @param version AVM2 version + * @param debug Debug flag + */ public AVM2RuntimeInfo(AVM2Runtime runtime, int version, boolean debug) { this.runtime = runtime; this.version = version; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java index a7481895d..38b57e2c6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/CodeStats.java @@ -20,30 +20,59 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.model.LocalData; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; /** - * + * Code statistics. * @author JPEXS */ public class CodeStats { + /** + * Maximum stack size + */ public int maxstack = 0; + /** + * Maximum scope size + */ public int maxscope = 0; + /** + * Number of local registers + */ public int maxlocal = 1; + /** + * Initial scope size + */ public int initscope = 0; + /** + * Has set_dxns instruction + */ public boolean has_set_dxns = false; + /** + * Has activation instruction + */ public boolean has_activation = false; + /** + * Instruction statistics + */ public InstructionStats[] instructionStats; + /** + * Converts statistics to string. + * @param writer Writer + * @param abc ABC + * @param fullyQualifiedNames Fully qualified names + * @return Writer + */ public GraphTextWriter toString(GraphTextWriter writer, ABC abc, List fullyQualifiedNames) { writer.appendNoHilight("Stats: maxstack=" + maxstack + ", maxscope=" + maxscope + ", maxlocal=" + maxlocal).newLine(); int i = 0; @@ -59,9 +88,16 @@ public class CodeStats { return writer; } + /** + * Constructs code statistics. + */ public CodeStats() { } + /** + * Constructs code statistics. + * @param code AVM2 code + */ public CodeStats(AVM2Code code) { instructionStats = new InstructionStats[code.code.size()]; for (int i = 0; i < code.code.size(); i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertException.java index 769a9e42b..a04a15976 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertException.java @@ -17,13 +17,22 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Convert exception. * @author JPEXS */ public class ConvertException extends RuntimeException { + /** + * Line number + */ public int line; + + /** + * Constructs convert exception. + * @param s Message + * @param line Line number + */ public ConvertException(String s, int line) { super(s + " on line " + line); this.line = line; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertOutput.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertOutput.java index 4e8331a68..03e13b2db 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertOutput.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/ConvertOutput.java @@ -18,18 +18,30 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; + import java.util.List; /** - * + * Conversion output. * @author JPEXS */ public class ConvertOutput { + /** + * Translate stack + */ public TranslateStack stack; + /** + * Output + */ public List output; + /** + * Constructs conversion output. + * @param stack Translate stack + * @param output Output + */ public ConvertOutput(TranslateStack stack, List output) { this.stack = stack; this.output = output; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java index d7c599ce5..7744c7d25 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/FixItemCounterTranslateStack.java @@ -20,17 +20,28 @@ import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; /** - * + * Translate stack that counts the number of items pushed and not popped. * @author JPEXS */ public class FixItemCounterTranslateStack extends TranslateStack { + /** + * + */ private int fixItemCount = Integer.MAX_VALUE; + /** + * Constructs a new FixItemCounterTranslateStack + * @param path Path + */ public FixItemCounterTranslateStack(String path) { super(null); //null path => do not add PushItems } + /** + * Pops an item from the stack + * @return The popped item + */ @Override public GraphTargetItem pop() { GraphTargetItem result = super.pop(); @@ -41,6 +52,11 @@ public class FixItemCounterTranslateStack extends TranslateStack { return result; } + /** + * Removes the element at the specified index + * @param index the index of the element to be removed + * @return The removed element + */ @Override public synchronized GraphTargetItem remove(int index) { if (index < fixItemCount) { @@ -49,10 +65,18 @@ public class FixItemCounterTranslateStack extends TranslateStack { return super.remove(index); } + /** + * All items were never popped. + * @return True if all items were never popped + */ public boolean allItemsFixed() { return size() <= fixItemCount; } + /** + * Gets the number of items that were never popped + * @return The number of items that were never popped + */ public int getFixItemCount() { return fixItemCount; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InstructionStats.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InstructionStats.java index 7d4f61970..af2a298cc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InstructionStats.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InstructionStats.java @@ -19,23 +19,45 @@ package com.jpexs.decompiler.flash.abc.avm2; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; /** - * + * Instruction statistics. * @author JPEXS */ public class InstructionStats { + /** + * Whether the instruction has been seen while walking the instruction list + */ public boolean seen = false; + /** + * Stack position before the instruction + */ public int stackpos = 0; + /** + * Scope position before the instruction + */ public int scopepos = 0; + /** + * Stack position after the instruction + */ public int stackpos_after = 0; + /** + * Scope position after the instruction + */ public int scopepos_after = 0; + /** + * Instruction + */ public AVM2Instruction ins; + /** + * Constructs a new InstructionStats object + * @param ins Instruction + */ public InstructionStats(AVM2Instruction ins) { this.ins = ins; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArguments.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArgumentsException.java similarity index 76% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArguments.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArgumentsException.java index fc34c1067..458f01cbc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArguments.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/InvalidInstructionArgumentsException.java @@ -17,12 +17,15 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Invalid instruction arguments exception. * @author JPEXS */ -public class InvalidInstructionArguments extends RuntimeException { +public class InvalidInstructionArgumentsException extends RuntimeException { - public InvalidInstructionArguments() { + /** + * Constructs new InvalidInstructionArgumentsException + */ + public InvalidInstructionArgumentsException() { super("Invalid method arguments"); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/LocalDataArea.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/LocalDataArea.java index b1145417e..a5c7ac2fe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/LocalDataArea.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/LocalDataArea.java @@ -20,30 +20,61 @@ import java.util.HashMap; import java.util.Stack; /** - * + * Local data area for AVM2 method execution. * @author JPEXS */ public class LocalDataArea { + /** + * Name of the method that is currently being executed. + */ public String methodName; + /** + * Operand stack. + */ public Stack operandStack = new Stack<>(); + /** + * Scope stack. + */ public Stack scopeStack = new Stack<>(); + /** + * Local registers values - maps register index to value. + */ public HashMap localRegisters = new HashMap<>(); + /** + * Offset of jump + */ public Long jump; + /** + * Return value of the method. + */ public Object returnValue; + /** + * Runtime info. + */ public AVM2RuntimeInfo runtimeInfo; + /** + * Domain memory. + */ private byte[] domainMemory; + /** + * Constructs a new LocalDataArea. + */ public LocalDataArea() { } + /** + * Gets domain memory. + * @return Domain memory bytes. + */ public byte[] getDomainMemory() { if (domainMemory == null) { domainMemory = new byte[1024]; // in flash player this is the default size @@ -52,14 +83,25 @@ public class LocalDataArea { return domainMemory; } + /** + * Gets runtime. + * @return Runtime. + */ public AVM2Runtime getRuntime() { return runtimeInfo == null ? AVM2Runtime.UNKNOWN : runtimeInfo.runtime; } + /** + * Gets debug flag. + * @return True if debug flag is set. + */ public boolean isDebug() { return runtimeInfo != null && runtimeInfo.debug; } + /** + * Clears the local data area. + */ public void clear() { operandStack.clear(); scopeStack.clear(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/NumberContext.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/NumberContext.java index da31810dd..78e633792 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/NumberContext.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/NumberContext.java @@ -16,8 +16,12 @@ */ package com.jpexs.decompiler.flash.abc.avm2; +/** + * Number context. + */ public class NumberContext { + //Rounding modes public static final int ROUND_CEILING = 0; public static final int ROUND_UP = 1; public static final int ROUND_HALF_UP = 2; @@ -26,28 +30,54 @@ public class NumberContext { public static final int ROUND_DOWN = 5; public static final int ROUND_FLOOR = 6; + //Usage modes public static final int USE_NUMBER = 0; public static final int USE_DECIMAL = 1; public static final int USE_DOUBLE = 2; public static final int USE_INT = 3; public static final int USE_UINT = 4; + /** + * Usage of the number. + */ private int usage = USE_NUMBER; + /** + * Precision of the number. + */ private int precision = 34; + /** + * Rounding of the number. + */ private int rounding = ROUND_HALF_EVEN; + /** + * Creates a new number context. + * + * @param usage Usage of the number. + * @param precision Precision of the number. + * @param rounding Rounding of the number. + */ public NumberContext(int usage, int precision, int rounding) { this.usage = usage; this.precision = precision; this.rounding = rounding; } + /** + * Creates a new number context. + * + * @param param Parameter. + */ public NumberContext(int param) { this.usage = param & 7; this.rounding = (param >> 3) & 7; this.precision = param >> 6; } + /** + * Sets the usage of the number. + * @param usage + */ public void setUsage(int usage) { if (usage > 6 || usage < 0) { throw new IllegalArgumentException("Invalid usage value :" + usage); @@ -55,14 +85,26 @@ public class NumberContext { this.usage = usage; } + /** + * Gets the usage of the number. + * @return Usage of the number. + */ public int getUsage() { return usage; } + /** + * Gets the precision of the number. + * @return Precision of the number. + */ public int getPrecision() { return precision; } + /** + * Sets the precision of the number. + * @param precision Precision of the number. + */ public void setPrecision(int precision) { if (precision > 34) { throw new IllegalArgumentException("Maximum value of precision is 34"); @@ -70,6 +112,10 @@ public class NumberContext { this.precision = precision; } + /** + * Converts the number context to a parameter. + * @return Parameter. + */ public int toParam() { int ret = usage; if (usage == USE_NUMBER || usage == USE_DECIMAL) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java index 5d373b506..17493315e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/OffsetUpdater.java @@ -17,12 +17,25 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Offset updater interface. + * Used to update offsets in instructions and operands. * @author JPEXS */ public interface OffsetUpdater { + /** + * Updates instruction offset. + * @param addr Address of the instruction + * @return New address of the instruction + */ public long updateInstructionOffset(long addr); + /** + * Updates operand offset. + * @param jumpAddr Address of the jump instruction + * @param targetAddress Address of the target instruction + * @param offset Operand (offset) of the jump instruction + * @return New operand offset + */ public int updateOperandOffset(long jumpAddr, long targetAddress, int offset); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCode.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCodeException.java similarity index 72% rename from libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCode.java rename to libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCodeException.java index 3608b055c..c61a78798 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCode.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/UnknownInstructionCodeException.java @@ -17,14 +17,21 @@ package com.jpexs.decompiler.flash.abc.avm2; /** - * + * Exception thrown when unknown instruction code is found. * @author JPEXS */ -public class UnknownInstructionCode extends RuntimeException { +public class UnknownInstructionCodeException extends RuntimeException { + /** + * Instruction code + */ public int code; - public UnknownInstructionCode(int code) { + /** + * Constructs a new UnknownInstructionCodeException. + * @param code Instruction code + */ + public UnknownInstructionCodeException(int code) { super("Unknown instruction code: 0x" + Integer.toHexString(code)); this.code = code; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java index abbacbce3..b6e4a96af 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGetSet.java @@ -36,11 +36,8 @@ import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.NotCompileTimeItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateException; +import com.jpexs.decompiler.graph.*; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -48,7 +45,7 @@ import java.util.Map; /** * - * AVM2 Deobfuscator removing single get / set registers + * AVM2 Deobfuscator removing single get / set registers. * * Example: getlocal_1, getlocal_2, (kill 1), (kill 2), setlocal_2, setlocal_1 * @@ -56,12 +53,32 @@ import java.util.Map; */ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { + /** + * Undefined item + */ private static final UndefinedAVM2Item UNDEFINED_ITEM = new UndefinedAVM2Item(null, null); + /** + * Not compile time undefined item + */ private static final NotCompileTimeItem NOT_COMPILE_TIME_UNDEFINED_ITEM = new NotCompileTimeItem(null, null, UNDEFINED_ITEM); + /** + * Execution limit + */ private final int executionLimit = 30000; + /** + * Remove obfuscation get sets + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param body Method body + * @param inlineIns Inline instructions + * @return True if removed + * @throws InterruptedException + */ protected boolean removeObfuscationGetSets(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, List inlineIns) throws InterruptedException { AVM2Code code = body.getCode(); if (code.code.isEmpty()) { @@ -99,10 +116,26 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { return false; } + /** + * Remove unreachable instructions. + * @param code AVM2 code + * @param body Method body + * @throws InterruptedException + */ protected void removeUnreachableInstructions(AVM2Code code, MethodBody body) throws InterruptedException { code.removeDeadCode(body); } + /** + * Create new local data. + * @param scriptIndex Script index + * @param abc ABC + * @param cpool Constant pool + * @param body Method body + * @param isStatic Is static + * @param classIndex Class index + * @return AVM2 local data + */ protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { AVM2LocalData localData = new AVM2LocalData(); localData.isStatic = isStatic; @@ -124,6 +157,12 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { return localData; } + /** + * Initialize local registers. + * @param localData AVM2 local data + * @param localReservedCount Local reserved count + * @param maxRegs Maximum registers + */ protected void initLocalRegs(AVM2LocalData localData, int localReservedCount, int maxRegs) { for (int i = 0; i < localReservedCount; i++) { localData.localRegs.put(i, NOT_COMPILE_TIME_UNDEFINED_ITEM); @@ -133,6 +172,15 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { } } + /** + * Execute instructions. + * @param body Method body + * @param code AVM2 code + * @param localData AVM2 local data + * @param idx Index + * @param endIdx End index + * @throws InterruptedException + */ private void executeInstructions(MethodBody body, AVM2Code code, AVM2LocalData localData, int idx, int endIdx) throws InterruptedException { List output = new ArrayList<>(); @@ -217,6 +265,18 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter { } } + /** + * AVM2 code remove traps. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGroupParts.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGroupParts.java index 83fe2115a..3a6d272ee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGroupParts.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorGroupParts.java @@ -25,12 +25,13 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter; + import java.util.ArrayList; import java.util.List; import java.util.Map; /** - * Stub for deobfuscator merging jump parts + * Stub for deobfuscator merging jump parts. * * @author JPEXS */ @@ -101,6 +102,19 @@ A: jump B C: blk_4 */ + + /** + * Removes dead code and merges jump parts. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); @@ -165,6 +179,12 @@ C: blk_4 new AVM2DeobfuscatorJumps().avm2CodeRemoveTraps(path, classIndex, isStatic, scriptIndex, abc, trait, methodInfo, body); } + /** + * Gets real refs. + * @param refs Refs + * @param ip IP + * @return Real refs + */ private int realRefs(Map> refs, int ip) { int refCount = 0; for (int r : refs.get(ip)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java index a326c0a83..0240b6087 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorJumps.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -38,6 +39,18 @@ import java.util.Map; */ public class AVM2DeobfuscatorJumps extends SWFDecompilerAdapter { + /** + * Removes jumps/ifs targeting other jumps. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index 44ebd0230..6455ced7b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -37,20 +37,10 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.helpers.Reference; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; + +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -64,6 +54,11 @@ import java.util.logging.Logger; */ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { + /** + * Gets registers used in the code. + * @param code AVM2 code + * @return Set of registers + */ private Set getRegisters(AVM2Code code) { Set regs = new HashSet<>(); for (AVM2Instruction ins : code.code) { @@ -88,6 +83,18 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { return regs; } + /** + * Removes single assigned local registers. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { //System.err.println("regdeo:" + path); @@ -155,6 +162,20 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { //System.err.println("/deo"); } + /** + * Replaces single use registers. + * @param singleRegisters Single registers + * @param setInss Set instructions + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param cpool Constant pool + * @param trait Trait + * @param minfo Method info + * @param body Method body + * @throws InterruptedException + */ private void replaceSingleUseRegisters(Map singleRegisters, List setInss, int classIndex, boolean isStatic, int scriptIndex, ABC abc, AVM2ConstantPool cpool, Trait trait, MethodInfo minfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); @@ -182,6 +203,16 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { } } + /** + * Gets first register id which has setter. + * @param assignment Assignment + * @param body Method body + * @param abc ABC + * @param ignoredRegisters Ignored registers + * @param ignoredGets Ignored gets + * @return first register id + * @throws InterruptedException + */ private int getFirstRegisterSetter(Reference assignment, MethodBody body, ABC abc, Set ignoredRegisters, Set ignoredGets) throws InterruptedException { AVM2Code code = body.getCode(); @@ -192,6 +223,21 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { return visitCode(assignment, new HashSet<>(), new Stack<>(), body, abc, code, 0, code.code.size() - 1, ignoredRegisters, ignoredGets); } + /** + * Visits code. + * @param assignment Assignment + * @param visited Visited + * @param stack Stack + * @param body Method body + * @param abc ABC + * @param code AVM2 code + * @param idx Index + * @param endIdx End index + * @param ignored Ignored + * @param ignoredGets Ignored gets + * @return Register id + * @throws InterruptedException + */ private int visitCode(Reference assignment, Set visited, Stack stack, MethodBody body, ABC abc, AVM2Code code, int idx, int endIdx, Set ignored, Set ignoredGets) throws InterruptedException { LocalDataArea localData = new LocalDataArea(); initLocalRegs(localData, body.getLocalReservedCount(), body.max_regs, false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java index 061d2d9c9..6fa71c7a1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java @@ -35,21 +35,10 @@ import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.helpers.Reference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; /** * @@ -61,6 +50,11 @@ import java.util.Set; */ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld { + /** + * Gets all register ids. + * @param code AVM2 code + * @return Set of register ids + */ private Set getRegisters(AVM2Code code) { Set regs = new HashSet<>(); for (AVM2Instruction ins : code.code) { @@ -85,6 +79,18 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld { return regs; } + /** + * Removes single assigned local registers. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { //System.err.println("regdeo:" + path); @@ -152,6 +158,19 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld { originalBody.setCode(body.getCode()); } + /** + * Gets first register with setter. + * @param assignment Assignment + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param body Method body + * @param ignoredRegisters Ignored registers + * @param ignoredGets Ignored gets + * @return Register id + * @throws InterruptedException + */ private int getFirstRegisterSetter(Reference assignment, int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, Set ignoredRegisters, Set ignoredGets) throws InterruptedException { AVM2Code code = body.getCode(); @@ -163,26 +182,66 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld { return visitCode(assignment, visited, new TranslateStack("deo"), classIndex, isStatic, body, scriptIndex, abc, code, 0, code.code.size() - 1, ignoredRegisters, ignoredGets); } + /** + * Exception target ip pair. + */ private class ExceptionTargetIpPair { + /** + * Exception. + */ private final ABCException exception; + /** + * Target ip. + */ private final int targetIp; + /** + * Constructs a new instance of ExceptionTargetIpPair. + * @param exception Exception + * @param targetIp Target ip + */ public ExceptionTargetIpPair(ABCException exception, int targetIp) { this.exception = exception; this.targetIp = targetIp; } + /** + * Gets exception. + * @return Exception + */ public ABCException getException() { return exception; } + /** + * Gets target ip. + * @return Target ip + */ public int getTargetIp() { return targetIp; } } + /** + * Visits code. + * @param assignment Assignment + * @param visited Visited + * @param stack Stack + * @param classIndex Class index + * @param isStatic Is static + * @param body Method body + * @param scriptIndex Script index + * @param abc ABC + * @param code AVM2 code + * @param idx Index + * @param endIdx End index + * @param ignored Ignored + * @param ignoredGets Ignored gets + * @return Register id + * @throws InterruptedException + */ private int visitCode(Reference assignment, Set visited, TranslateStack stack, int classIndex, boolean isStatic, MethodBody body, int scriptIndex, ABC abc, AVM2Code code, int idx, int endIdx, Set ignored, Set ignoredGets) throws InterruptedException { Map> exceptionStartToTargets = new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java index bdc815291..efb364dbe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimple.java @@ -20,38 +20,10 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewArrayIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewObjectIns; @@ -59,18 +31,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; @@ -78,19 +39,34 @@ import com.jpexs.decompiler.flash.ecma.NotCompileTime; import com.jpexs.decompiler.flash.ecma.Undefined; import com.jpexs.decompiler.flash.helpers.collections.FixItemCounterStack; import com.jpexs.decompiler.graph.TranslateException; + import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.Stack; /** - * + * Simple AVM2 deobfuscator. * @author JPEXS */ public class AVM2DeobfuscatorSimple extends AVM2DeobfuscatorZeroJumpsNullPushes { + /** + * Maximum number of instructions to execute in one pass + */ private final int executionLimit = 30000; + /** + * Removes obfuscation ifs. + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param body Method body + * @param inlineIns Inline instruction + * @return True if code was modified + * @throws InterruptedException + */ protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, AVM2Instruction inlineIns) throws InterruptedException { AVM2Code code = body.getCode(); if (code.code.isEmpty()) { @@ -128,6 +104,13 @@ public class AVM2DeobfuscatorSimple extends AVM2DeobfuscatorZeroJumpsNullPushes return false; } + /** + * Initializes local registers. + * @param localData Local data + * @param localReservedCount Count of reserved local registers + * @param maxRegs Maximum registers + * @param executeFromFirst Execute from first + */ protected void initLocalRegs(LocalDataArea localData, int localReservedCount, int maxRegs, boolean executeFromFirst) { for (int i = 0; i < localReservedCount; i++) { localData.localRegisters.put(i, NotCompileTime.INSTANCE); @@ -137,6 +120,20 @@ public class AVM2DeobfuscatorSimple extends AVM2DeobfuscatorZeroJumpsNullPushes } } + /** + * Executes instructions. + * @param staticRegs Static registers + * @param body Method body + * @param abc ABC + * @param code AVM2 code + * @param localData Local data + * @param idx Start index + * @param endIdx End index + * @param result Execution result + * @param inlineIns Inline instruction + * @return True if code was modified + * @throws InterruptedException + */ private boolean executeInstructions(Map staticRegs, MethodBody body, ABC abc, AVM2Code code, LocalDataArea localData, int idx, int endIdx, ExecutionResult result, AVM2Instruction inlineIns) throws InterruptedException { int instructionsProcessed = 0; @@ -348,6 +345,18 @@ public class AVM2DeobfuscatorSimple extends AVM2DeobfuscatorZeroJumpsNullPushes return modified; } + /** + * Simple deobfuscation. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); @@ -357,12 +366,24 @@ public class AVM2DeobfuscatorSimple extends AVM2DeobfuscatorZeroJumpsNullPushes removeNullPushes(code, body); } + /** + * Execution result. + */ class ExecutionResult { + /** + * Ip + */ public int idx = -1; + /** + * Number of instructions processed + */ public int instructionsProcessed = -1; + /** + * Stack + */ public Stack stack = new Stack<>(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java index 877ad4798..9ec174b7f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorSimpleOld.java @@ -21,39 +21,10 @@ import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.FixItemCounterTranslateStack; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; -import com.jpexs.decompiler.flash.abc.avm2.instructions.DeobfuscatePopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.IfTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.AddIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DecrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.DivideIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.IncrementIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.ModuloIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.MultiplyIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NegateIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.SubtractIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitAndIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitNotIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitOrIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.BitXorIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.LShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.RShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.URShiftIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.EqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.GreaterThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessEqualsIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.LessThanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.StrictEqualsIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise.*; +import com.jpexs.decompiler.flash.abc.avm2.instructions.comparison.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewArrayIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; @@ -67,59 +38,48 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIn import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.DupIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.SwapIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceOrConvertTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.TypeOfIns; -import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.ecma.Null; import com.jpexs.decompiler.flash.ecma.Undefined; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.NotCompileTimeItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateException; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.decompiler.graph.model.FalseItem; import com.jpexs.decompiler.graph.model.TrueItem; import com.jpexs.helpers.Reference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; /** - * + * Simple deobfuscator for AVM2 code. (Old version) * @author JPEXS */ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPushes { + /** + * Undefined item + */ private static final UndefinedAVM2Item UNDEFINED_ITEM = new UndefinedAVM2Item(null, null); + /** + * Not compile time undefined item + */ private static final NotCompileTimeItem NOT_COMPILE_TIME_UNDEFINED_ITEM = new NotCompileTimeItem(null, null, UNDEFINED_ITEM); + /** + * Execution limit + */ private final int executionLimit = 30000; + /** + * Creates a push instruction from a graph target item. + * @param cpool Constant pool + * @param graphTargetItem Graph target item + * @return Push instruction + */ protected AVM2Instruction makePush(AVM2ConstantPool cpool, GraphTargetItem graphTargetItem) { if (graphTargetItem instanceof IntegerValueAVM2Item) { IntegerValueAVM2Item iv = (IntegerValueAVM2Item) graphTargetItem; @@ -143,6 +103,17 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush return null; } + /** + * Removes obfuscation ifs. + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param body Method body + * @param inlineIns Inline instructions + * @return True if removed, false otherwise + * @throws InterruptedException + */ protected boolean removeObfuscationIfs(int classIndex, boolean isStatic, int scriptIndex, ABC abc, MethodBody body, List inlineIns) throws InterruptedException { AVM2Code code = body.getCode(); if (code.code.isEmpty()) { @@ -196,6 +167,16 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush return false; } + /** + * Creates a new local data. + * @param scriptIndex Script index + * @param abc ABC + * @param cpool Constant pool + * @param body Method body + * @param isStatic Is static + * @param classIndex Class index + * @return New local data + */ protected AVM2LocalData newLocalData(int scriptIndex, ABC abc, AVM2ConstantPool cpool, MethodBody body, boolean isStatic, int classIndex) { AVM2LocalData localData = new AVM2LocalData(); localData.isStatic = isStatic; @@ -217,6 +198,12 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush return localData; } + /** + * Initializes local registers. + * @param localData Local data + * @param localReservedCount Count of reserved local registers + * @param maxRegs Maximal register id + */ protected void initLocalRegs(AVM2LocalData localData, int localReservedCount, int maxRegs) { for (int i = 0; i < localReservedCount; i++) { localData.localRegs.put(i, NOT_COMPILE_TIME_UNDEFINED_ITEM); @@ -226,6 +213,23 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush } } + /** + * Executes instructions. + * @param importantOffsets Important offsets + * @param staticRegs Static registers + * @param body Method body + * @param abc ABC + * @param code AVM2 code + * @param localData Local data + * @param idx Index + * @param endIdx End index + * @param result Execution result + * @param inlineIns Inline instructions + * @param jumpTargets Jump targets + * @param minChangedIpRef Minimal changed IP reference + * @return True if executed, false otherwise + * @throws InterruptedException + */ private boolean executeInstructions(Set importantOffsets, Map staticRegs, MethodBody body, ABC abc, AVM2Code code, AVM2LocalData localData, int idx, int endIdx, ExecutionResult result, List inlineIns, List jumpTargets, Reference minChangedIpRef) throws InterruptedException { List output = new ArrayList<>(); @@ -535,6 +539,18 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush return false; } + /** + * Simple deobfuscates AVM2 code. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); @@ -544,12 +560,24 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush removeNullPushes(code, body); } + /** + * Execution result. + */ class ExecutionResult { + /** + * Ip + */ public int idx = -1; + /** + * Number of instructions processed + */ public int instructionsProcessed = -1; - public TranslateStack stack = new TranslateStack("?"); + /** + * Stack + */ + public Stack stack = new Stack<>(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorZeroJumpsNullPushes.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorZeroJumpsNullPushes.java index 92482c112..7d34ddbad 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorZeroJumpsNullPushes.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorZeroJumpsNullPushes.java @@ -22,34 +22,39 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic.NotIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushDoubleIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushFalseIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNanIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushNullIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushShortIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushTrueIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUIntIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushUndefinedIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.*; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.helpers.SWFDecompilerAdapter; import com.jpexs.helpers.Reference; + import java.util.Set; /** - * + * Deobfuscator for removing zero jumps and null pushes. * @author JPEXS */ public class AVM2DeobfuscatorZeroJumpsNullPushes extends SWFDecompilerAdapter { + /** + * Removes zero jumps from the code. + * @param code AVM2 code + * @param body Method body + * @return True if any zero jumps were removed + * @throws InterruptedException + */ protected boolean removeZeroJumps(AVM2Code code, MethodBody body) throws InterruptedException { return removeZeroJumps(code, body, new Reference<>(-1)); } + /** + * Removes zero jumps from the code. + * @param code AVM2 code + * @param body Method body + * @param minChangedIpRef Reference to the minimum changed instruction pointer + * @return True if any zero jumps were removed + * @throws InterruptedException + */ protected boolean removeZeroJumps(AVM2Code code, MethodBody body, Reference minChangedIpRef) throws InterruptedException { boolean result = false; int minChangedIp = -1; @@ -74,6 +79,11 @@ public class AVM2DeobfuscatorZeroJumpsNullPushes extends SWFDecompilerAdapter { return result; } + /** + * Checks if the instruction is a simple push. + * @param def Instruction definition + * @return True if the instruction is a simple push + */ private boolean isSimplePush(InstructionDefinition def) { return (def instanceof PushByteIns || def instanceof PushDoubleIns @@ -88,6 +98,13 @@ public class AVM2DeobfuscatorZeroJumpsNullPushes extends SWFDecompilerAdapter { || def instanceof PushUndefinedIns); } + /** + * Removes null pushes from the code. + * @param code AVM2 code + * @param body Method body + * @return True if any null pushes were removed + * @throws InterruptedException + */ protected boolean removeNullPushes(AVM2Code code, MethodBody body) throws InterruptedException { boolean result = false; Set offsets = code.getImportantOffsets(body, true); @@ -136,6 +153,18 @@ public class AVM2DeobfuscatorZeroJumpsNullPushes extends SWFDecompilerAdapter { return result; } + /** + * Removes zero jumps and null pushes from the code. + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC + * @param trait Trait + * @param methodInfo Method info + * @param body Method body + * @throws InterruptedException + */ @Override public void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException { AVM2Code code = body.getCode(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AbcMultiNameCollisionFixer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AbcMultiNameCollisionFixer.java index a6e113bda..0f14f8785 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AbcMultiNameCollisionFixer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AbcMultiNameCollisionFixer.java @@ -23,12 +23,22 @@ import com.jpexs.decompiler.flash.abc.types.NamespaceSet; import com.jpexs.decompiler.flash.abc.usages.multinames.MultinameUsage; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; + import java.util.HashSet; import java.util.Objects; import java.util.Set; +/** + * Fixes collisions of multinames in ABC files. + */ public class AbcMultiNameCollisionFixer { + /** + * Fixes collisions of multinames in SWF file. + * + * @param swf SWF file + * @return Number of fixed collisions + */ public int fixCollisions(SWF swf) { int ret = 0; for (ABCContainerTag tag : swf.getAbcList()) { @@ -37,6 +47,12 @@ public class AbcMultiNameCollisionFixer { return ret; } + /** + * Fixes collisions of multinames in ABC file. + * + * @param abc ABC file + * @return Number of fixed collisions + */ public int fixCollisions(ABC abc) { Set collidingUsages = abc.getCollidingMultinameUsages(); Set collidingMultinameIndices = new HashSet<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationLevel.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationLevel.java index 1d99a42c9..75e8cd041 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationLevel.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationLevel.java @@ -17,19 +17,32 @@ package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; /** - * + * Level of deobfuscation enum. * @author JPEXS */ public enum DeobfuscationLevel { LEVEL_REMOVE_DEAD_CODE(1), LEVEL_REMOVE_TRAPS(2); + + /** + * Level of deobfuscation as number + */ private final int level; + /** + * Get level of deobfuscation as number + * @return + */ public int getLevel() { return level; } + /** + * Get deobfuscation level by level number. + * @param level Level number + * @return Deobfuscation level or null if not found + */ public static DeobfuscationLevel getByLevel(int level) { switch (level) { case 1: diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationScope.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationScope.java index 3652add42..4f48861ca 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationScope.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/DeobfuscationScope.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; /** - * + * Deobfuscation scope enum. * @author JPEXS */ public enum DeobfuscationScope { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/package-info.java new file mode 100644 index 000000000..4647a3dbb --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/package-info.java @@ -0,0 +1,4 @@ +/** + * Deobfuscating AVM2 bytecode. + */ +package com.jpexs.decompiler.flash.abc.avm2.deobfuscation; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2ExecutionException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2ExecutionException.java index 63cd86281..767cbcef0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2ExecutionException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2ExecutionException.java @@ -17,11 +17,15 @@ package com.jpexs.decompiler.flash.abc.avm2.exceptions; /** - * + * Exception thrown when an error occurs during AVM2 execution. * @author JPEXS */ public class AVM2ExecutionException extends Exception { + /** + * Constructs new AVM2ExecutionException with the specified detail message. + * @param message + */ public AVM2ExecutionException(String message) { super(message); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2RangeErrorException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2RangeErrorException.java index 01dc7293b..6fee2bf4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2RangeErrorException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2RangeErrorException.java @@ -17,19 +17,37 @@ package com.jpexs.decompiler.flash.abc.avm2.exceptions; /** - * + * Range error exception. * @author JPEXS */ public class AVM2RangeErrorException extends AVM2ExecutionException { + /** + * Constructs new AVM2RangeErrorException with the specified error code. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + */ public AVM2RangeErrorException(int code, boolean debug) { super(codeToMessage(code, debug, null)); } + /** + * Constructs new AVM2RangeErrorException with the specified error code and parameters. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + */ public AVM2RangeErrorException(int code, boolean debug, Object[] params) { super(codeToMessage(code, debug, params)); } + /** + * Converts error code to error message. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + * @return Error message + */ private static String codeToMessage(int code, boolean debug, Object[] params) { String msg = null; /*switch (code) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2TypeErrorException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2TypeErrorException.java index fd6f5d510..4dda75617 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2TypeErrorException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2TypeErrorException.java @@ -17,19 +17,37 @@ package com.jpexs.decompiler.flash.abc.avm2.exceptions; /** - * + * AVM2 TypeError exception. * @author JPEXS */ public class AVM2TypeErrorException extends AVM2ExecutionException { + /** + * Constructs new AVM2TypeErrorException with the specified error code. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + */ public AVM2TypeErrorException(int code, boolean debug) { super(codeToMessage(code, debug, null)); } + /** + * Constructs new AVM2TypeErrorException with the specified error code and parameters. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + */ public AVM2TypeErrorException(int code, boolean debug, Object[] params) { super(codeToMessage(code, debug, params)); } + /** + * Converts error code to error message. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + * @return Error message + */ private static String codeToMessage(int code, boolean debug, Object[] params) { String msg = null; /*switch (code) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2VerifyErrorException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2VerifyErrorException.java index a4064cb5e..2a303b17c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2VerifyErrorException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/AVM2VerifyErrorException.java @@ -17,25 +17,52 @@ package com.jpexs.decompiler.flash.abc.avm2.exceptions; /** - * + * AVM2 VerifyError exception. * @author JPEXS */ public class AVM2VerifyErrorException extends AVM2ExecutionException { + /** + * Illegal opcode error code. + */ public static final int ILLEGAL_OPCODE = 1011; + /** + * Branch target is not a valid instruction error code. + */ public static final int BRANCH_TARGET_INVALID_INSTRUCTION = 1021; + /** + * Cpool index out of range error code. + */ public static final int CPOOL_INDEX_OUT_OF_RANGE = 1032; + /** + * Constructs new AVM2VerifyErrorException with the specified error code. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + */ public AVM2VerifyErrorException(int code, boolean debug) { super(codeToMessage(code, debug, null)); } + /** + * Constructs new AVM2VerifyErrorException with the specified error code and parameters. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + */ public AVM2VerifyErrorException(int code, boolean debug, Object[] params) { super(codeToMessage(code, debug, params)); } + /** + * Converts error code to error message. + * @param code Error code + * @param debug If true, the error message will contain a description of the error + * @param params Parameters for the error message + * @return Error message + */ private static String codeToMessage(int code, boolean debug, Object[] params) { String msg = null; switch (code) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/package-info.java new file mode 100644 index 000000000..761b375ff --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/exceptions/package-info.java @@ -0,0 +1,4 @@ +/** + * Exceptions for AVM2 execution. + */ +package com.jpexs.decompiler.flash.abc.avm2.exceptions; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/AVM2InstructionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/AVM2InstructionItem.java index 3e0dacc14..1fc54bb56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/AVM2InstructionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/AVM2InstructionItem.java @@ -17,51 +17,99 @@ package com.jpexs.decompiler.flash.abc.avm2.fastavm2; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; + import java.util.HashSet; import java.util.List; import java.util.Set; /** - * + * Instruction item for fast AVM2 list. * @author JPEXS */ public class AVM2InstructionItem { + /** + * Instruction + */ public AVM2Instruction ins; + /** + * Previous instruction + */ public AVM2InstructionItem prev; + /** + * Next instruction + */ public AVM2InstructionItem next; + /** + * Jump target + */ private AVM2InstructionItem jumpTarget; + /** + * Instructions that jump here + */ public Set jumpsHere; + /** + * Instructions that this instruction is the last instruction of + */ public Set lastInsOf; + /** + * Last instruction container + */ private List containerLastInstructions; - // 1 means reachable, 2 means reachable and processed + // + /** + * Whether this instruction is reachable. + * 1 means reachable, 2 means reachable and processed. + */ int reachable; + /** + * Excluded + */ public boolean excluded; + /** + * Constructs a new AVM2InstructionItem + * @param ins Instruction + */ public AVM2InstructionItem(AVM2Instruction ins) { this.ins = ins; } + /** + * Checks whether this instruction is a jump target. + * @return Whether this instruction is a jump target + */ public boolean isJumpTarget() { return jumpsHere != null && !jumpsHere.isEmpty(); } + /** + * Gets the number of jumps to this instruction. + * @return Number of jumps to this instruction + */ public int jumpsHereSize() { return jumpsHere == null ? 0 : jumpsHere.size(); } + /** + * Checks whether this instruction is the last instruction of a container. + * @return Whether this instruction is the last instruction of a container + */ public boolean isContainerLastInstruction() { return lastInsOf != null && !lastInsOf.isEmpty(); } + /** + * Remove jump target. + */ public void removeJumpTarget() { if (jumpTarget == null) { return; @@ -74,14 +122,26 @@ public class AVM2InstructionItem { jumpTarget = null; } + /** + * Get jump target. + * @return Instruction item + */ public AVM2InstructionItem getJumpTarget() { return jumpTarget; } + /** + * Get jump target instruction. + * @return Instruction + */ public AVM2Instruction getJumpTargetInstruction() { return jumpTarget == null ? null : jumpTarget.ins; } + /** + * Set jump target. + * @param item Instruction item + */ public void setJumpTarget(AVM2InstructionItem item) { removeJumpTarget(); @@ -97,10 +157,17 @@ public class AVM2InstructionItem { jumpTarget = item; } + /** + * Get last instructions of container. + * @return List of instruction items + */ public List getContainerLastInstructions() { return containerLastInstructions; } + /** + * Remove last instructions of container. + */ public void removeContainerLastInstructions() { if (containerLastInstructions == null) { return; @@ -115,6 +182,11 @@ public class AVM2InstructionItem { containerLastInstructions = null; } + /** + * Replace container last instruction. + * @param oldItem Old instruction item + * @param newItem New instruction item + */ public void replaceContainerLastInstruction(AVM2InstructionItem oldItem, AVM2InstructionItem newItem) { if (containerLastInstructions == null) { return; @@ -132,6 +204,10 @@ public class AVM2InstructionItem { } } + /** + * Set container last instructions. + * @param lastInstructions + */ public void setContainerLastInstructions(List lastInstructions) { removeContainerLastInstructions(); @@ -142,6 +218,10 @@ public class AVM2InstructionItem { containerLastInstructions = lastInstructions; } + /** + * Ensure last instruction is non-null. + * @return Set of instruction items + */ private Set ensureLastInstructionOf() { if (lastInsOf == null) { lastInsOf = new HashSet<>(); @@ -150,6 +230,10 @@ public class AVM2InstructionItem { return lastInsOf; } + /** + * Checks whether this instruction is excluded. + * @return Whether this instruction is excluded + */ public boolean isExcluded() { return excluded; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2List.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2List.java index 8db51037e..4fe441768 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2List.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2List.java @@ -24,28 +24,39 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.graph.GraphSourceItemContainer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; + +import java.util.*; /** - * + * Fast AVM2 instruction list. * @author JPEXS */ public class FastAVM2List implements Collection { + /** + * Size of the list + */ private int size; + /** + * First item + */ private AVM2InstructionItem firstItem; + /** + * Map of instructions to items + */ private final Map actionItemMap; + /** + * Set of items + */ private final Set actionItemSet; + /** + * Constructs a new FastAVM2List from a method body + * @param body Method body + */ public FastAVM2List(MethodBody body) { // exceptions todo AVM2Code avm2code = body.getCode(); @@ -60,11 +71,23 @@ public class FastAVM2List implements Collection { getJumps(avm2code, actionItemMap); } + /** + * Inserts item before another item + * @param item Item to insert before + * @param action Action to insert + * @return + */ public final AVM2InstructionItem insertItemBefore(AVM2InstructionItem item, AVM2Instruction action) { AVM2InstructionItem newItem = new AVM2InstructionItem(action); return insertItemBefore(item, newItem); } + /** + * Inserts item before another item + * @param item Item to insert before + * @param newItem New item + * @return New item + */ public final AVM2InstructionItem insertItemBefore(AVM2InstructionItem item, AVM2InstructionItem newItem) { insertItemAfter(item.prev, newItem); if (item == firstItem) { @@ -74,11 +97,23 @@ public class FastAVM2List implements Collection { return newItem; } + /** + * Inserts item after another item + * @param item Item to insert after + * @param action Action to insert + * @return + */ public final AVM2InstructionItem insertItemAfter(AVM2InstructionItem item, AVM2Instruction action) { AVM2InstructionItem newItem = new AVM2InstructionItem(action); return insertItemAfter(item, newItem); } + /** + * Inserts item after another item + * @param item Item to insert after + * @param newItem New item + * @return New item + */ public final AVM2InstructionItem insertItemAfter(AVM2InstructionItem item, AVM2InstructionItem newItem) { if (item == null && firstItem == null) { firstItem = newItem; @@ -103,6 +138,11 @@ public class FastAVM2List implements Collection { return newItem; } + /** + * Removes item + * @param item Item to remove + * @return Next item + */ public AVM2InstructionItem removeItem(AVM2InstructionItem item) { AVM2InstructionItem next = null; if (item == firstItem) { @@ -143,6 +183,11 @@ public class FastAVM2List implements Collection { return next; } + /** + * Removes item. + * @param index Index of item to remove + * @param count Number of items to remove + */ public void removeItem(int index, int count) { FastAVM2ListIterator iterator = new FastAVM2ListIterator(this, index); for (int i = 0; i < count; i++) { @@ -151,11 +196,21 @@ public class FastAVM2List implements Collection { } } + /** + * Gets item at index + * @param index Index + * @return Item + */ public AVM2InstructionItem get(int index) { FastAVM2ListIterator iterator = new FastAVM2ListIterator(this, index); return iterator.next(); } + /** + * Replace jump targets. + * @param target Target + * @param newTarget New target + */ public void replaceJumpTargets(AVM2InstructionItem target, AVM2InstructionItem newTarget) { if (target.jumpsHere != null) { for (AVM2InstructionItem item : new ArrayList<>(target.jumpsHere)) { @@ -164,6 +219,13 @@ public class FastAVM2List implements Collection { } } + /** + * Gets nerby address. + * @param instructions Instructions + * @param address Address + * @param next Next + * @return + */ private long getNearAddress(List instructions, long address, boolean next) { int min = 0; int max = instructions.size() - 1; @@ -185,6 +247,11 @@ public class FastAVM2List implements Collection { : (max >= 0 ? instructions.get(max).getAddress() : -1); } + /** + * Gets jumps. + * @param actions Actions + * @param actionItemMap Action item map + */ private void getJumps(AVM2Code actions, Map actionItemMap) { AVM2InstructionItem item = firstItem; if (item == null) { @@ -208,6 +275,9 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Updates action addresses and lengths. + */ private void updateActionAddressesAndLengths() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -223,6 +293,9 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Updates jumps. + */ private void updateJumps() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -249,6 +322,10 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + + /** + * Updates container sizes. + */ private void updateContainerSizes() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -273,6 +350,11 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Gets container. + * @param item Item + * @return Container + */ public AVM2InstructionItem getContainer(AVM2InstructionItem item) { while (!(item.ins instanceof GraphSourceItemContainer) && item != firstItem) { item = item.prev; @@ -285,6 +367,9 @@ public class FastAVM2List implements Collection { return null; } + /** + * Removes zero jumps. + */ public void removeZeroJumps() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -304,6 +389,9 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Removes unreachable actions. + */ public void removeUnreachableActions() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -322,6 +410,9 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Removes included actions. + */ public void removeIncludedActions() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -338,6 +429,12 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Gets unreachable action count. + * @param jump Jump + * @param jumpTarget Jump target + * @return + */ public int getUnreachableActionCount(AVM2InstructionItem jump, AVM2InstructionItem jumpTarget) { AVM2InstructionItem item = firstItem; if (item == null) { @@ -359,6 +456,9 @@ public class FastAVM2List implements Collection { return count; } + /** + * Clears reachable flags. + */ private void clearReachableFlags() { AVM2InstructionItem item = firstItem; if (item == null) { @@ -371,6 +471,10 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Sets excluded flags. + * @param value Value + */ public void setExcludedFlags(boolean value) { AVM2InstructionItem item = firstItem; if (item == null) { @@ -383,6 +487,11 @@ public class FastAVM2List implements Collection { } while (item != firstItem); } + /** + * Updates reachable flags. + * @param jump Jump + * @param jumpTarget Jump target + */ private void updateReachableFlags(AVM2InstructionItem jump, AVM2InstructionItem jumpTarget) { if (firstItem == null) { return; @@ -446,6 +555,10 @@ public class FastAVM2List implements Collection { } } + /** + * Updates actions. + * @param body Method body + */ public void updateActions(MethodBody body) { AVM2Code result = new AVM2Code(size); AVM2InstructionItem item = firstItem; @@ -466,28 +579,53 @@ public class FastAVM2List implements Collection { updateContainerSizes(); } + /** + * Gets first item. + * @return First item + */ public AVM2InstructionItem first() { return firstItem; } + /** + * Gets last item. + * @return Last item + */ public AVM2InstructionItem last() { return firstItem == null ? null : firstItem.prev; } + /** + * Converts to method body. + * @param body Method body + */ public void toMethodBody(MethodBody body) { updateActions(body); } + /** + * Gets size. + * @return Size + */ @Override public int size() { return size; } + /** + * Checks if empty. + * @return Whether empty + */ @Override public boolean isEmpty() { return size == 0; } + /** + * Checks if contains. + * @param o element whose presence in this collection is to be tested + * @return Whether contains + */ @Override public boolean contains(Object o) { if (o instanceof AVM2InstructionItem) { @@ -499,11 +637,19 @@ public class FastAVM2List implements Collection { return false; } + /** + * Gets iterator. + * @return Iterator + */ @Override public FastAVM2ListIterator iterator() { return new FastAVM2ListIterator(this); } + /** + * Converts to array. + * @return Array + */ @Override public Object[] toArray() { Object[] result = new Object[size]; @@ -522,6 +668,14 @@ public class FastAVM2List implements Collection { return null; } + /** + * Converts to array. + * @param a the array into which the elements of this collection are to be + * stored, if it is big enough; otherwise, a new array of the same + * runtime type is allocated for this purpose. + * @return Array + * @param + */ @Override @SuppressWarnings("unchecked") public T[] toArray(T[] a) { @@ -543,12 +697,22 @@ public class FastAVM2List implements Collection { return null; } + /** + * Adds an element to this collection. + * @param e element whose presence in this collection is to be ensured + * @return Whether added + */ @Override public boolean add(AVM2InstructionItem e) { insertItemAfter(null, e); return true; } + /** + * Removes a single instance of the specified element from this collection, + * @param o element to be removed from this collection, if present + * @return Whether removed + */ @Override public boolean remove(Object o) { AVM2InstructionItem item = null; @@ -566,6 +730,11 @@ public class FastAVM2List implements Collection { return true; } + /** + * Checks whether this collection contains all of the elements in the specified collection. + * @param c collection to be checked for containment in this collection + * @return Whether contains all + */ @Override public boolean containsAll(Collection c) { for (Object c1 : c) { @@ -577,6 +746,11 @@ public class FastAVM2List implements Collection { return true; } + /** + * Adds all of the elements in the specified collection to this collection. + * @param c collection containing elements to be added to this collection + * @return Whether added all + */ @Override public boolean addAll(Collection c) { for (AVM2InstructionItem c1 : c) { @@ -586,6 +760,11 @@ public class FastAVM2List implements Collection { return true; } + /** + * Removes all of this collection's elements that are also contained in the specified collection. + * @param c collection containing elements to be removed from this collection + * @return Whether removed all + */ @Override public boolean removeAll(Collection c) { boolean result = false; @@ -596,6 +775,11 @@ public class FastAVM2List implements Collection { return result; } + /** + * Retains only the elements in this collection that are contained in the specified collection. + * @param c collection containing elements to be retained in this collection + * @return Whether retained all + */ @Override public boolean retainAll(Collection c) { AVM2InstructionItem item = firstItem; @@ -616,6 +800,9 @@ public class FastAVM2List implements Collection { return modified; } + /** + * Clears this collection. + */ @Override public void clear() { firstItem = null; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2ListIterator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2ListIterator.java index e398f50de..cf4d3be01 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2ListIterator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/FastAVM2ListIterator.java @@ -17,25 +17,44 @@ package com.jpexs.decompiler.flash.abc.avm2.fastavm2; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; + import java.util.Iterator; /** - * + * Iterator for FastAVM2List * @author JPEXS */ public final class FastAVM2ListIterator implements Iterator { + /** + * Current item + */ private AVM2InstructionItem item; + /** + * List + */ private final FastAVM2List list; + /** + * If the iterator has been started + */ private boolean started = false; + /** + * Constructs a new iterator. + * @param list List + */ FastAVM2ListIterator(FastAVM2List list) { item = list.first(); this.list = list; } + /** + * Constructs a new iterator. + * @param list List + * @param index Index + */ FastAVM2ListIterator(FastAVM2List list, int index) { item = list.first(); this.list = list; @@ -48,11 +67,19 @@ public final class FastAVM2ListIterator implements Iterator } } + /** + * Checks if there is a next item. + * @return True if there is a next item + */ @Override public boolean hasNext() { return item != null && (!started || item != list.first()); } + /** + * Gets the next item. + * @return Next item + */ @Override public AVM2InstructionItem next() { AVM2InstructionItem result = item; @@ -65,6 +92,10 @@ public final class FastAVM2ListIterator implements Iterator return result; } + /** + * Gets the previous item. + * @return Previous item + */ public AVM2InstructionItem prev() { item = item.prev; if (item == list.first()) { @@ -77,6 +108,10 @@ public final class FastAVM2ListIterator implements Iterator return item; } + /** + * Sets the current item. + * @param item Item + */ public void setCurrent(AVM2InstructionItem item) { this.item = item; if (item == list.first()) { @@ -84,23 +119,43 @@ public final class FastAVM2ListIterator implements Iterator } } + /** + * Removes the current item. + */ @Override public void remove() { item = list.removeItem(item.prev); } + /** + * Adds an item. + * @param ins Instruction + */ public void add(AVM2Instruction ins) { item = list.insertItemAfter(item.prev, ins).next; } + /** + * Adds an item. + * @param insItem Instruction item + */ public void add(AVM2InstructionItem insItem) { item = list.insertItemAfter(item.prev, insItem).next; } + /** + * Adds an item before the current item. + * @param insItem Instruction item + */ public void addBefore(AVM2InstructionItem insItem) { list.insertItemBefore(item.prev, insItem); } + /** + * Get the item at the specified index. + * @param index Index + * @return Item + */ public AVM2InstructionItem peek(int index) { AVM2InstructionItem item = this.item; for (int i = 0; i < index; i++) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/package-info.java new file mode 100644 index 000000000..1eb92aa9a --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/fastavm2/package-info.java @@ -0,0 +1,4 @@ +/** + * Fast AVM2 instruction list implementation. + */ +package com.jpexs.decompiler.flash.abc.avm2.fastavm2; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index b4f1b8cea..96c2cb5ab 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -30,13 +30,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.LookupSwitchIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.*; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.NopIns; @@ -47,111 +41,70 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConstructAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FilteredCheckAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NextNameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ThrowAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.WithAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.WithEndAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.WithObjectAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.FilterAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForEachInAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ForInAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.clauses.TryAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.*; import com.jpexs.decompiler.flash.abc.avm2.model.operations.StrictEqAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphException; -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.Loop; -import com.jpexs.decompiler.graph.ScopeStack; -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.TypeItem; -import com.jpexs.decompiler.graph.model.AnyItem; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.ExitItem; -import com.jpexs.decompiler.graph.model.FalseItem; -import com.jpexs.decompiler.graph.model.GotoItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.LoopItem; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.PushItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.decompiler.graph.*; +import com.jpexs.decompiler.graph.model.*; import com.jpexs.helpers.Reference; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; + +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * AVM2 graph. * @author JPEXS */ public class AVM2Graph extends Graph { + /** + * AVM2 code + */ private final AVM2Code avm2code; + /** + * ABC + */ private final ABC abc; + /** + * Method body + */ private final MethodBody body; + /** + * ABC indexing + */ private final AbcIndexing abcIndex; + /** + * Logger + */ private final Logger logger = Logger.getLogger(AVM2Graph.class.getName()); + //Kinds of finally blocks final int FINALLY_KIND_STACK_BASED = 0; final int FINALLY_KIND_REGISTER_BASED = 1; final int FINALLY_KIND_INLINED = 2; final int FINALLY_KIND_UNKNOWN = -1; + /** + * Get AVM2 code + * @return AVM2 code + */ public AVM2Code getCode() { return avm2code; } + /** + * Get exceptions + * @param body Method body + * @return Exceptions + */ private static List getExceptionEntries(MethodBody body) { List ret = new ArrayList<>(); AVM2Code code = body.getCode(); @@ -161,29 +114,39 @@ public class AVM2Graph extends Graph { return ret; } + /** + * Constructs AVM2 graph + * @param abcIndex ABC indexing + * @param code AVM2 code + * @param abc ABC + * @param body Method body + * @param isStatic Is static + * @param scriptIndex Script index + * @param classIndex Class index + * @param localRegs Local registers + * @param scopeStack Scope stack + * @param localScopeStack Local scope stack + * @param localRegNames Local register names + * @param fullyQualifiedNames Fully qualified names + * @param localRegAssigmentIps Local register assignment IPs + */ public AVM2Graph(AbcIndexing abcIndex, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, ScopeStack localScopeStack, HashMap localRegNames, List fullyQualifiedNames, HashMap localRegAssigmentIps) { super(new AVM2GraphSource(code, isStatic, scriptIndex, classIndex, localRegs, abc, body, localRegNames, fullyQualifiedNames, localRegAssigmentIps), getExceptionEntries(body)); this.avm2code = code; this.abc = abc; this.body = body; this.abcIndex = abcIndex; - /*heads = makeGraph(code, new ArrayList(), body); - this.code = code; - this.abc = abc; - this.body = body; - for (GraphPart head : heads) { - fixGraph(head); - makeMulti(head, new ArrayList()); - }*/ - } + /** + * Checks whether part can be break candidate + * @param localData Local data + * @param part Part + * @param throwStates List of throw states + * @return True if part can be break candidate, false otherwise + */ @Override protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List throwStates) { - /*AVM2LocalData aLocalData = (AVM2LocalData) localData; - if (aLocalData.finallyTargetParts.containsValue(part)) { - return false; - }*/ for (ThrowState ts : throwStates) { if (ts.targetPart == part) { return false; @@ -192,6 +155,14 @@ public class AVM2Graph extends Graph { return true; } + /** + * Check before get loops + * @param localData Local data + * @param path Path + * @param allParts All parts + * @param throwStates Throw states + * @throws InterruptedException + */ @Override protected void beforeGetLoops(BaseLocalData localData, String path, Set allParts, List throwStates) throws InterruptedException { AVM2LocalData avm2LocalData = ((AVM2LocalData) localData); @@ -221,11 +192,24 @@ public class AVM2Graph extends Graph { avm2LocalData.inGetLoops = true; } + /** + * Check after get loops + * @param localData Local data + * @param path Path + * @param allParts All parts + * @throws InterruptedException + */ @Override protected void afterGetLoops(BaseLocalData localData, String path, Set allParts) throws InterruptedException { ((AVM2LocalData) localData).inGetLoops = false; } + /** + * Gets ignored switches + * @param localData Local data + * @param allParts All parts + * @throws InterruptedException + */ private void getIgnoredSwitches(AVM2LocalData localData, Set allParts) throws InterruptedException { for (int e = 0; e < body.exceptions.length; e++) { @@ -494,6 +478,17 @@ public class AVM2Graph extends Graph { } } + /** + * Walk local registers usage + * @param throwStates List of throw states + * @param localData Local data + * @param getLocalPos Get local position + * @param startPart Start part + * @param part Part + * @param visited Visited + * @param ip IP + * @param searchRegId Search register ID + */ private void walkLocalRegsUsage(List throwStates, AVM2LocalData localData, Set getLocalPos, GraphPart startPart, GraphPart part, Set visited, int ip, int searchRegId) { if (visited.contains(part) && part != startPart) { return; @@ -584,7 +579,17 @@ public class AVM2Graph extends Graph { } } - //TODO: optimize this to make it faster!!! + /** + * Calculates local registers usage. + * + * TODO: optimize this to make it faster!!! + * @param throwStates List of throw states + * @param localData Local data + * @param ignoredSwitches Ignored switches + * @param path Path + * @param allParts All parts + * @return Map of getLocal to setLocal set + */ public Map> calculateLocalRegsUsage(List throwStates, AVM2LocalData localData, Set ignoredSwitches, String path, Set allParts) { logger.log(Level.FINE, "--- {0} ---", path); Map> setLocalPosToGetLocalPos = new TreeMap<>(); @@ -627,6 +632,29 @@ public class AVM2Graph extends Graph { return setLocalPosToGetLocalPos; } + /** + * Translates via Graph - decompiles. + * @param secondPassData Second pass data + * @param callStack Call stack + * @param abcIndex ABC indexing + * @param path Path + * @param code AVM2 code + * @param abc ABC + * @param body Method body + * @param isStatic Is static + * @param scriptIndex Script index + * @param classIndex Class index + * @param localRegs Local registers + * @param scopeStack Scope stack + * @param localRegNames Local register names + * @param localRegTypes Local register types + * @param fullyQualifiedNames Fully qualified names + * @param staticOperation Unused + * @param localRegAssigmentIps Local register assignment IPs + * @param thisHasDefaultToPrimitive This has default to primitive + * @return List of graph target items + * @throws InterruptedException + */ public static List translateViaGraph(SecondPassData secondPassData, List callStack, AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ScopeStack scopeStack, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, int staticOperation, HashMap localRegAssigmentIps, boolean thisHasDefaultToPrimitive) throws InterruptedException { ScopeStack localScopeStack = new ScopeStack(); AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localScopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps); @@ -657,6 +685,10 @@ public class AVM2Graph extends Graph { return g.translate(localData, staticOperation, path); } + /** + * Check graph. + * @param allBlocks All blocks + */ @Override protected void checkGraph(List allBlocks) { for (ABCException ex : body.exceptions) { @@ -674,41 +706,13 @@ public class AVM2Graph extends Graph { } } - private void findNearestPartOutsideTry(AVM2LocalData localData, GraphPart part, int tryEndIp, Set visited, Set result) { - if (visited.contains(part)) { - return; - } - - if (part.start >= tryEndIp || part.end >= tryEndIp) { - result.add(part); - return; - } - - if (localData.finallyJumps.containsKey(part)) { - GraphPart afterSwitchPart = localData.finallyJumps.get(part); - GraphPart switchPart = null; - for (GraphPart r : afterSwitchPart.refs) { - if (localData.ignoredSwitches.containsValue(r)) { - switchPart = r; - } - } - - if (switchPart != null) { - return; - } - } - - for (GraphPart n : part.nextParts) { - findNearestPartOutsideTry(localData, n, tryEndIp, visited, result); - } - } - - private Set findNearestPartOutsideTry(AVM2LocalData localData, GraphPart start, int tryEndIp) { - Set result = new HashSet<>(); - findNearestPartOutsideTry(localData, start, tryEndIp, new HashSet<>(), result); - return result; - } - + /** + * Finds lookup switch with get local. + * @param registerId Register ID + * @param part Part + * @param visited Visited + * @return Graph part + */ private GraphPart findLookupSwitchWithGetLocal(int registerId, GraphPart part, Set visited) { if (visited.contains(part)) { return null; @@ -735,10 +739,25 @@ public class AVM2Graph extends Graph { return null; } + /** + * Finds lookup switch with get local. + * @param registerId Register ID + * @param part Part + * @return Graph part + */ private GraphPart findLookupSwitchWithGetLocal(int registerId, GraphPart part) { return findLookupSwitchWithGetLocal(registerId, part, new HashSet<>()); } + /** + * Finds all pops. + * @param localData Local data + * @param stackLevel Stack level + * @param part Part + * @param foundIps Found IPs + * @param foundParts Found parts + * @param visited Visited + */ private void findAllPops(AVM2LocalData localData, int stackLevel, GraphPart part, List foundIps, List foundParts, Set visited) { if (visited.contains(part)) { return; @@ -758,6 +777,12 @@ public class AVM2Graph extends Graph { } } + /** + * Gets real references. + * Real = start >= 0 + * @param part + * @return + */ private List getRealRefs(GraphPart part) { List ret = new ArrayList<>(); for (GraphPart r : part.refs) { @@ -768,31 +793,14 @@ public class AVM2Graph extends Graph { return ret; } - private GraphPart firstPartOutsideWalk(GraphPart part, int startIp, int endIp, Set visited) { - if (visited.contains(part)) { - return null; - } - visited.add(part); - if (part.start < startIp || part.start >= endIp) { - return part; - } - for (GraphPart n : part.nextParts) { - GraphPart r = firstPartOutsideWalk(n, startIp, endIp, visited); - if (r != null) { - return r; - } - } - return null; - } - - private GraphPart searchFirstPartOutSideTryCatchSimple(ABCException ex, Collection allParts) { - int startIp = code.adr2pos(ex.start, true); - int endIp = code.adr2pos(ex.end, true); - - GraphPart startPart = searchPart(startIp, allParts); - return firstPartOutsideWalk(startPart, startIp, endIp, new HashSet<>()); - } - + /** + * Search first part outside try-catch. + * @param localData Local data + * @param ex Exception + * @param loops Loops + * @param allParts All parts + * @return Graph part + */ private GraphPart searchFirstPartOutSideTryCatch(AVM2LocalData localData, ABCException ex, List loops, Collection allParts) { LinkedHashSet reachable = new LinkedHashSet<>(); int startIp = localData.code.adr2pos(ex.start, true); @@ -820,6 +828,11 @@ public class AVM2Graph extends Graph { return null; } + /** + * Gets nearest non-empty part. + * @param part Part + * @return Graph part + */ private GraphPart nearestNonEmptyPart(GraphPart part) { while (isPartEmpty(part)) { part = part.nextParts.get(0); @@ -827,6 +840,16 @@ public class AVM2Graph extends Graph { return part; } + /** + * Gets catched exception IDs. + * @param part Part + * @param previouslyCatchedExceptionIds Previously catched exception IDs + * @param catchedExceptionIds Catched exception IDs + * @param finallyIndex Finally index + * @param allParts All parts + * @param loops Loops + * @param localData Local data + */ private void getCatchedExceptionIds(GraphPart part, List previouslyCatchedExceptionIds, List catchedExceptionIds, Reference finallyIndex, Collection allParts, List loops, AVM2LocalData localData) { @@ -935,6 +958,12 @@ public class AVM2Graph extends Graph { } } + /** + * Finds nearest part outside catch. + * @param tryTarget Try target + * @param catchParts Catch parts + * @return Graph part + */ private GraphPart findNearestPartOutsideCatch(GraphPart tryTarget, Set catchParts) { for (GraphPart p : catchParts) { for (GraphPart n : p.nextParts) { @@ -946,6 +975,27 @@ public class AVM2Graph extends Graph { return null; } + /** + * Checks try. + * @param currentRet Current return + * @param foundGotos Found gotos + * @param partCodes Part codes + * @param partCodePos Part code position + * @param visited Visited + * @param localData Local data + * @param part Part + * @param stopPart Stop part + * @param stopPartKind Stop part kind + * @param loops Loops + * @param throwStates Throw states + * @param allParts All parts + * @param stack Stack + * @param staticOperation Unused + * @param path Path + * @param recursionLevel Recursion level + * @return True if try is found + * @throws InterruptedException + */ private boolean checkTry(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, Set visited, AVM2LocalData localData, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, Set allParts, TranslateStack stack, int staticOperation, String path, int recursionLevel) throws InterruptedException { if (localData.parsedExceptions == null) { localData.parsedExceptions = new ArrayList<>(); @@ -1413,6 +1463,12 @@ public class AVM2Graph extends Graph { return false; } + /** + * Checks whether the part can handle visited. + * @param localData Local data + * @param part Graph part + * @return True if the part can handle visited + */ @Override protected boolean canHandleVisited(BaseLocalData localData, GraphPart part) { AVM2LocalData aLocalData = (AVM2LocalData) localData; @@ -1428,6 +1484,14 @@ public class AVM2Graph extends Graph { return true; } + /** + * Checks whether the part can handle loop. + * @param localData Local data + * @param part Graph part + * @param loops List of loops + * @param throwStates List of throw states + * @return True if the part can handle loop + */ @Override protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List loops, List throwStates) { Loop toBeLoop = null; @@ -1466,6 +1530,30 @@ public class AVM2Graph extends Graph { return true; } + /** + * Check part output. + * @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 currentLoop Current loop + * @param staticOperation Unused + * @param path Path + * @param recursionLevel Recursion level + * @return True to stop processing. False to continue. + * @throws InterruptedException + */ @Override protected boolean checkPartOutput(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, @@ -1481,6 +1569,31 @@ public class AVM2Graph extends Graph { return checkTry(currentRet, foundGotos, partCodes, partCodePos, visited, aLocalData, part, stopPart, stopPartKind, loops, throwStates, allParts, stack, staticOperation, path, recursionLevel); } + /** + * Check before decompiling next section. + * Override this method to provide custom behavior. + * @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 check(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, @@ -1607,6 +1720,13 @@ public class AVM2Graph extends Graph { return ret; } + /** + * Get next parts of a part. + * Can be overriden to provide custom behavior. + * @param localData Local data + * @param part Part + * @return List of GraphParts + */ @Override protected List getNextParts(BaseLocalData localData, GraphPart part) { AVM2LocalData aLocalData = (AVM2LocalData) localData; @@ -1618,6 +1738,17 @@ public class AVM2Graph extends Graph { return super.getNextParts(localData, part); } + /** + * Check of Part passing output. + * + * @param output List of GraphTargetItems + * @param stack Translate stack + * @param localData Local data + * @param prev Previous part + * @param part Part + * @param allParts All parts + * @return Return same part to continue processing or return another part to continue to other part. Or return null to stop. + */ @Override protected GraphPart checkPartWithOutput(List output, TranslateStack stack, BaseLocalData localData, GraphPart prev, @@ -1693,11 +1824,26 @@ public class AVM2Graph extends Graph { return part; } + + /** + * Check of part. + * @param stack Translate stack + * @param localData Local data + * @param prev Previous part + * @param part Part + * @param allParts All parts + * @return Return same part to continue processing or return another part to continue to other part. Or return null to stop. + */ @Override protected GraphPart checkPart(TranslateStack stack, BaseLocalData localData, GraphPart prev, GraphPart part, Set allParts) { return checkPartWithOutput(null, stack, localData, prev, part, allParts); } + /** + * Checks whether part is empty. + * @param part Part + * @return True if part is empty + */ @Override protected boolean isPartEmpty(GraphPart part) { if (part.nextParts.size() > 1) { @@ -1715,6 +1861,16 @@ public class AVM2Graph extends Graph { return true; } + /** + * Check loop. + * @param output List of GraphTargetItems + * @param loopItem Loop item + * @param localData Local data + * @param loops Loops + * @param throwStates Throw states + * @param stack Translate stack + * @return Return loopItem to replace current loop. Return null to continue. + */ @Override protected GraphTargetItem checkLoop(List output, LoopItem loopItem, BaseLocalData localData, List loops, List throwStates, TranslateStack stack) { if (debugDoNotProcess) { @@ -2047,6 +2203,11 @@ public class AVM2Graph extends Graph { return loopItem; } + /** + * Process various items. + * @param list List of GraphTargetItems + * @param lastLoopId Last loop id + */ @Override protected void processOther(List list, long lastLoopId) { if (list.isEmpty()) { @@ -2097,6 +2258,13 @@ public class AVM2Graph extends Graph { } } + /** + * Final process after. + * @param list List of GraphTargetItems + * @param level Level + * @param localData Local data + * @param path Path + */ @Override protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { super.finalProcessAfter(list, level, localData, path); @@ -2127,6 +2295,11 @@ public class AVM2Graph extends Graph { } } + /** + * Check if item is integer or pop integer. + * @param item GraphTargetItem + * @return True if item is integer or pop integer + */ private boolean isIntegerOrPopInteger(GraphTargetItem item) { if (item instanceof IntegerValueAVM2Item) { return true; @@ -2137,6 +2310,14 @@ public class AVM2Graph extends Graph { return false; } + /** + * Final process. + * @param list List of GraphTargetItems + * @param level Level + * @param localData Local data + * @param path Path + * @throws InterruptedException + */ @Override protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { if (debugDoNotProcess) { @@ -2489,6 +2670,13 @@ public class AVM2Graph extends Graph { super.finalProcess(list, level, localData, path); } + /** + * Gets data for final process. + * @param localData + * @param loops + * @param throwStates + * @return + */ @Override protected FinalProcessLocalData getFinalData(BaseLocalData localData, List loops, List throwStates) { FinalProcessLocalData finalProcess = new AVM2FinalProcessLocalData(loops, ((AVM2LocalData) localData).localRegNames, ((AVM2LocalData) localData).setLocalPosToGetLocalPos); @@ -2496,6 +2684,11 @@ public class AVM2Graph extends Graph { return finalProcess; } + /** + * Prepares local data for branch. + * @param localData Local data + * @return Local data for a branch + */ @Override public AVM2LocalData prepareBranchLocalData(BaseLocalData localData) { AVM2LocalData aLocalData = (AVM2LocalData) localData; @@ -2506,6 +2699,13 @@ public class AVM2Graph extends Graph { return ret; } + /** + * Checks switch statement. + * @param localData Local data + * @param switchItem Switch item + * @param otherSides Other sides + * @param output Output + */ @Override protected void checkSwitch(BaseLocalData localData, SwitchItem switchItem, Collection otherSides, List output) { if (output.isEmpty()) { @@ -2539,6 +2739,11 @@ public class AVM2Graph extends Graph { } } + /** + * Checks if part is a switch. + * @param part Part + * @return True if part is a switch + */ @Override protected boolean partIsSwitch(GraphPart part) { if (part.end < 0) { @@ -2547,6 +2752,12 @@ public class AVM2Graph extends Graph { return avm2code.code.get(part.end).definition instanceof LookupSwitchIns; } + /** + * Gets throw states. + * @param localData Local data + * @param allParts All parts + * @return List of ThrowStates + */ @Override protected List getThrowStates(BaseLocalData localData, Set allParts) { @@ -2628,6 +2839,15 @@ public class AVM2Graph extends Graph { return ret; } + /** + * Walk catch parts register. + * @param registerId Register id + * @param part Part + * @param startIp Start ip + * @param catchParts Catch parts + * @param path Path + * @param visited Visited + */ private void walkCatchPartsReg(int registerId, GraphPart part, int startIp, Set catchParts, List path, Set visited) { if (visited.contains(part)) { return; @@ -2661,6 +2881,16 @@ public class AVM2Graph extends Graph { } } + /** + * Walk catch parts. + * @param stats Code stats + * @param part Part + * @param startIp Start ip + * @param catchParts Catch parts + * @param scopePos Scope position + * @param allParts All parts + * @param isFinally True if the catch is finally + */ private void walkCatchParts(CodeStats stats, GraphPart part, int startIp, Set catchParts, int scopePos, Set allParts, boolean isFinally) { if (catchParts.contains(part)) { return; @@ -2704,19 +2934,13 @@ public class AVM2Graph extends Graph { part.nextParts.add(secondPart); secondPart.refs.add(part); - secondPart.type = GraphPart.TYPE_NONE; secondPart.discoveredTime = part.discoveredTime; secondPart.closedTime = part.closedTime; secondPart.finishedTime = part.finishedTime; - secondPart.iloop_header = part.iloop_header; - secondPart.irreducible = part.irreducible; secondPart.level = part.level; secondPart.numBlocks = part.numBlocks; secondPart.order = part.order; secondPart.path = part.path; - secondPart.posX = part.posX; - secondPart.posY = part.posY; - secondPart.traversed = true; allParts.add(secondPart); } catchParts.add(part); @@ -2729,6 +2953,12 @@ public class AVM2Graph 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 commands, TranslateStack stack) { for (int i = 0; i < stack.size(); i++) { //These are often obfuscated, so ignore them @@ -2740,6 +2970,12 @@ public class AVM2Graph extends Graph { super.makeAllCommands(commands, stack); } + /** + * 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 protected SecondPassData prepareSecondPass(List list) { return new SecondPassData(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index d3686159a..1deeb1611 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -23,49 +23,91 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.types.MethodBody; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.Graph; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSource; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.helpers.Reference; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; /** - * + * AVM2 graph source. * @author JPEXS */ public class AVM2GraphSource extends GraphSource { + /** + * AVM2 code + */ private final AVM2Code code; + /** + * Is static + */ boolean isStatic; + /** + * Class index + */ int classIndex; + /** + * Script index + */ int scriptIndex; + /** + * Local registers - map of register index to value item + */ HashMap localRegs; + /** + * ABC + */ ABC abc; + /** + * Method body + */ MethodBody body; + /** + * Local register names - map of register index to name + */ HashMap localRegNames; + /** + * Fully qualified names + */ List fullyQualifiedNames; + /** + * Local register assignment IPs - map of register index to IP + */ HashMap localRegAssigmentIps; + /** + * Get AVM2 code + * @return AVM2 code + */ public AVM2Code getCode() { return code; } + /** + * Constructs a new AVM2 graph source + * @param code AVM2 code + * @param isStatic Is static + * @param scriptIndex Script index + * @param classIndex Class index + * @param localRegs Local registers + * @param abc ABC + * @param body Method body + * @param localRegNames Local register names + * @param fullyQualifiedNames Fully qualified names + * @param localRegAssigmentIp Local register assignment IPs + */ public AVM2GraphSource(AVM2Code code, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, ABC abc, MethodBody body, HashMap localRegNames, List fullyQualifiedNames, HashMap localRegAssigmentIp) { this.code = code; this.isStatic = isStatic; @@ -80,11 +122,20 @@ public class AVM2GraphSource extends GraphSource { code.calculateDebugFileLine(abc); } + /** + * Gets important addresses + * @return Important addresses + */ @Override public Set getImportantAddresses() { return code.getImportantOffsets(body, false); } + /** + * 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 < code.code.size()) { @@ -93,21 +144,47 @@ public class AVM2GraphSource extends GraphSource { return ""; } + /** + * Gets the size of the graph source + * @return The size of the graph source + */ @Override public int size() { return code.code.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 AVM2Instruction get(int pos) { return code.code.get(pos); } + /** + * Checks if the graph source is empty + * @return True if the graph source is empty, false otherwise + */ @Override public boolean isEmpty() { return code.code.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 + */ @Override public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { List ret = new ArrayList<>(); @@ -118,16 +195,32 @@ public class AVM2GraphSource extends GraphSource { return ret; } + /** + * Converts address to position + * @param adr Address + * @return Position + */ @Override public int adr2pos(long adr) { return code.adr2pos(adr); } + /** + * Converts address to position + * @param adr Address + * @param nearest Nearest + * @return Position + */ @Override public int adr2pos(long adr, boolean nearest) { return code.adr2pos(adr, true); } + /** + * Converts position to address + * @param pos Position + * @return Address + */ @Override public long pos2adr(int pos) { return code.pos2adr(pos); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/package-info.java new file mode 100644 index 000000000..33364df9c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/package-info.java @@ -0,0 +1,4 @@ +/** + * AVM2 control flow graph. + */ +package com.jpexs.decompiler.flash.abc.avm2.graph; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java index f5d7969f5..2bd96c3af 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instruction.java @@ -32,43 +32,63 @@ import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.ecma.EcmaScript; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.DottedChain; -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.decompiler.graph.model.LocalData; import com.jpexs.helpers.Helper; + import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** - * + * AVM2 instruction. * @author JPEXS */ public class AVM2Instruction implements Cloneable, GraphSourceItem { + /** + * Definition + */ public InstructionDefinition definition; + /** + * Operands + */ public int[] operands; + /** + * Address + */ private long address; + /** + * Comment + */ public String comment; + /** + * Ignored + */ private boolean ignored = false; + /** + * Line + */ private int line; + /** + * File + */ private String file; + /** + * Virtual address - used for deobfuscation + */ private long virtualAddress = -1; + /** + * Old style names for getlocal and setlocal + */ private static final Map oldStyleNames = new HashMap<>(); static { @@ -78,11 +98,19 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { } } + /** + * Gets file offset. + * @return File offset + */ @Override public long getFileOffset() { return -1; } + /** + * Gets the line offset. + * @return Line offset + */ @Override public long getLineOffset() { if (virtualAddress > -1) { @@ -91,21 +119,42 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return getAddress(); } + /** + * Sets file and line. + * @param file File + * @param line Line + */ public void setFileLine(String file, int line) { this.file = file; this.line = line; } - public AVM2Instruction(long offset, int insructionCode, int[] operands) { - this(offset, AVM2Code.instructionSet[insructionCode], operands); + /** + * Constructs a new AVM2 instruction. + * @param offset Offset + * @param instructionCode Instruction code + * @param operands Operands + */ + public AVM2Instruction(long offset, int instructionCode, int[] operands) { + this(offset, AVM2Code.instructionSet[instructionCode], operands); } + /** + * Constructs a new AVM2 instruction. + * @param address Address + * @param definition Definition + * @param operands Operands + */ public AVM2Instruction(long address, InstructionDefinition definition, int[] operands) { this.definition = definition; this.operands = operands != null && operands.length > 0 ? operands : null; this.address = address; } + /** + * Gets the bytes. + * @return Bytes + */ public byte[] getBytes() { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { @@ -142,6 +191,10 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return bos.toByteArray(); } + /** + * Gets the length of the bytes. + * @return Length of the bytes + */ @Override public int getBytesLength() { int cnt = 1; @@ -174,6 +227,10 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return cnt; } + /** + * Gets the offsets. + * @return Offsets + */ public List getOffsets() { List ret = new ArrayList<>(); String s = ""; @@ -196,6 +253,12 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return ret; } + /** + * Gets the parameter. + * @param constants Constants + * @param idx Index of operand + * @return Parameter + */ public Object getParam(AVM2ConstantPool constants, int idx) { //if (idx < 0 || idx >= definition.operands.length) { // return null; @@ -223,10 +286,22 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { } } + /** + * Gets the parameter as a long. + * @param constants Constants + * @param idx Index of operand + * @return Parameter as a long + */ public Long getParamAsLong(AVM2ConstantPool constants, int idx) { return (Long) getParam(constants, idx); } + /** + * Gets all parameters as string. + * @param constants Constants + * @param fullyQualifiedNames Fully qualified names + * @return All parameters as string + */ public String getParams(AVM2ConstantPool constants, List fullyQualifiedNames) { StringBuilder s = new StringBuilder(); for (int i = 0; i < definition.operands.length; i++) { @@ -398,6 +473,10 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return s.toString(); } + /** + * Gets the comment. + * @return Comment + */ public String getComment() { if (isIgnored()) { return " ;ignored"; @@ -408,11 +487,19 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return " ;" + comment; } + /** + * Checks whether this item is ignored. + * @return True if this item is ignored, false otherwise + */ @Override public boolean isIgnored() { return ignored; } + /** + * To string. + * @return String + */ @Override public String toString() { StringBuilder s = new StringBuilder(); @@ -426,12 +513,22 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return s.toString(); } + /** + * To string. + * @param writer Writer + * @param localData Local data + * @return Writer + */ public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) { writer.appendNoHilight(Helper.formatAddress(address) + " " + String.format("%-30s", Helper.byteArrToString(getBytes())) + getCustomizedInstructionName()); writer.appendNoHilight(getParams(localData.constantsAvm2, localData.fullyQualifiedNames) + getComment()); return writer; } + /** + * Gets the customized instruction name. + * @return Customized instruction name + */ private String getCustomizedInstructionName() { if (Configuration.useOldStyleGetSetLocalsAs3PCode.get() && oldStyleNames.containsKey(definition.instructionName)) { return oldStyleNames.get(definition.instructionName); @@ -439,6 +536,12 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return definition.instructionName; } + /** + * To string without address. + * @param constants Constants + * @param fullyQualifiedNames Fully qualified names + * @return String without address + */ public String toStringNoAddress(AVM2ConstantPool constants, List fullyQualifiedNames) { String s = getCustomizedInstructionName(); if (Configuration.padAs3PCodeInstructionName.get()) { @@ -450,6 +553,15 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return s.trim(); } + /** + * 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 output, int staticOperation, String path) throws InterruptedException { AVM2LocalData aLocalData = (AVM2LocalData) localData; @@ -460,58 +572,114 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { }*/ } + /** + * 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) { AVM2LocalData aLocalData = (AVM2LocalData) localData; return getStackPopCount(aLocalData); } + /** + * Gets the number of stack items that are popped by this item. + * @param aLocalData Local data + * @return Number of stack items that are popped by this item + */ public int getStackPopCount(AVM2LocalData aLocalData) { return definition.getStackPopCount(this, aLocalData.abc); } + /** + * 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) { AVM2LocalData aLocalData = (AVM2LocalData) localData; return getStackPushCount(aLocalData); } + /** + * Gets the number of stack items that are pushed by this item. + * @param aLocalData Local data + * @return Number of stack items that are pushed by this item + */ public int getStackPushCount(AVM2LocalData aLocalData) { return definition.getStackPushCount(this, aLocalData.abc); } + /** + * Checks whether this item is a jump. + * @return True if this item is a jump, false otherwise + */ @Override public boolean isJump() { return definition instanceof JumpIns; } + /** + * Checks whether this item is a branch. + * @return True if this item is a branch, false otherwise + */ @Override public boolean isBranch() { return (definition instanceof IfTypeIns) || (definition instanceof LookupSwitchIns); } + /** + * 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 (definition instanceof ReturnValueIns) || (definition instanceof ReturnVoidIns) || (definition instanceof ThrowIns); } + /** + * Gets the address. + * @return Address + */ @Override public long getAddress() { return address; } + /** + * Sets the address. + * @param address Address + */ public void setAddress(long address) { this.address = address; } + /** + * Gets the target address of jump. + * @return Target address. + */ public long getTargetAddress() { return address + 4 /*getBytesLength()*/ + operands[0]; } + /** + * Sets the target offset of jump. + * @param offset Offset + */ public void setTargetOffset(int offset) { operands[0] = offset; } + + /** + * Gets branches + * @param code Code + * @return List of IPs to branch to + */ @Override public List getBranches(GraphSource code) { List ret = new ArrayList<>(); @@ -531,21 +699,39 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { return ret; } + /** + * Checks whether the loops are ignored. + * @return True if the loops are ignored, false otherwise + */ @Override public boolean ignoredLoops() { return false; } + /** + * 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; } + /** + * 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 definition instanceof DeobfuscatePopIns; } + /** + * Clone the instruction. + * @return Cloned instruction + */ @Override public AVM2Instruction clone() { try { @@ -559,11 +745,19 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { } } + /** + * Gets the line in the high level source code. + * @return Line + */ @Override public int getLine() { return line; } + /** + * Gets the high level source code file name. + * @return File name + */ @Override public String getFile() { return file; @@ -571,12 +765,12 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { /** * Set operand value the right way - update offsets neccessarily. Because - * some operand types are variable length (like U30) + * some operand types are variable length (like U30). * - * @param operandIndex - * @param newValue - * @param code - * @param body + * @param operandIndex Index of operand + * @param newValue New value + * @param code Code + * @param body Method body */ public void setOperand(int operandIndex, int newValue, AVM2Code code, MethodBody body) { int oldByteCount = getBytesLength(); @@ -591,11 +785,11 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { /** * Set operand values the right way - update offsets neccessarily. Because - * some operand types are variable length (like U30) + * some operand types are variable length (like U30). * - * @param operands - * @param code - * @param body + * @param operands Operands + * @param code Code + * @param body Method body */ public void setOperands(int[] operands, AVM2Code code, MethodBody body) { int oldByteCount = getBytesLength(); @@ -608,11 +802,23 @@ public class AVM2Instruction implements Cloneable, GraphSourceItem { body.setModified(); } + /** + * 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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2InstructionFlag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2InstructionFlag.java index 522a9a0f6..8fbfbe60e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2InstructionFlag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2InstructionFlag.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2.instructions; /** - * + * Flags for AVM2 instructions. * @author JPEXS */ public enum AVM2InstructionFlag { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instructions.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instructions.java index 19e065ff2..babd0c61b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instructions.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/AVM2Instructions.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.abc.avm2.instructions; /** - * + * Set of AVM2 instructions. * @author JPEXS */ public class AVM2Instructions { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java index 5157c0c3c..d8ab8b99d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/DeobfuscatePopIns.java @@ -21,31 +21,61 @@ import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; + import java.util.List; /** - * + * DeobfuscatePop instruction. + * Special pop pused for deobfuscation purposes. * @author JPEXS */ public class DeobfuscatePopIns extends PopIns { + /** + * Instruction name + */ public static final String NAME = "ffdec_deobfuscatepop"; + /** + * Singleton instance + */ private static final DeobfuscatePopIns instance = new DeobfuscatePopIns(); + /** + * Returns singleton instance + * @return Singleton instance + */ public static final DeobfuscatePopIns getInstance() { return instance; } + /** + * Constructs new instance + */ private DeobfuscatePopIns() { instructionName = NAME; } + + /** + * Translates instruction to high level code. + * @param localData Local data area + * @param stack Translate stack + * @param ins Instruction + * @param output Output + * @param path Path + */ @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { stack.pop(); //Just ignore the value } + /** + * Gets number of pops from stack. + * @param ins Instruction + * @param abc ABC + * @return Number of pops from stack + */ @Override public int getStackPopCount(AVM2Instruction ins, ABC abc) { return 1; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/IfTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/IfTypeIns.java index 5367ba571..991c4b27d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/IfTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/IfTypeIns.java @@ -19,13 +19,21 @@ package com.jpexs.decompiler.flash.abc.avm2.instructions; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; + import java.util.HashMap; /** - * + * IfType instruction interface. * @author JPEXS */ public interface IfTypeIns { - public abstract void translateInverted(AVM2LocalData localData, HashMap localRegs, TranslateStack stack, AVM2Instruction ins); + /** + * Translates the instruction as inverted. + * @param localData Local data + * @param localRegs Local registers + * @param stack Stack + * @param ins Instruction + */ + public void translateInverted(AVM2LocalData localData, HashMap localRegs, TranslateStack stack, AVM2Instruction ins); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index e8618acc6..b76e06dd3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -23,35 +23,9 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2VerifyErrorException; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; -import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ApplyTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ClassAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConstructAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostDecrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; @@ -61,43 +35,57 @@ import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitWithSlot; import com.jpexs.decompiler.flash.abc.types.traits.Traits; -import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.DottedChain; -import com.jpexs.decompiler.graph.GraphPart; -import com.jpexs.decompiler.graph.GraphSourceItem; -import com.jpexs.decompiler.graph.GraphTargetItem; -import com.jpexs.decompiler.graph.ScopeStack; -import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.*; import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.helpers.Reference; + import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.Stack; +import java.util.*; /** - * + * AVM2 Instruction definition. * @author JPEXS */ public abstract class InstructionDefinition implements Serializable { + /** + * Serial version UID + */ public static final long serialVersionUID = 1L; + /** + * Operands + */ public int[] operands; + /** + * Instruction name + */ public String instructionName = ""; + /** + * Instruction code + */ public int instructionCode = 0; + /** + * Can throw exception + */ public boolean canThrow; + /** + * Flags + */ public AVM2InstructionFlag[] flags; + /** + * Constructs new instance + * @param instructionCode Instruction code + * @param instructionName Instruction name + * @param operands Operands + * @param canThrow Can throw exception + * @param flags Flags + */ public InstructionDefinition(int instructionCode, String instructionName, int[] operands, boolean canThrow, AVM2InstructionFlag... flags) { this.instructionCode = instructionCode; this.instructionName = instructionName; @@ -106,6 +94,11 @@ public abstract class InstructionDefinition implements Serializable { this.flags = flags; } + /** + * Checks if instruction has flag + * @param flag Flag + * @return True if instruction has flag + */ public boolean hasFlag(AVM2InstructionFlag flag) { for (AVM2InstructionFlag f : flags) { if (f == flag) { @@ -115,6 +108,10 @@ public abstract class InstructionDefinition implements Serializable { return false; } + /** + * To string + * @return String representation + */ @Override public String toString() { StringBuilder s = new StringBuilder(); @@ -125,6 +122,13 @@ public abstract class InstructionDefinition implements Serializable { return s.toString(); } + /** + * Verify instruction + * @param lda Local data area + * @param constants Constant pool + * @param ins Instruction + * @throws AVM2VerifyErrorException + */ public void verify(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) throws AVM2VerifyErrorException { for (int i = 0; i < operands.length; i++) { int operand = operands[i]; @@ -177,22 +181,77 @@ public abstract class InstructionDefinition implements Serializable { } } + /** + * Checks if instruction cannot be statically computed. + * @return True = cannot be statically computed, false = can be statically computed + */ public boolean isNotCompileTimeSupported() { return false; } + /** + * Executes instruction. + * @param lda Local data area + * @param constants Constant pool + * @param ins Instruction + * @return True if instruction was executed, false if not + * @throws AVM2ExecutionException + */ public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) throws AVM2ExecutionException { //throw new UnsupportedOperationException("Instruction " + instructionName + " not implemented"); return false; } + /** + * Throws illegal opcode exception. + * @param lda Local data area + * @param ins Instruction + * @throws AVM2VerifyErrorException + */ protected void illegalOpCode(LocalDataArea lda, AVM2Instruction ins) throws AVM2VerifyErrorException { throw new AVM2VerifyErrorException(AVM2VerifyErrorException.ILLEGAL_OPCODE, lda.isDebug(), new Object[]{lda.methodName, instructionCode, ins.getAddress()}); } + /** + * Translates instruction to high level code. + * @param localData Local data area + * @param stack Translate stack + * @param ins Instruction + * @param output Output + * @param path Path + * @throws InterruptedException + */ public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) throws InterruptedException { } + /** + * Translates instruction to high level code. + * @param switchParts Switch parts + * @param callStack Call stack + * @param abcIndex ABC indexing + * @param setLocalPosToGetLocalPos Set local position to get local position + * @param lineStartItem Line start item + * @param isStatic Is static + * @param scriptIndex Script index + * @param classIndex Class index + * @param localRegs Local registers + * @param stack Translate stack + * @param scopeStack Scope stack + * @param localScopeStack Local scope stack + * @param ins Instruction + * @param output Output + * @param body Method body + * @param abc ABC + * @param localRegNames Local register names + * @param localRegTypes Local register types + * @param fullyQualifiedNames Fully qualified names + * @param path Path + * @param localRegsAssignmentIps Local registers assignment IPs + * @param ip IP + * @param code AVM2 code + * @param thisHasDefaultToPrimitive This has default to primitive + * @throws InterruptedException + */ public void translate(Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, Reference lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, AVM2Instruction ins, List output, MethodBody body, ABC abc, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, String path, HashMap localRegsAssignmentIps, int ip, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException { AVM2LocalData localData = new AVM2LocalData(); localData.allSwitchParts = switchParts; @@ -219,14 +278,32 @@ public abstract class InstructionDefinition implements Serializable { lineStartItem.setVal(localData.lineStartInstruction); } + /** + * Gets number of pops from stack. + * @param ins Instruction + * @param abc ABC + * @return Number of pops from stack + */ public int getStackPopCount(AVM2Instruction ins, ABC abc) { return 0; } + /** + * Gets number of pushes to stack. + * @param ins Instruction + * @param abc ABC + * @return Number of pushes to stack + */ public int getStackPushCount(AVM2Instruction ins, ABC abc) { return 0; } + /** + * Resolves multiname. + * @param localData Local data area + * @param constants Constant pool + * @param multinameIndex Multiname index + */ protected void resolveMultiname(LocalDataArea localData, AVM2ConstantPool constants, int multinameIndex) { if (multinameIndex > 0 && multinameIndex < constants.getMultinameCount()) { Multiname multiname = constants.getMultiname(multinameIndex); @@ -239,6 +316,16 @@ public abstract class InstructionDefinition implements Serializable { } } + /** + * Resolves multiname. + * @param localData Local data area + * @param property Property + * @param stack Translate stack + * @param constants Constant pool + * @param multinameIndex Multiname index + * @param ins Instruction + * @return Resolved multiname + */ protected FullMultinameAVM2Item resolveMultiname(AVM2LocalData localData, boolean property, TranslateStack stack, AVM2ConstantPool constants, int multinameIndex, AVM2Instruction ins) { GraphTargetItem ns = null; GraphTargetItem name = null; @@ -255,6 +342,12 @@ public abstract class InstructionDefinition implements Serializable { return new FullMultinameAVM2Item(property, ins, localData.lineStartInstruction, multinameIndex, localData.abc.constants.getMultiname(multinameIndex).getName(localData.getConstants(), new ArrayList<>(), true, true), name, ns); } + /** + * Gets required stack size for multiname. + * @param constants Constant pool + * @param multinameIndex Multiname index + * @return Required stack size + */ protected int getMultinameRequiredStackSize(AVM2ConstantPool constants, int multinameIndex) { int res = 0; if (multinameIndex > 0 && multinameIndex < constants.getMultinameCount()) { @@ -274,78 +367,40 @@ public abstract class InstructionDefinition implements Serializable { return res; } - protected int resolvedCount(AVM2ConstantPool constants, int multinameIndex) { - int pos = 0; - if (constants.getMultiname(multinameIndex).needsNs()) { - pos++; - } - if (constants.getMultiname(multinameIndex).needsName()) { - pos++; - } - return pos; - - } - - protected String resolveMultinameNoPop(int pos, Stack stack, AVM2ConstantPool constants, int multinameIndex, AVM2Instruction ins, List fullyQualifiedNames) { - String ns = ""; - String name; - if (constants.getMultiname(multinameIndex).needsNs()) { - ns = "[" + stack.get(pos) + "]"; - pos++; - } - if (constants.getMultiname(multinameIndex).needsName()) { - name = stack.get(pos).toString(); - } else { - name = GraphTextWriter.hilighOffset(constants.getMultiname(multinameIndex).getName(constants, fullyQualifiedNames, false, true), ins.getAddress()); - } - return name + ns; - } - + /** + * Gets stack delta. Stack push count - stack pop count. + * @param ins Instruction + * @param abc ABC + * @return Stack delta + */ public int getStackDelta(AVM2Instruction ins, ABC abc) { return getStackPushCount(ins, abc) - getStackPopCount(ins, abc); } + /** + * Gets scope stack delta. Scope stack push count - scope stack pop count. + * @param ins Instruction + * @param abc ABC + * @return Scope stack delta + */ public int getScopeStackDelta(AVM2Instruction ins, ABC abc) { return 0; } - protected boolean isRegisterCompileTime(int regId, int ip, HashMap> refs, AVM2Code code) { - Set previous = new HashSet<>(); - AVM2Code.getPreviousReachableIps(ip, refs, previous, new HashSet<>()); - for (int p : previous) { - if (p < 0) { - continue; - } - if (p >= code.code.size()) { - continue; - } - AVM2Instruction sins = code.code.get(p); - if (code.code.get(p).definition instanceof SetLocalTypeIns) { - SetLocalTypeIns sl = (SetLocalTypeIns) sins.definition; - if (sl.getRegisterId(sins) == regId) { - if (!AVM2Code.isDirectAncestor(ip, p, refs)) { - return false; - } - } - } - if ((code.code.get(p).definition instanceof IncLocalIns) - || (code.code.get(p).definition instanceof IncLocalIIns) - || (code.code.get(p).definition instanceof DecLocalIns) - || (code.code.get(p).definition instanceof DecLocalIIns)) { - if (sins.operands[0] == regId) { - if (!AVM2Code.isDirectAncestor(ip, p, refs)) { - return false; - } - } - } - } - return true; - } - + /** + * Checks if instruction is exit instruction. (e.g. return, throw) + * @return True if instruction is exit instruction + */ public boolean isExitInstruction() { return false; } + /** + * Gets item IP. + * @param localData Local data + * @param item Item + * @return Item IP or -1 if not found + */ public static int getItemIp(AVM2LocalData localData, GraphTargetItem item) { GraphSourceItem src = item.getSrc(); if (src == null) { @@ -354,10 +409,27 @@ public abstract class InstructionDefinition implements Serializable { return localData.code.adr2pos(src.getAddress()); } + /** + * Searches for slot name. + * @param slotIndex Slot index + * @param localData Local data + * @param obj Object + * @param realObj Real object + * @return Slot multiname or null if not found + */ protected static Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj, Reference realObj) { return searchSlotName(slotIndex, localData, obj, -1, realObj); } + /** + * Searches for slot name. + * @param slotIndex Slot index + * @param localData Local data + * @param obj Object + * @param multiNameIndex Multiname index + * @param realObj Real object + * @return Slot multiname or null if not found + */ private static Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj, int multiNameIndex, Reference realObj) { if ((obj instanceof ExceptionAVM2Item) && (multiNameIndex == -1 || ((ExceptionAVM2Item) obj).exception.name_index == multiNameIndex)) { return localData.getConstants().getMultiname(((ExceptionAVM2Item) obj).exception.name_index); @@ -402,6 +474,15 @@ public abstract class InstructionDefinition implements Serializable { return null; } + /** + * Handles set property. + * @param init Init + * @param localData Local data + * @param stack Translate stack + * @param ins Instruction + * @param output Output + * @param path Path + */ public void handleSetProperty(boolean init, AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { int multinameIndex = ins.operands[0]; GraphTargetItem value = stack.pop(); @@ -649,6 +730,18 @@ public abstract class InstructionDefinition implements Serializable { SetTypeIns.handleResult(value, stack, output, localData, (GraphTargetItem) result, -1, type.getVal()); } + /** + * Checks if increment or decrement. + * @param standalone Standalone + * @param multinameIndex Multiname index + * @param ins Instruction + * @param localData Local data + * @param item Item + * @param valueLocalReg Value local register + * @param nameLocalReg Name local register + * @param objLocalReg Object local register + * @return Increment or decrement item or null if not found + */ private GraphTargetItem checkIncDec(boolean standalone, int multinameIndex, AVM2Instruction ins, AVM2LocalData localData, GraphTargetItem item, LocalRegAVM2Item valueLocalReg, LocalRegAVM2Item nameLocalReg, LocalRegAVM2Item objLocalReg) { if (item instanceof SetLocalAVM2Item) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java index 8b6bf31e7..74356a515 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java @@ -17,23 +17,26 @@ package com.jpexs.decompiler.flash.abc.avm2.instructions; import com.jpexs.decompiler.flash.abc.AVM2LocalData; -import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.decompiler.graph.model.DuplicateItem; + import java.util.List; /** - * + * SetType instruction interface. * @author JPEXS */ public interface SetTypeIns { + /** + * Handles number to int conversion. + * @param value Value to convert + * @param type Type to convert to + * @return Value + */ public static GraphTargetItem handleNumberToInt(GraphTargetItem value, GraphTargetItem type) { if ((value instanceof ConvertAVM2Item) || (value instanceof CoerceAVM2Item)) { if (type != null && (type.equals(TypeItem.INT) || type.equals(TypeItem.UINT))) { @@ -45,6 +48,16 @@ public interface SetTypeIns { return value; } + /** + * Handles result. + * @param value Value + * @param stack Stack + * @param output Output + * @param localData Local data + * @param result Result + * @param regId Register ID + * @param type Type + */ public static void handleResult(GraphTargetItem value, TranslateStack stack, List output, AVM2LocalData localData, GraphTargetItem result, int regId, GraphTargetItem type) { GraphTargetItem notCoercedValue = value; if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/UnknownInstruction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/UnknownInstruction.java index 9f7744804..b7957379a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/UnknownInstruction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/UnknownInstruction.java @@ -22,20 +22,39 @@ import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException; import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2VerifyErrorException; /** - * + * Unknown instruction definition. * @author JPEXS */ public class UnknownInstruction extends InstructionDefinition { + /** + * Constructs a new UnknownInstruction object. + * @param instructionCode Instruction code + */ public UnknownInstruction(int instructionCode) { super(instructionCode, "instruction_" + Integer.toString(instructionCode), new int[0], false); } + /** + * Verify instruction + * @param lda Local data area + * @param constants Constant pool + * @param ins Instruction + * @throws AVM2VerifyErrorException + */ @Override public void verify(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) throws AVM2VerifyErrorException { illegalOpCode(lda, ins); } + /** + * Executes instruction. + * @param lda Local data area + * @param constants Constant pool + * @param ins Instruction + * @return True if instruction was executed, false if not + * @throws AVM2ExecutionException + */ @Override public boolean execute(LocalDataArea lda, AVM2ConstantPool constants, AVM2Instruction ins) throws AVM2ExecutionException { return false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/package-info.java new file mode 100644 index 000000000..e153b688b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/package-info.java @@ -0,0 +1,4 @@ +/** + * Alchemy (domain memory) AVM2 instructions + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/package-info.java new file mode 100644 index 000000000..ee313adab --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/arithmetic/package-info.java @@ -0,0 +1,4 @@ +/** + * Arithmetic AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.arithmetic; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/bitwise/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/bitwise/package-info.java new file mode 100644 index 000000000..3ec8606a1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/bitwise/package-info.java @@ -0,0 +1,4 @@ +/** + * Bitwise AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.bitwise; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/comparison/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/comparison/package-info.java new file mode 100644 index 000000000..18039f7a9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/comparison/package-info.java @@ -0,0 +1,4 @@ +/** + * Comparison AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.comparison; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/package-info.java new file mode 100644 index 000000000..d50a27b55 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/package-info.java @@ -0,0 +1,4 @@ +/** + * Construction AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.construction; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/debug/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/debug/package-info.java new file mode 100644 index 000000000..03ba68e53 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/debug/package-info.java @@ -0,0 +1,4 @@ +/** + * Debug AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.debug; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/package-info.java new file mode 100644 index 000000000..8dc9028ab --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/package-info.java @@ -0,0 +1,4 @@ +/** + * Execution AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.executing; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/package-info.java new file mode 100644 index 000000000..04a365d09 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/jumps/package-info.java @@ -0,0 +1,4 @@ +/** + * Jump, ifs and switch AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.jumps; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/package-info.java new file mode 100644 index 000000000..de37d3ab8 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/package-info.java @@ -0,0 +1,4 @@ +/** + * AVM2 instructions that work with local registers. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.localregs; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/package-info.java new file mode 100644 index 000000000..4b8f50283 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/decimalsupport/package-info.java @@ -0,0 +1,4 @@ +/** + * Decimal support AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.other.decimalsupport; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/deprecated/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/deprecated/package-info.java new file mode 100644 index 000000000..5c19b4de3 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/deprecated/package-info.java @@ -0,0 +1,4 @@ +/** + * Deprecated AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.other.deprecated; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/floatsupport/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/floatsupport/package-info.java new file mode 100644 index 000000000..19c49f190 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/floatsupport/package-info.java @@ -0,0 +1,4 @@ +/** + * Float support AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.other.floatsupport; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/package-info.java new file mode 100644 index 000000000..a5e12047e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/package-info.java @@ -0,0 +1,4 @@ +/** + * Other uncategorized AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.other; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/unknown/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/unknown/package-info.java new file mode 100644 index 000000000..9a6a39f1b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/unknown/package-info.java @@ -0,0 +1,4 @@ +/** + * Unknown AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.other.unknown; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/package-info.java new file mode 100644 index 000000000..e5cb440b6 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/package-info.java @@ -0,0 +1,4 @@ +/** + * AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/package-info.java new file mode 100644 index 000000000..96ac5afae --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/package-info.java @@ -0,0 +1,4 @@ +/** + * Stack AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.stack; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/package-info.java new file mode 100644 index 000000000..f2316afad --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/types/package-info.java @@ -0,0 +1,4 @@ +/** + * Type checking and conversion AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.types; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/package-info.java new file mode 100644 index 000000000..f6bbba931 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/xml/package-info.java @@ -0,0 +1,4 @@ +/** + * XML AVM2 instructions. + */ +package com.jpexs.decompiler.flash.abc.avm2.instructions.xml; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/package-info.java new file mode 100644 index 000000000..a42d3f382 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level AVM2 model of various clauses. + */ +package com.jpexs.decompiler.flash.abc.avm2.model.clauses; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/package-info.java new file mode 100644 index 000000000..947767238 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level AVM2 model of operations. + */ +package com.jpexs.decompiler.flash.abc.avm2.model.operations; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/package-info.java new file mode 100644 index 000000000..54bfd7bdc --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level AVM2 model. + */ +package com.jpexs.decompiler.flash.abc.avm2.model; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/package-info.java new file mode 100644 index 000000000..1d70bac35 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/package-info.java @@ -0,0 +1,4 @@ +/** + * AVM2 (ActionScript Virtual Machine 2) bytecode. + */ +package com.jpexs.decompiler.flash.abc.avm2; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/package-info.java new file mode 100644 index 000000000..02ab9451c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing AVM2 ActionScript and/or P-code. + */ +package com.jpexs.decompiler.flash.abc.avm2.parser; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/package-info.java new file mode 100644 index 000000000..b5a26e335 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing AVM2 P-code. + */ +package com.jpexs.decompiler.flash.abc.avm2.parser.pcode; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/package-info.java new file mode 100644 index 000000000..4e1c9e7d4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing AVM2 (ActionScript 3) scripts. + */ +package com.jpexs.decompiler.flash.abc.avm2.parser.script; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfoparser/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfoparser/package-info.java new file mode 100644 index 000000000..39f0e9d28 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/methodinfoparser/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing method info P-code. + */ +package com.jpexs.decompiler.flash.abc.methodinfoparser; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/package-info.java new file mode 100644 index 000000000..4b2cc2eda --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/package-info.java @@ -0,0 +1,4 @@ +/** + * ActionScript Bytecode (ABC). + */ +package com.jpexs.decompiler.flash.abc; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 90e27ad3e..a2619c732 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -22,7 +22,7 @@ import com.jpexs.decompiler.flash.abc.ABCInputStream; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.CodeStats; -import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCode; +import com.jpexs.decompiler.flash.abc.avm2.UnknownInstructionCodeException; import com.jpexs.decompiler.flash.abc.avm2.deobfuscation.DeobfuscationLevel; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; @@ -45,17 +45,10 @@ import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import com.jpexs.helpers.MemoryInputStream; import com.jpexs.helpers.stat.Statistics; + import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.*; +import java.util.concurrent.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -153,7 +146,7 @@ public final class MethodBody implements Cloneable { if (abc != null) { avm2Code.removeWrongIndices(abc.constants); } - } catch (UnknownInstructionCode | IOException ex) { + } catch (UnknownInstructionCodeException | IOException ex) { avm2Code = new AVM2Code(); logger.log(Level.SEVERE, null, ex); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/package-info.java new file mode 100644 index 000000000..cd182bfc3 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/package-info.java @@ -0,0 +1,4 @@ +/** + * ABC types. + */ +package com.jpexs.decompiler.flash.abc.types; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/package-info.java new file mode 100644 index 000000000..2ceebe321 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/package-info.java @@ -0,0 +1,4 @@ +/** + * ABC traits. + */ +package com.jpexs.decompiler.flash.abc.types.traits; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/package-info.java new file mode 100644 index 000000000..781618329 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/multinames/package-info.java @@ -0,0 +1,4 @@ +/** + * ABC Multiname usages. + */ +package com.jpexs.decompiler.flash.abc.usages.multinames; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/package-info.java new file mode 100644 index 000000000..a8be68740 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/package-info.java @@ -0,0 +1,4 @@ +/** + * Usages of ABC elements. + */ +package com.jpexs.decompiler.flash.abc.usages; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/simple/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/simple/package-info.java new file mode 100644 index 000000000..41e0021e2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/simple/package-info.java @@ -0,0 +1,4 @@ +/** + * Detection of ABC element usages and elements removing. + */ +package com.jpexs.decompiler.flash.abc.usages.simple; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java index 64ed7038e..da20f16f2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java @@ -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 propertyNamesList = Arrays.asList(propertyNames); + /** + * Property names list in lower case + */ public static final List 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 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 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> 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 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 actions, int ip) { - /* List actions=new ArrayList(); - for(GraphSourceItem s:sources){ - if(s instanceof Action){ - actions.add((Action)s); - } - }*/ if (ip >= actions.size()) { if (actions.isEmpty()) { return 0; @@ -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 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> uninitializedClassTraits, final ASMSource asm, final List 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> uninitializedClassTraits, final ASMSource asm, final List actions, final String path, GraphTextWriter writer, String charset, List 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 actionsToTree(Map> uninitializedClassTraits, boolean insideDoInitAction, boolean insideFunction, List 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> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, GraphSourceItem lineStartIns, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap 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 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 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 prepareVariables(GraphSourceItemContainer cnt, HashMap variables) { HashMap 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 actionsPartToTree(ActionGraph graph, Set switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference fi, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List 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 actionsPartToTree(ActionGraph graph, Set switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference lineStartActionRef, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List 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 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 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 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 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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java index 5571b64e4..1aa0e4567 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java @@ -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) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 602a12c6d..7d589e4de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -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> 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> uninitializedClassTraits, String path, boolean insideDoInitAction, boolean insideFunction, List code, HashMap registerNames, HashMap variables, HashMap 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> getUninitializedClassTraits() { return uninitializedClassTraits; } + + /** + * Gets the graphSource + * @return GraphSource + */ @Override public ActionGraphSource getGraphCode() { return (ActionGraphSource) code; } + /** + * Gets sub-graphs + * @return + */ @Override public LinkedHashMap getSubGraphs() { LinkedHashMap 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 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 translateViaGraph(Map> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, boolean insideFunction, HashMap registerNames, HashMap variables, HashMap functions, List 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 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 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 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 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 translate(BaseLocalData localData, int staticOperation, String path) throws InterruptedException { List 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 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 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 check(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, Set visited, GraphSource code, BaseLocalData localData, Set allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, List 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 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 processedIfs, List list, List> allSwitchParts, List> allSwitchOnFalseParts, List> allSwitchExpressions) { for (GraphTargetItem item : list) { if (item instanceof IfItem) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java index b4b0b7af7..832f0a933 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java @@ -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 registerNames; + /** + * Variables - map of variable name to variable item + */ private final HashMap variables; + /** + * Functions - map of function name to function item + */ private final HashMap 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 posCache = null; + + /** + * Gets actions + * @return Actions + */ public List 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 actions, int version, HashMap registerNames, HashMap variables, HashMap 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 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 translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { Reference fi = new Reference<>(localData.lineStartInstruction); @@ -116,8 +200,10 @@ public class ActionGraphSource extends GraphSource { return r; } - private List 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 getVariables() { return variables; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java index ff829d3a0..9e024dc3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java @@ -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 { + /** + * 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 actions, String charset) { super(actions); this.charset = charset; } + /** + * Sets actions. + * @param list Actions + */ public void setActions(List list) { clear(); addAll(list); } + /** + * Removes actions. + * @param actionsToRemove Actions to remove + */ public void removeActions(List 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 { } } + /** + * 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 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 getContainerLastActions(Action action) { return ActionListReader.getContainerLastActions(this, action); } + /** + * Gets references for action. + * @param target Target + * @return References + */ public Iterator getReferencesFor(final Action target) { return new Iterator() { private final Iterator iterator = ActionList.this.iterator(); @@ -167,6 +230,10 @@ public class ActionList extends ArrayList { }; } + /** + * Gets constant pools. + * @return Constant pools + */ public Iterable getConstantPools() { return () -> new Iterator() { private final Iterator iterator = ActionList.this.iterator(); @@ -203,6 +270,10 @@ public class ActionList extends ArrayList { }; } + /** + * Gets pushes. + * @return Pushes + */ public Iterable getPushes() { return () -> new Iterator() { private final Iterator iterator = ActionList.this.iterator(); @@ -239,6 +310,11 @@ public class ActionList extends ArrayList { }; } + /** + * 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 { 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 { } } + /** + * 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 { } } + /** + * 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 { } } + /** + * 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 { 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 { 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 { return -1; } + /** + * Gets unreachable actions. + * @return Unreachable actions + */ public List getUnreachableActions() { int[] isReachable = getUnreachableActionsMap(-1, 0); List unreachableActions = new ArrayList<>(); @@ -411,6 +527,12 @@ public class ActionList extends ArrayList { return unreachableActions; } + /** + * Gets unreachable actions. + * @param jumpIndex Jump index + * @param jumpTargetIndex Jump target index + * @return Unreachable actions + */ public List getUnreachableActions(int jumpIndex, int jumpTargetIndex) { int[] isReachable = getUnreachableActionsMap(jumpIndex, jumpTargetIndex); isReachable[jumpIndex] = 0; @@ -428,6 +550,12 @@ public class ActionList extends ArrayList { 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 { 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 { } } + /** + * 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 { } } + /** + * 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 { } } + /** + * 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 { 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; - }*/ } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 3983c6389..8e7f91bd8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -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 nextOffsets) { Map> 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 getOriginalActions(SWFInputStream sis, int startIp, int endIp) throws IOException, InterruptedException { // Map of the actions. Use TreeMap to sort the keys in ascending order Map actionMap = new TreeMap<>(); @@ -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 actionListToMap(List actions) { Map 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 actions, Map jumps) { Map 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 getContainerLastActions(ActionList actions, Action action) { GraphSourceItemContainer container = (GraphSourceItemContainer) action; List 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> 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 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 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 actions, Map jumps) { Map 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 actions, Map> 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 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> containerLastActions, Action oldTarget, Action newTarget) { for (Action a : containerLastActions.keySet()) { List 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 actions, Map jumps, Map> 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 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 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 listeners, ConstantPool cpool, SWFInputStream sis, Map actions, Map nextOffsets, long ip, long startIp, long endIp, String path, boolean indeterminate, List 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 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 listeners, ConstantPool cpool, List actions, Map actionMap, int ip, int startIp, int endIp, String path, boolean indeterminate, List visitedContainers) throws IOException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionLocalData.java index 435e4443a..969081bde 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionLocalData.java @@ -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> uninitializedClassTraits; + /** + * Register names - map of register number to register name + */ public final HashMap regNames; + /** + * Variables - map of variable name to variable target item + */ public final HashMap variables; + /** + * Functions - map of function name to function target item + */ public final HashMap 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> 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 regNames, Map> 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 switchParts, SecondPassData secondPassData, boolean insideDoInitAction, HashMap regNames, HashMap variables, HashMap functions, Map> uninitializedClassTraits) { this.allSwitchParts = switchParts; this.regNames = regNames; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptArray.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptArray.java index 170ea0e53..76d6eefe0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptArray.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptArray.java @@ -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 values = new ArrayList<>(); //TODO: implement some methods? + + /** + * Enumerates all members of this object + * @return + */ @Override public List enumerate() { List 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? diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptFunction.java index 950bce524..a3e33f4b7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptFunction.java @@ -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 paramNames; + /** + * Names of the registers - map of register index to register name + */ protected Map funcRegNames; + /** + * Gets function name + * @return Function name + */ public String getFunctionName() { return functionName; } + /** + * Gets register names + * @return Register names + */ public Map 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 paramNames, Map 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; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptObject.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptObject.java index 4c1f38ce4..a45d6b357 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptObject.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptObject.java @@ -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 properties = new HashMap<>(); + /** + * Members of the object + */ protected Map members = new HashMap<>(); + /** + * Object that this object extends + */ protected Object extendsObj; + /** + * Objects that this object implements + */ protected List 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 getImplementsObjs() { return implementsObjs; } + /** + * Sets implements objects + * @param implementsObjs Implements objects + */ public void setImplementsObjs(List 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 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("/")) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptWith.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptWith.java index c80238567..6ed170457 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptWith.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionScriptWith.java @@ -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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionSecondPassData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionSecondPassData.java index 67f9c0408..e7db45439 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionSecondPassData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionSecondPassData.java @@ -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> switchParts = new ArrayList<>(); + /** + * List of onFalse parts for each switch statement + */ List> switchOnFalseParts = new ArrayList<>(); + /** + * List of case expressions for each switch statement + */ List> switchCaseExpressions = new ArrayList<>(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionTreeOperation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionTreeOperation.java index 39e5198be..a8b1349cc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionTreeOperation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionTreeOperation.java @@ -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 tree); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ConstantPoolTooBigException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ConstantPoolTooBigException.java index f6c4dfdd9..c08ae58aa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ConstantPoolTooBigException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ConstantPoolTooBigException.java @@ -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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DepthStateObjectAdapter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DepthStateObjectAdapter.java index 1da804b16..ccae0aea6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DepthStateObjectAdapter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DepthStateObjectAdapter.java @@ -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; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DisplayObject.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DisplayObject.java index 1aea27e7a..a5a237366 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DisplayObject.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/DisplayObject.java @@ -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 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 args, Map 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); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java index 5f5a034dc..9eb1bbdfa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/LocalDataArea.java @@ -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 constantPool; + /** + * Stack + */ public Stack stack = new Stack<>(); + /** + * Functions + */ public List functions = new ArrayList<>(); + /** + * Local variables + */ public Map localVariables = new HashMap<>(); + /** + * Withs + */ public List withs = new ArrayList<>(); + /** + * Local registers - map of register index to value + */ public Map 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()); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Stage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Stage.java index 65d330a29..f58e84840 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Stage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Stage.java @@ -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 enumerate() { List 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) { } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/StoreTypeAction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/StoreTypeAction.java index 149ab7b9b..04e08c421 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/StoreTypeAction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/StoreTypeAction.java @@ -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); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownActionException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownActionException.java index 5a7c8c2b8..c541006da 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownActionException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownActionException.java @@ -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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownJumpException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownJumpException.java index bf26df995..2c7f74e24 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownJumpException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/UnknownJumpException.java @@ -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 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() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2ClassDetector.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2ClassDetector.java index bd88990a3..55842653e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2ClassDetector.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2ClassDetector.java @@ -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 objectPath, Reference newPathItem) { List 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 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 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 instanceReg, Reference classReg,Reference 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> uninitializedClassTraits, List parts, HashMap variables, int partsPos, int commandsStartPos, int commandsEndPos, List commands, List 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 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> uninitializedClassTraits, List commands, HashMap 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> uninitializedClassTraits, List commands, HashMap variables, String scriptPath) { List localCommands = new ArrayList<>(commands); boolean changed = false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2Classes.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2Classes.java index 1a1c1ea9e..01a45f2b8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2Classes.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/ActionScript2Classes.java @@ -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> classToTraits = new HashMap<>(); + /** + * Map of class name to list of parent class names + */ private static final Map> 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 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> 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> getClassInheritance() { initClasses(); return classInheritance; } + + /** + * Sample test + * @param args + */ public static void main(String[] args) { Map traits = getClassTraits("flash.filters.BevelFilter", true); if (traits != null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Method.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Method.java index c178ad91b..e8e2dae17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Method.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Method.java @@ -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"; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Trait.java index 149137de1..38c340726 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Trait.java @@ -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(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/UninitializedClassFieldsDetector.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/UninitializedClassFieldsDetector.java index 606e58710..f1e4ae863 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/UninitializedClassFieldsDetector.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/UninitializedClassFieldsDetector.java @@ -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 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 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> classTraits, Map> 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> calculateAs2UninitializedClassTraits(SWF swf) { if (swf.isAS3()) { return new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Variable.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Variable.java index b3a9d46ef..af80d72a1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Variable.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/Variable.java @@ -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; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/package-info.java new file mode 100644 index 000000000..6f32233e4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/as2/package-info.java @@ -0,0 +1,4 @@ +/** + * ActionScript 2.0 decompilation. + */ +package com.jpexs.decompiler.flash.action.as2; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/package-info.java new file mode 100644 index 000000000..8c86b0d03 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/deobfuscation/package-info.java @@ -0,0 +1,4 @@ +/** + * Deobfuscating ActionScript 1/2 code. + */ +package com.jpexs.decompiler.flash.action.deobfuscation; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/package-info.java new file mode 100644 index 000000000..e4babd843 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/fastactionlist/package-info.java @@ -0,0 +1,4 @@ +/** + * Fast action list. + */ +package com.jpexs.decompiler.flash.action.fastactionlist; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/flashlite/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/flashlite/package-info.java new file mode 100644 index 000000000..b6d7dd204 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/flashlite/package-info.java @@ -0,0 +1,4 @@ +/** + * Flash Lite Actions. + */ +package com.jpexs.decompiler.flash.action.flashlite; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CompoundableBinaryOpAs12.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CompoundableBinaryOpAs12.java index d3b0293ad..c33537e73 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CompoundableBinaryOpAs12.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/CompoundableBinaryOpAs12.java @@ -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 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/package-info.java new file mode 100644 index 000000000..808d48682 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level ActionScript 1/2 model of various clauses. + */ +package com.jpexs.decompiler.flash.action.model.clauses; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/package-info.java new file mode 100644 index 000000000..b32b827d2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/operations/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level ActionScript 1/2 model of operations. + */ +package com.jpexs.decompiler.flash.action.model.operations; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/package-info.java new file mode 100644 index 000000000..51b0bbd87 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/package-info.java @@ -0,0 +1,4 @@ +/** + * ActionScript1/2 high-level model. + */ +package com.jpexs.decompiler.flash.action.model; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/package-info.java new file mode 100644 index 000000000..ac29ca3ae --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing, decompiling and execution of ActionScript 1/2 bytecode. + */ +package com.jpexs.decompiler.flash.action; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/package-info.java new file mode 100644 index 000000000..be45291fb --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing ActionScript 1/2 scripts and P-code. + */ +package com.jpexs.decompiler.flash.action.parser; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/package-info.java new file mode 100644 index 000000000..b9fbef2e9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/pcode/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing ActionScript 1/2 PCode. + */ +package com.jpexs.decompiler.flash.action.parser.pcode; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/package-info.java new file mode 100644 index 000000000..196d4536e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing ActionScript 1/2 scripts. + */ +package com.jpexs.decompiler.flash.action.parser.script; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/package-info.java new file mode 100644 index 000000000..7cd9fd3ae --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/special/package-info.java @@ -0,0 +1,4 @@ +/** + * Special actions. + */ +package com.jpexs.decompiler.flash.action.special; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf3/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf3/package-info.java new file mode 100644 index 000000000..b7ddad9ed --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf3/package-info.java @@ -0,0 +1,4 @@ +/** + * SWF 3 actions. + */ +package com.jpexs.decompiler.flash.action.swf3; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/package-info.java new file mode 100644 index 000000000..a9d049513 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/package-info.java @@ -0,0 +1,4 @@ +/** + * SWF 4 actions. + */ +package com.jpexs.decompiler.flash.action.swf4; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/package-info.java new file mode 100644 index 000000000..b588c8043 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf5/package-info.java @@ -0,0 +1,4 @@ +/** + * SWF 5 actions. + */ +package com.jpexs.decompiler.flash.action.swf5; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/package-info.java new file mode 100644 index 000000000..e607f9186 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf6/package-info.java @@ -0,0 +1,4 @@ +/** + * SWF 6 actions. + */ +package com.jpexs.decompiler.flash.action.swf6; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/package-info.java new file mode 100644 index 000000000..c2a02ff95 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf7/package-info.java @@ -0,0 +1,4 @@ +/** + * SWF 7 actions. + */ +package com.jpexs.decompiler.flash.action.swf7; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/package-info.java new file mode 100644 index 000000000..04ccb2146 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/package-info.java @@ -0,0 +1,4 @@ +/** + * AMF3. + */ +package com.jpexs.decompiler.flash.amf.amf3; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/types/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/types/package-info.java new file mode 100644 index 000000000..a966b5e0d --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/amf/amf3/types/package-info.java @@ -0,0 +1,4 @@ +/** + * AMF3 types. + */ +package com.jpexs.decompiler.flash.amf.amf3.types; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/package-info.java new file mode 100644 index 000000000..9640d3e1d --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/cache/package-info.java @@ -0,0 +1,4 @@ +/** + * Caching AS data. + */ +package com.jpexs.decompiler.flash.cache; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/package-info.java new file mode 100644 index 000000000..6f9f330c9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/package-info.java @@ -0,0 +1,4 @@ +/** + * Configuration of FFDec. + */ +package com.jpexs.decompiler.flash.configuration; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/package-info.java new file mode 100644 index 000000000..1b2b94f95 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/docs/package-info.java @@ -0,0 +1,4 @@ +/** + * Documentation for instructions and actions. + */ +package com.jpexs.decompiler.flash.docs; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/package-info.java new file mode 100644 index 000000000..4d3ebd1b9 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/dumpview/package-info.java @@ -0,0 +1,4 @@ +/** + * Dump view data. + */ +package com.jpexs.decompiler.flash.dumpview; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/package-info.java new file mode 100644 index 000000000..b8edc0997 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/ecma/package-info.java @@ -0,0 +1,4 @@ +/** + * ECMAScript types. + */ +package com.jpexs.decompiler.flash.ecma; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/amf/amf3/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/amf/amf3/package-info.java new file mode 100644 index 000000000..87c456a5b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/amf/amf3/package-info.java @@ -0,0 +1,4 @@ +/** + * AMF3 export. + */ +package com.jpexs.decompiler.flash.exporters.amf.amf3; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/package-info.java new file mode 100644 index 000000000..6580569d7 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/commonshape/package-info.java @@ -0,0 +1,4 @@ +/** + * Common classes for exporting shapes. + */ +package com.jpexs.decompiler.flash.exporters.commonshape; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/package-info.java new file mode 100644 index 000000000..58efb1430 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/modes/package-info.java @@ -0,0 +1,4 @@ +/** + * Export modes. + */ +package com.jpexs.decompiler.flash.exporters.modes; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/morphshape/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/morphshape/package-info.java new file mode 100644 index 000000000..1692089a6 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/morphshape/package-info.java @@ -0,0 +1,4 @@ +/** + * Morph shapes exporter. + */ +package com.jpexs.decompiler.flash.exporters.morphshape; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/package-info.java new file mode 100644 index 000000000..1f18e39c6 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/package-info.java @@ -0,0 +1,4 @@ +/** + * Exporting Flash elements to various formats. + */ +package com.jpexs.decompiler.flash.exporters; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/graphviz/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/graphviz/package-info.java new file mode 100644 index 000000000..f4f833026 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/graphviz/package-info.java @@ -0,0 +1,4 @@ +/** + * Graphviz graphs exporter for scripts. + */ +package com.jpexs.decompiler.flash.exporters.script.graphviz; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/package-info.java new file mode 100644 index 000000000..cd5017c79 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/package-info.java @@ -0,0 +1,4 @@ +/** + * Exporting scripts. + */ +package com.jpexs.decompiler.flash.exporters.script; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/package-info.java new file mode 100644 index 000000000..984ceea55 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/settings/package-info.java @@ -0,0 +1,4 @@ +/** + * Export settings. + */ +package com.jpexs.decompiler.flash.exporters.settings; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/package-info.java new file mode 100644 index 000000000..6e7e83b05 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/shape/package-info.java @@ -0,0 +1,4 @@ +/** + * Exporting shapes. + */ +package com.jpexs.decompiler.flash.exporters.shape; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/package-info.java new file mode 100644 index 000000000..61b66d685 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/package-info.java @@ -0,0 +1,4 @@ +/** + * Exporting whole SWF files. + */ +package com.jpexs.decompiler.flash.exporters.swf; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/package-info.java new file mode 100644 index 000000000..89318c067 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flexsdk/package-info.java @@ -0,0 +1,4 @@ +/** + * Flex SDK support. + */ +package com.jpexs.decompiler.flash.flexsdk; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flv/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flv/package-info.java new file mode 100644 index 000000000..bc22f73f6 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/flv/package-info.java @@ -0,0 +1,4 @@ +/** + * FLV files. + */ +package com.jpexs.decompiler.flash.flv; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/gfx/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/gfx/package-info.java new file mode 100644 index 000000000..6020177d5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/gfx/package-info.java @@ -0,0 +1,4 @@ +/** + * GFX files. + */ +package com.jpexs.decompiler.flash.gfx; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/harman/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/harman/package-info.java new file mode 100644 index 000000000..e8e94055f --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/harman/package-info.java @@ -0,0 +1,4 @@ +/** + * Harman. + */ +package com.jpexs.decompiler.flash.harman; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerAdapter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerAdapter.java index 520f3241d..d2a236446 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerAdapter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerAdapter.java @@ -22,51 +22,84 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.action.ActionList; import com.jpexs.decompiler.graph.GraphTargetItem; + import java.util.List; /** - * + * Adapter for SWFDecompilerListener * @author JPEXS */ public class SWFDecompilerAdapter implements SWFDecompilerListener { + /** + * Called when a file is proxied + * @param data file data + * @return proxied file data + */ @Override public byte[] proxyFileCatched(byte[] data) { return null; } + /** + * Called when a SWF file is parsed + * @param swf SWF object + */ @Override public void swfParsed(SWF swf) { } + /** + * 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 { } + /** + * Called when an action tree is created + * @param tree Action tree + * @param swf SWF object + * @throws InterruptedException + */ @Override public void actionTreeCreated(List tree, SWF swf) throws InterruptedException { } + /** + * Called when an ABC is parsed + * @param abc ABC object + * @param swf SWF object + */ @Override public void abcParsed(ABC abc, SWF swf) { } + /** + * Called when a method body is parsed + * @param abc ABC object + * @param body Method body + * @param swf SWF object + */ @Override public void methodBodyParsed(ABC abc, MethodBody body, SWF swf) { } /** * This method is only called when deobfuscation is enabled and new - * deobfuscation mode is selected + * deobfuscation mode is selected. * - * @param path - * @param classIndex - * @param isStatic - * @param scriptIndex - * @param abc - * @param trait - * @param methodInfo - * @param body + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC object + * @param trait Trait object + * @param methodInfo Method info + * @param body Method body * @throws InterruptedException */ @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerListener.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerListener.java index 36a61d99e..5b3001a3d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerListener.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/SWFDecompilerListener.java @@ -22,38 +22,71 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.action.ActionList; import com.jpexs.decompiler.graph.GraphTargetItem; + import java.util.List; /** - * + * Listener for SWF decompiler events. * @author JPEXS */ public interface SWFDecompilerListener { + /** + * Called when a file is proxied + * @param data file data + * @return proxied file data + */ byte[] proxyFileCatched(byte[] data); + /** + * Called when a SWF file is parsed + * @param swf SWF object + */ void swfParsed(SWF swf); + /** + * Called when an action list is parsed + * @param actions Action list + * @param swf SWF object + * @throws InterruptedException + */ void actionListParsed(ActionList actions, SWF swf) throws InterruptedException; + /** + * Called when an action tree is created + * @param tree Action tree + * @param swf SWF object + * @throws InterruptedException + */ void actionTreeCreated(List tree, SWF swf) throws InterruptedException; + /** + * Called when an ABC is parsed + * @param abc ABC object + * @param swf SWF object + */ void abcParsed(ABC abc, SWF swf); + /** + * Called when a method body is parsed + * @param abc ABC object + * @param body Method body + * @param swf SWF object + */ void methodBodyParsed(ABC abc, MethodBody body, SWF swf); /** - * this method is only called when deobfuscation is enabled and new - * deobfuscation mode is selected + * This method is only called when deobfuscation is enabled and new + * deobfuscation mode is selected. * - * @param path - * @param classIndex - * @param isStatic - * @param scriptIndex - * @param abc - * @param trait - * @param methodInfo - * @param body + * @param path Path + * @param classIndex Class index + * @param isStatic Is static + * @param scriptIndex Script index + * @param abc ABC object + * @param trait Trait object + * @param methodInfo Method info + * @param body Method body * @throws InterruptedException */ void avm2CodeRemoveTraps(String path, int classIndex, boolean isStatic, int scriptIndex, ABC abc, Trait trait, int methodInfo, MethodBody body) throws InterruptedException; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/collections/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/collections/package-info.java new file mode 100644 index 000000000..f94d93f6a --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/collections/package-info.java @@ -0,0 +1,4 @@ +/** + * Collection helpers. + */ +package com.jpexs.decompiler.flash.helpers.collections; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/package-info.java new file mode 100644 index 000000000..b24eab0d0 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/package-info.java @@ -0,0 +1,4 @@ +/** + * Code position highlighting. + */ +package com.jpexs.decompiler.flash.helpers.hilight; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/package-info.java new file mode 100644 index 000000000..8decd077e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/package-info.java @@ -0,0 +1,4 @@ +/** + * Helpers for flash. + */ +package com.jpexs.decompiler.flash.helpers; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/package-info.java new file mode 100644 index 000000000..b0d9e0cb5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/annotations/package-info.java @@ -0,0 +1,4 @@ +/** + * Iggy format annotations. + */ +package com.jpexs.decompiler.flash.iggy.annotations; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/package-info.java new file mode 100644 index 000000000..9b0240a15 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/conversion/package-info.java @@ -0,0 +1,4 @@ +/** + * Converting Iggy format. + */ +package com.jpexs.decompiler.flash.iggy.conversion; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/package-info.java new file mode 100644 index 000000000..a4b0375b1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/package-info.java @@ -0,0 +1,4 @@ +/** + * IGGY files. + */ +package com.jpexs.decompiler.flash.iggy; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/package-info.java new file mode 100644 index 000000000..21a311210 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/iggy/streams/package-info.java @@ -0,0 +1,4 @@ +/** + * Iggy streams. + */ +package com.jpexs.decompiler.flash.iggy.streams; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/amf/amf3/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/amf/amf3/package-info.java new file mode 100644 index 000000000..04e3799e1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/amf/amf3/package-info.java @@ -0,0 +1,4 @@ +/** + * AMF3 importer. + */ +package com.jpexs.decompiler.flash.importers.amf.amf3; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/morphshape/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/morphshape/package-info.java new file mode 100644 index 000000000..d0792e598 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/morphshape/package-info.java @@ -0,0 +1,4 @@ +/** + * Morph shape importer. + */ +package com.jpexs.decompiler.flash.importers.morphshape; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/package-info.java new file mode 100644 index 000000000..3e2eb1e2e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/package-info.java @@ -0,0 +1,4 @@ +/** + * Importers. + */ +package com.jpexs.decompiler.flash.importers; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/css/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/css/package-info.java new file mode 100644 index 000000000..96e356a75 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/css/package-info.java @@ -0,0 +1,4 @@ +/** + * CSS parser and styles. + */ +package com.jpexs.decompiler.flash.importers.svg.css; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/package-info.java new file mode 100644 index 000000000..b6f3cda6c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/svg/package-info.java @@ -0,0 +1,4 @@ +/** + * SVG importer. + */ +package com.jpexs.decompiler.flash.importers.svg; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/docs/pcode/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/docs/pcode/package-info.java new file mode 100644 index 000000000..fb1aaf249 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/docs/pcode/package-info.java @@ -0,0 +1,4 @@ +/** + * Localization of instruction documentation. + */ +package com.jpexs.decompiler.flash.locales.docs.pcode; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/package-info.java new file mode 100644 index 000000000..0ced431d2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/package-info.java @@ -0,0 +1,4 @@ +/** + * Localization of the FFDec library. + */ +package com.jpexs.decompiler.flash.locales; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/math/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/math/package-info.java new file mode 100644 index 000000000..bff2ae6d5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/math/package-info.java @@ -0,0 +1,4 @@ +/** + * Mathematical operations. + */ +package com.jpexs.decompiler.flash.math; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/package-info.java new file mode 100644 index 000000000..0631fb4f1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/package-info.java @@ -0,0 +1,4 @@ +/** + * Main package for Flash. + */ +package com.jpexs.decompiler.flash; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/packers/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/packers/package-info.java new file mode 100644 index 000000000..cc11ddda5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/packers/package-info.java @@ -0,0 +1,4 @@ +/** + * Packing and unpacking SWF files and BinaryData objects. + */ +package com.jpexs.decompiler.flash.packers; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/package-info.java new file mode 100644 index 000000000..ee1ef4963 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/package-info.java @@ -0,0 +1,4 @@ +/** + * Searching in SWF files. + */ +package com.jpexs.decompiler.flash.search; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/package-info.java new file mode 100644 index 000000000..67a103700 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/package-info.java @@ -0,0 +1,4 @@ +/** + * Base classes for Flash tags. + */ +package com.jpexs.decompiler.flash.tags.base; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/dynamictext/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/dynamictext/package-info.java new file mode 100644 index 000000000..31bbfb032 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/dynamictext/package-info.java @@ -0,0 +1,4 @@ +/** + * Dynamic text tags. + */ +package com.jpexs.decompiler.flash.tags.dynamictext; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/enums/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/enums/package-info.java new file mode 100644 index 000000000..bcc67d919 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/enums/package-info.java @@ -0,0 +1,4 @@ +/** + * Enums for tags. + */ +package com.jpexs.decompiler.flash.tags.enums; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/font/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/font/package-info.java new file mode 100644 index 000000000..918b99ee2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/font/package-info.java @@ -0,0 +1,4 @@ +/** + * Font tags handling. + */ +package com.jpexs.decompiler.flash.tags.font; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/enums/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/enums/package-info.java new file mode 100644 index 000000000..c6ad2bd24 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/enums/package-info.java @@ -0,0 +1,4 @@ +/** + * GFX tag enums. + */ +package com.jpexs.decompiler.flash.tags.gfx.enums; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/package-info.java new file mode 100644 index 000000000..d5c12a7a2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/gfx/package-info.java @@ -0,0 +1,4 @@ +/** + * GFX tags. + */ +package com.jpexs.decompiler.flash.tags.gfx; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/package-info.java new file mode 100644 index 000000000..c96abb020 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/package-info.java @@ -0,0 +1,4 @@ +/** + * Flash tags. + */ +package com.jpexs.decompiler.flash.tags; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/text/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/text/package-info.java new file mode 100644 index 000000000..86c8cb246 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/text/package-info.java @@ -0,0 +1,4 @@ +/** + * Text tags. + */ +package com.jpexs.decompiler.flash.tags.text; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java index 920294bf6..809253731 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Frame.java @@ -29,11 +29,8 @@ import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.decompiler.flash.types.SOUNDINFO; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.TreeMap; + +import java.util.*; /** * Single frame of a timeline. @@ -88,7 +85,7 @@ public class Frame implements TreeItem, Exportable { /** * Inner nested tags in this frame. - * @see ShowFrameTag.isNestedTagType + * See ShowFrameTag.isNestedTagType */ public List innerTags = new ArrayList<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/package-info.java new file mode 100644 index 000000000..60ce98db7 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/package-info.java @@ -0,0 +1,4 @@ +/** + * Flash timeline. + */ +package com.jpexs.decompiler.flash.timeline; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/package-info.java new file mode 100644 index 000000000..d5fa1ed1e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/treeitems/package-info.java @@ -0,0 +1,4 @@ +/** + * Tree items. + */ +package com.jpexs.decompiler.flash.treeitems; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/package-info.java new file mode 100644 index 000000000..1508cf26e --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/package-info.java @@ -0,0 +1,4 @@ +/** + * Annotations for Flash types. + */ +package com.jpexs.decompiler.flash.types.annotations; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/parser/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/parser/package-info.java new file mode 100644 index 000000000..78672a72c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/annotations/parser/package-info.java @@ -0,0 +1,4 @@ +/** + * Parsing annotations. + */ +package com.jpexs.decompiler.flash.types.annotations.parser; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/package-info.java new file mode 100644 index 000000000..7a3885136 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/filters/package-info.java @@ -0,0 +1,4 @@ +/** + * Flash filters. + */ +package com.jpexs.decompiler.flash.types.filters; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/package-info.java new file mode 100644 index 000000000..ead36f8da --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/gfx/package-info.java @@ -0,0 +1,4 @@ +/** + * GFX types. + */ +package com.jpexs.decompiler.flash.types.gfx; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/package-info.java new file mode 100644 index 000000000..b2b461b6c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/package-info.java @@ -0,0 +1,4 @@ +/** + * Flash types. + */ +package com.jpexs.decompiler.flash.types; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/shaperecords/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/shaperecords/package-info.java new file mode 100644 index 000000000..cb251bddb --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/shaperecords/package-info.java @@ -0,0 +1,4 @@ +/** + * Shape record types. + */ +package com.jpexs.decompiler.flash.types.shaperecords; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/package-info.java new file mode 100644 index 000000000..0ab8e9ad0 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/sound/package-info.java @@ -0,0 +1,4 @@ +/** + * Sound types. + */ +package com.jpexs.decompiler.flash.types.sound; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/package-info.java new file mode 100644 index 000000000..f96aac047 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/package-info.java @@ -0,0 +1,4 @@ +/** + * XFL (FLA) generator. + */ +package com.jpexs.decompiler.flash.xfl; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/shapefixer/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/shapefixer/package-info.java new file mode 100644 index 000000000..8421baf2f --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/shapefixer/package-info.java @@ -0,0 +1,4 @@ +/** + * Fixing shapes in XFL files. + */ +package com.jpexs.decompiler.flash.xfl.shapefixer; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/AbstractGraphTargetVisitor.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/AbstractGraphTargetVisitor.java index 3369ed437..cc51be997 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/AbstractGraphTargetVisitor.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/AbstractGraphTargetVisitor.java @@ -19,14 +19,22 @@ package com.jpexs.decompiler.graph; import java.util.Collection; /** - * + * Abstract graph target visitor. * @author JPEXS */ public abstract class AbstractGraphTargetVisitor implements GraphTargetVisitorInterface { + /** + * Visits a graph target item. + * @param item Graph target item + */ @Override public abstract void visit(GraphTargetItem item); + /** + * Visits all graph target items. + * @param items Collection of graph target items + */ @Override public final void visitAll(Collection items) { for (GraphTargetItem item : items) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Block.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Block.java index 832be1e20..0ee5e5d41 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Block.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Block.java @@ -17,15 +17,25 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.graph.model.ContinueItem; + import java.util.List; /** - * + * Block interface. + * For example, a block can be a loop, if statement, or a function. * @author JPEXS */ public interface Block { + /** + * Gets all sub continues. + * @return List of continues + */ public List getContinues(); + /** + * Gets all sub blocks. + * @return List of blocks + */ public List> getSubs(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/CompilationException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/CompilationException.java index a5fd75dc2..39af4872b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/CompilationException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/CompilationException.java @@ -17,15 +17,26 @@ package com.jpexs.decompiler.graph; /** - * + * Compilation exception. * @author JPEXS */ public class CompilationException extends Exception { + /** + * Line number. + */ public int line; + /** + * Error message. + */ public String text; + /** + * Constructs a new compilation exception. + * @param message Error message + * @param line Line number + */ public CompilationException(String message, int line) { super("Compilation error on line " + line + ": " + message); this.line = line; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java index 251c03139..28e223549 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.helpers.Helper; + import java.io.File; import java.io.Serializable; import java.util.ArrayList; @@ -26,11 +27,14 @@ import java.util.List; import java.util.Objects; /** - * + * Dotted chain class. + * Represents a chain of names separated by dots. * @author JPEXS */ public class DottedChain implements Serializable, Comparable { + //Basic dotted chains + public static final DottedChain EMPTY = new DottedChain(true); public static final DottedChain UNBOUNDED = new DottedChain(new String[]{"*"}); @@ -65,14 +69,29 @@ public class DottedChain implements Serializable, Comparable { public static final DottedChain ALL = new DottedChain(new String[]{"*"}); + /** + * Parts of the chain. + */ private List parts; + /** + * Is this chain null? + */ private boolean isNull = false; + /** + * Get the namespace suffix of the part at the given index. + * @param index Index + * @return Namespace suffix + */ public String getNamespaceSuffix(int index) { return parts.get(index).namespaceSuffix; } + /** + * Gets the last namespace suffix. + * @return Last namespace suffix + */ public String getLastNamespaceSuffix() { if (parts.isEmpty()) { return ""; @@ -80,6 +99,11 @@ public class DottedChain implements Serializable, Comparable { return parts.get(parts.size() - 1).namespaceSuffix; } + /** + * Parses a dotted chain from a string without suffix. + * @param name Name + * @return Dotted chain + */ public static final DottedChain parseNoSuffix(String name) { if (name == null) { return DottedChain.EMPTY; @@ -96,6 +120,11 @@ public class DottedChain implements Serializable, Comparable { } } + /** + * Parses a dotted chain from a string with suffix. + * @param name Name + * @return Dotted chain + */ public static final DottedChain parseWithSuffix(String name) { if (name == null) { return DottedChain.EMPTY; @@ -118,25 +147,46 @@ public class DottedChain implements Serializable, Comparable { } } + /** + * Constructs a new dotted chain. + * @param isNull Whether the chain is null + */ private DottedChain(boolean isNull) { this.isNull = isNull; this.parts = new ArrayList<>(); } + /** + * Constructs a new dotted chain. + * @param src Source chain + */ public DottedChain(DottedChain src) { this.parts = new ArrayList<>(src.parts); this.isNull = src.isNull; } + /** + * Constructs a new dotted chain. + * @param parts Parts + */ public DottedChain(String[] parts) { this(Arrays.asList(parts)); } + /** + * Constructs a new dotted chain. + * @param parts Parts + * @param isNull Whether the chain is null + */ private DottedChain(List parts, boolean isNull) { this.parts = parts; this.isNull = isNull; } + /** + * Constructs a new dotted chain. + * @param parts Parts + */ public DottedChain(List parts) { List newParts = new ArrayList<>(); for (String part : parts) { @@ -145,10 +195,21 @@ public class DottedChain implements Serializable, Comparable { this.parts = newParts; } + /** + * Constructs a new dotted chain. + * @param parts Parts + * @param namespaceSuffixes Namespace suffixes + */ public DottedChain(String[] parts, String[] namespaceSuffixes) { this(new boolean[parts.length], parts, namespaceSuffixes); } + /** + * Constructs a new dotted chain. + * @param attributes Attributes + * @param parts Parts + * @param namespaceSuffixes Namespace suffixes + */ public DottedChain(boolean[] attributes, String[] parts, String[] namespaceSuffixes) { List newParts = new ArrayList<>(); for (int i = 0; i < attributes.length; i++) { @@ -158,18 +219,35 @@ public class DottedChain implements Serializable, Comparable { } + /** + * Checks whether this chain is top-level. + * @return Whether this chain is top-level + */ public boolean isTopLevel() { return !isNull && parts.isEmpty(); } + /** + * Checks whether this chain is empty. + * @return Whether this chain is empty + */ public boolean isEmpty() { return isNull; } + /** + * Gets the number of parts in this chain. + * @return Number of parts + */ public int size() { return parts.size(); } + /** + * Gets the part at the given index. + * @param index Index + * @return Part + */ public String get(int index) { if (index >= parts.size()) { throw new ArrayIndexOutOfBoundsException(); @@ -178,6 +256,11 @@ public class DottedChain implements Serializable, Comparable { return parts.get(index).name; } + /** + * Checks whether the part at the given index is an attribute. + * @param index Index + * @return Whether the part at the given index is an attribute + */ public boolean isAttribute(int index) { if (index >= parts.size()) { throw new ArrayIndexOutOfBoundsException(); @@ -185,6 +268,11 @@ public class DottedChain implements Serializable, Comparable { return parts.get(index).attribute; } + /** + * Gets the sub-chain of specific length. + * @param count Length + * @return + */ public DottedChain subChain(int count) { if (count > parts.size()) { throw new ArrayIndexOutOfBoundsException(); @@ -193,6 +281,10 @@ public class DottedChain implements Serializable, Comparable { return new DottedChain(new ArrayList<>(parts.subList(0, count)), isNull); } + /** + * Gets last part. + * @return Last part + */ public String getLast() { if (isNull) { return null; @@ -204,6 +296,10 @@ public class DottedChain implements Serializable, Comparable { } } + /** + * Checks whether the last part is an attribute. + * @return Whether the last part is an attribute + */ public boolean isLastAttribute() { if (isNull) { return false; @@ -215,6 +311,10 @@ public class DottedChain implements Serializable, Comparable { } } + /** + * Gets the chain without the last part. + * @return Chain without the last part + */ public DottedChain getWithoutLast() { if (isNull) { return null; @@ -226,6 +326,11 @@ public class DottedChain implements Serializable, Comparable { return subChain(parts.size() - 1); } + /** + * Adds a part to the chain with a suffix. + * @param name Name + * @return New chain + */ public DottedChain addWithSuffix(String name) { String addedNameNoSuffix = name; String addedNamespaceSuffix = ""; @@ -236,10 +341,23 @@ public class DottedChain implements Serializable, Comparable { return add(addedNameNoSuffix, addedNamespaceSuffix); } + /** + * Adds a part to the chain. + * @param name Name + * @param namespaceSuffix Namespace suffix + * @return New chain + */ public DottedChain add(String name, String namespaceSuffix) { return add(false, name, namespaceSuffix); } + /** + * Adds a part to the chain. + * @param attribute Whether the part is an attribute + * @param name Name + * @param namespaceSuffix Namespace suffix + * @return New chain + */ public DottedChain add(boolean attribute, String name, String namespaceSuffix) { if (name == null) { return new DottedChain(this); @@ -249,10 +367,23 @@ public class DottedChain implements Serializable, Comparable { return new DottedChain(newParts, false); } + /** + * Adds prefix to the chain. + * @param name Name + * @param namespaceSuffix Namespace suffix + * @return New chain + */ public DottedChain preAdd(String name, String namespaceSuffix) { return preAdd(false, name, namespaceSuffix); } + /** + * Adds prefix to the chain. + * @param attribute Whether the part is an attribute + * @param name Name + * @param namespaceSuffix Namespace suffix + * @return New chain + */ public DottedChain preAdd(boolean attribute, String name, String namespaceSuffix) { if (name == null) { return new DottedChain(this); @@ -262,11 +393,22 @@ public class DottedChain implements Serializable, Comparable { return new DottedChain(newParts, false); } + /** + * To string. + * @return String + */ @Override public String toString() { return toRawString(); } + /** + * To string. + * @param as3 Whether to print as AS3 + * @param raw Whether to print raw (without deobfuscation) + * @param withSuffix Whether to print with suffix + * @return String + */ protected String toString(boolean as3, boolean raw, boolean withSuffix) { if (isNull) { return ""; @@ -294,6 +436,10 @@ public class DottedChain implements Serializable, Comparable { return ret.toString(); } + /** + * To file path. + * @return File path + */ public String toFilePath() { if (isNull) { return ""; @@ -313,6 +459,10 @@ public class DottedChain implements Serializable, Comparable { return ret.toString(); } + /** + * To list. + * @return List + */ public List toList() { List ret = new ArrayList<>(); for (PathPart p : parts) { @@ -321,14 +471,27 @@ public class DottedChain implements Serializable, Comparable { return ret; } + /** + * To printable string. + * @param as3 Whether to print as AS3 + * @return Printable string + */ public String toPrintableString(boolean as3) { return toString(as3, false, true); } + /** + * To raw string. (without deobfuscation) + * @return Raw string + */ public String toRawString() { //Is SUFFIX correctly handled? return toString(false/*ignored*/, true, true); } + /** + * Hash code. + * @return Hash code + */ @Override public int hashCode() { int hash = 7; @@ -337,6 +500,11 @@ public class DottedChain implements Serializable, Comparable { return hash; } + /** + * Equals. + * @param obj Object + * @return Whether this object is equal to the given object + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -355,23 +523,52 @@ public class DottedChain implements Serializable, Comparable { return Objects.equals(this.parts, other.parts); } + /** + * Compare to. + * @param o the object to be compared. + * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. + */ @Override public int compareTo(DottedChain o) { return toRawString().compareTo(o.toRawString()); } + /** + * Path part class. + */ private static class PathPart implements Serializable { + /** + * Name. + */ public String name; + + /** + * Is this part an attribute? + */ public boolean attribute; + + /** + * Namespace suffix. + */ public String namespaceSuffix; + /** + * Constructs a new path part. + * @param name Name + * @param attribute Whether this part is an attribute + * @param namespaceSuffix Namespace suffix + */ public PathPart(String name, boolean attribute, String namespaceSuffix) { this.name = name; this.attribute = attribute; this.namespaceSuffix = namespaceSuffix; } + /** + * Hash code. + * @return + */ @Override public int hashCode() { int hash = 5; @@ -381,6 +578,11 @@ public class DottedChain implements Serializable, Comparable { return hash; } + /** + * Equals. + * @param obj Object + * @return Whether this object is equal to the given object + */ @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/EqualsTypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/EqualsTypeItem.java index d6fdf7bb8..404177e40 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/EqualsTypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/EqualsTypeItem.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.graph.model.BinaryOp; /** - * + * Equals type item. * @author JPEXS */ public interface EqualsTypeItem extends BinaryOp { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 47fcb4e03..cfef54dfa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -22,95 +22,102 @@ import com.jpexs.decompiler.flash.action.Action; import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction; import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.graph.model.AndItem; -import com.jpexs.decompiler.graph.model.BinaryOpItem; -import com.jpexs.decompiler.graph.model.BranchStackResistant; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.DefaultItem; -import com.jpexs.decompiler.graph.model.DoWhileItem; -import com.jpexs.decompiler.graph.model.DuplicateItem; -import com.jpexs.decompiler.graph.model.ExitItem; -import com.jpexs.decompiler.graph.model.FalseItem; -import com.jpexs.decompiler.graph.model.ForItem; -import com.jpexs.decompiler.graph.model.GotoItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.IntegerValueItem; -import com.jpexs.decompiler.graph.model.IntegerValueTypeItem; -import com.jpexs.decompiler.graph.model.LabelItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.decompiler.graph.model.LogicalOpItem; -import com.jpexs.decompiler.graph.model.LoopItem; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.OrItem; -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.TernarOpItem; -import com.jpexs.decompiler.graph.model.TrueItem; -import com.jpexs.decompiler.graph.model.UniversalLoopItem; -import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.decompiler.graph.model.*; import com.jpexs.decompiler.graph.precontinues.GraphPrecontinueDetector; import com.jpexs.helpers.Reference; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.Stack; -import java.util.TreeSet; + +import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; /** + * Graph class. + * This is the main class where decompilation process is done. + * It translates GraphSourceItems to GraphTargetItems. * + * Subclasses of Graph are used for different types of decompilation. * @author JPEXS */ public class Graph { + /** + * Graph entry points + */ public List heads; + /** + * Graph source code + */ protected GraphSource code; + /** + * Exceptions in the graph + */ private final List exceptions; + /** + * Constant not used anymore + * @deprecated not used. + */ public static final int SOP_USE_STATIC = 0; - public static final int SOP_SKIP_STATIC = 1; - - public static final int SOP_REMOVE_STATIC = 2; - + /** + * Debug flag to print all parts + */ private boolean debugPrintAllParts = false; + /** + * Debug flag to print loop list + */ private boolean debugPrintLoopList = false; + /** + * Debug flag to print getLoops + */ private boolean debugGetLoops = false; + /** + * Debug flag to print decompilation progress (printGraph method) + */ private boolean debugPrintGraph = false; + /** + * Debug flag to not process Ifs + */ protected boolean debugDoNotProcess = false; + /** + * Logger + */ private static final Logger logger = Logger.getLogger(Graph.class.getName()); + /** + * Gets the graphSource + * @return GraphSource + */ public GraphSource getGraphCode() { return code; } + /** + * Gets sub-graphs + * @return + */ public LinkedHashMap getSubGraphs() { return new LinkedHashMap<>(); } + /** + * Constructs a new Graph. + * @param code Graph source + * @param exceptions Exceptions in the graph + */ public Graph(GraphSource code, List exceptions) { this.code = code; this.exceptions = exceptions; - } + /** + * Initializes the graph. + * @param localData Local data + * @throws InterruptedException + */ public void init(BaseLocalData localData) throws InterruptedException { if (heads != null) { return; @@ -178,16 +185,35 @@ public class Graph { } + /** + * Edge for calculating closed time. + */ private class LevelMapEdge { + /** + * Source part + */ public GraphPart from; + + /** + * Target part + */ public GraphPart to; + /** + * Constructs a new LevelMapEdge + * @param from Source part + * @param to Target part + */ public LevelMapEdge(GraphPart from, GraphPart to) { this.from = from; this.to = to; } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 7; @@ -196,6 +222,11 @@ public class Graph { return hash; } + /** + * Equals + * @param obj Object + * @return True if equals + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -217,10 +248,19 @@ public class Graph { } } + /** + * Gets graph exceptions. + * @return List of exceptions + */ public List getExceptions() { return exceptions; } + /** + * Populates all parts available from the part. + * @param part Source part + * @param allParts Result + */ protected static void populateParts(GraphPart part, Set allParts) { if (allParts.contains(part)) { return; @@ -231,10 +271,21 @@ public class Graph { } } + /** + * Deep copies GraphPart. + * @param part Source part + * @return Deep copy of the part + */ public GraphPart deepCopy(GraphPart part) { return deepCopy(part, new HashMap<>()); } + /** + * Deep copies GraphPart. + * @param part Source part + * @param copies Already copied parts + * @return Deep copy of the part + */ private GraphPart deepCopy(GraphPart part, Map copies) { GraphPart copy = copies.get(part); if (copy != null) { @@ -256,6 +307,11 @@ public class Graph { return copy; } + /** + * Resets the graph. + * @param part Part to reset + * @param visited Visited parts + */ public void resetGraph(GraphPart part, Set visited) { if (visited.contains(part)) { return; @@ -273,11 +329,28 @@ public class Graph { } } + /** + * Gets reachable parts from the part. + * @param localData Local data + * @param part Source part + * @param ret Result + * @param loops Loops + * @param throwStates Throw states + */ protected void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet ret, List loops, List throwStates) { // use LinkedHashSet to preserve order getReachableParts(localData, part, ret, loops, throwStates, true); } + /** + * Gets reachable parts from the part. + * @param localData Local data + * @param part Source part + * @param ret Result + * @param loops Loops + * @param throwStates Throw states + * @param first First call + */ private void getReachableParts(BaseLocalData localData, GraphPart part, LinkedHashSet ret, List loops, List throwStates, boolean first) { // todo: honfika: why call with first = true parameter always? Stack stack = new Stack<>(); @@ -378,11 +451,31 @@ public class Graph { } } + /** + * Gets common successor of the next parts of the part. + * @param localData Local data + * @param part Part + * @param loops Loops + * @param throwStates Throw states + * @return Common successor + * @throws InterruptedException + */ public GraphPart getNextCommonPart(BaseLocalData localData, GraphPart part, List loops, List throwStates) throws InterruptedException { return getCommonPart(localData, part, getNextParts(localData, part), loops, throwStates); } - //TODO: Make this faster! + /** + * Gets common successor of the parts. + * + * TODO: Make this faster! + * @param localData Local data + * @param prev Previous part + * @param parts Parts + * @param loops Loops + * @param throwStates Throw states + * @return Common successor + * @throws InterruptedException + */ public GraphPart getCommonPart(BaseLocalData localData, GraphPart prev, List parts, List loops, List throwStates) throws InterruptedException { if (parts.isEmpty()) { return null; @@ -442,6 +535,19 @@ public class Graph { return null; } + /** + * Gets common successor of most of the nextparts of the part. + * + * This is used mostly in switch detection. + * + * @param localData Local data + * @param parts Parts + * @param loops Loops + * @param throwStates Throw states + * @param stopPart Stop part + * @return Most common successor + * @throws InterruptedException + */ public GraphPart getMostCommonPart(BaseLocalData localData, List parts, List loops, List throwStates, List stopPart) throws InterruptedException { if (parts.isEmpty()) { return null; @@ -626,16 +732,35 @@ public class Graph { return null; } + /** + * Common part + */ private class PartCommon implements Comparable { + /** + * Part + */ public GraphPart part; + /** + * Level - how many parts are common + */ public int level; + /** + * Constructs a new PartCommon + * @param part Part + * @param level Level + */ public PartCommon(GraphPart part, int level) { this.part = part; this.level = level; } + /** + * Compares to another PartCommon + * @param o Other PartCommon + * @return Comparison result + */ @Override public int compareTo(PartCommon o) { int ret = o.level - level; @@ -649,11 +774,19 @@ public class Graph { return ret; } + /** + * To string + * @return String representation + */ @Override public String toString() { return "" + part.toString() + " (level=" + level + ")"; } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 5; @@ -662,6 +795,11 @@ public class Graph { return hash; } + /** + * Equals + * @param obj Object + * @return True if equals + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -682,50 +820,33 @@ public class Graph { } - public GraphPart getNextNoJump(GraphPart part, BaseLocalData localData) { - while (code.get(part.start).isJump()) { - part = part.getSubParts().get(0).nextParts.get(0); - } - /*localData = prepareBranchLocalData(localData); - TranslateStack st = new TranslateStack(); - List output=new ArrayList<>(); - GraphPart startPart = part; - for (int i = part.start; i <= part.end; i++) { - GraphSourceItem src = code.get(i); - if (src.isJump()) { - part = getNextParts(localData, part).get(0); - if(st.isEmpty()){ - startPart = part; - } - i = part.start - 1; - continue; - } - try{ - src.translate(localData, st, output, SOP_USE_STATIC, ""); - }catch(Exception ex){ - return startPart; - } - if(!output.isEmpty()){ - return startPart; - } - }*/ - return part; - } - - public static List translateViaGraph(BaseLocalData localData, String path, GraphSource code, List exceptions, int staticOperation) throws InterruptedException { - Graph g = new Graph(code, exceptions); - g.init(localData); - return g.translate(localData, staticOperation, path); - } - + /** + * Method called after populating all parts. + * @param allParts All parts + */ protected void afterPopupateAllParts(Set allParts) { } + /** + * Gets throw states. + * Override this method to get throw states. + * @param localData Local data + * @param allParts All parts + * @return List of ThrowStates + */ protected List getThrowStates(BaseLocalData localData, Set allParts) { return new ArrayList<>(); } + /** + * Translates the graph - decompiles. + * @param localData Local data + * @param staticOperation Unused + * @param path Path + * @return List of GraphTargetItems + * @throws InterruptedException + */ public List translate(BaseLocalData localData, int staticOperation, String path) throws InterruptedException { Set allParts = new HashSet<>(); @@ -826,15 +947,31 @@ public class Graph { return ret; } + /** + * Prepares second pass data. + * Can return null when no second pass will happen. + * Override this method to prepare second pass data. + * @param list List of GraphTargetItems + * @return Second pass data or null + */ protected SecondPassData prepareSecondPass(List list) { return null; } + /** + * Process various items. Override this method to process items. + * @param list List of GraphTargetItems + * @param lastLoopId Last loop id + */ protected void processOther(List list, long lastLoopId) { } - protected void processSwitches(List list) { + /** + * Process switches. + * @param list + */ + protected final void processSwitches(List list) { processSwitches(list, -1); } @@ -876,7 +1013,13 @@ public class Graph { This will fix precontinue handler which detects multiple continues */ - protected void processSwitches(List list, long lastLoopId) { + + /** + * Process switches. + * @param list List of GraphTargetItems + * @param lastLoopId Last loop id + */ + protected final void processSwitches(List list, long lastLoopId) { loopi: for (int i = 0; i < list.size(); i++) { GraphTargetItem item = list.get(i); @@ -993,22 +1136,58 @@ public class Graph { } } + /** + * Gets data for final process. + * Override this method to provide data for final process. + * @param localData + * @param loops + * @param throwStates + * @return + */ protected FinalProcessLocalData getFinalData(BaseLocalData localData, List loops, List throwStates) { return new FinalProcessLocalData(loops); } + /** + * Method called before getting loops. + * Override this method to provide custom behavior. + * @param localData Local data + * @param path Path + * @param allParts All parts + * @param throwStates Throw states + * @throws InterruptedException + */ protected void beforeGetLoops(BaseLocalData localData, String path, Set allParts, List throwStates) throws InterruptedException { } + /** + * Method called after getting loops. + * Override this method to provide custom behavior. + * @param localData Local data + * @param path Path + * @param allParts All parts + * @throws InterruptedException + */ protected void afterGetLoops(BaseLocalData localData, String path, Set allParts) throws InterruptedException { } + /** + * Checks whether part is empty. + * Override this method to provide custom behavior. + * @param part Part + * @return True if part is empty + */ protected boolean isPartEmpty(GraphPart part) { return false; } + /** + * Converts path to string + * @param list Collection of objects + * @return String representation of the path + */ private String pathToString(Collection list) { List strs = new ArrayList<>(); for (Object p : list) { @@ -1017,7 +1196,12 @@ public class Graph { return "[" + String.join(", ", strs) + "]"; } - private List getUnicatePartList(List list) { + /** + * Gets unique part list. + * @param list List of parts + * @return Unique list of parts + */ + private List getUniquePartList(List list) { List result = new ArrayList<>(); for (GraphPart p : list) { if (!result.contains(p)) { @@ -1027,7 +1211,13 @@ public class Graph { return result; } - private List getUnicateRefsNoThrow(GraphPart part, Set throwEdges) { + /** + * Gets list of unique references of part without going through throw edges. + * @param part Part + * @param throwEdges Throw edges + * @return List of unique references + */ + private List getUniqueRefsNoThrow(GraphPart part, Set throwEdges) { List result = new ArrayList<>(); for (GraphPart r : part.refs) { GraphPartEdge edge = new GraphPartEdge(r, part); @@ -1036,24 +1226,16 @@ public class Graph { } } - return getUnicatePartList(result); + return getUniquePartList(result); } - private List getUsableRefs(GraphPart g, List loops, List throwStates) { - List ret = getUnicatePartList(g.refs); - for (Loop el : loops) { - for (GraphPart be : el.backEdges) { - if (ret.contains(be)) { - ret.remove(be); - } - } - } - return ret; - } - - - /**/ - //if (getNextParts(localData, ref)) + /** + * Gets of loop backedges + * @param localData Local data + * @param loops Loops + * @param throwStates Throw states + * @throws InterruptedException + */ private void getBackEdges(BaseLocalData localData, List loops, List throwStates) throws InterruptedException { clearLoops(loops); for (Loop el : loops) { @@ -1069,9 +1251,24 @@ public class Graph { clearLoops(loops); } + /** + * Final process stack. + * Override this method to provide custom behavior. + * @param stack Translate stack + * @param output Output + * @param path Path + */ public void finalProcessStack(TranslateStack stack, List output, String path) { } + /** + * Final process all. + * @param list List of GraphTargetItems + * @param level Level + * @param localData Local data + * @param path Path + * @throws InterruptedException + */ private void finalProcessAll(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { if (debugDoNotProcess) { return; @@ -1088,6 +1285,13 @@ public class Graph { finalProcessAfter(list, level, localData, path); } + /** + * Processes sub blocks. + * TODO: make this clearer what it does + * @param b Block + * @param replacement If not null, then if last item of block is PushItem, then it will be replaced with this item + * @return If all blocks ends with PushItem + */ private boolean processSubBlk(Block b, GraphTargetItem replacement) { boolean allSubPush = true; boolean atleastOne = false; @@ -1127,6 +1331,14 @@ public class Graph { return allSubPush && atleastOne; } + /** + * Final process after. + * Override this method to provide custom behavior. + * @param list List of GraphTargetItems + * @param level Level + * @param localData Local data + * @param path Path + */ protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { if (list.size() >= 2) { if (list.get(list.size() - 1) instanceof ExitItem) { @@ -1143,6 +1355,15 @@ public class Graph { } } + /** + * Final process. + * Override this method to provide custom behavior. + * @param list List of GraphTargetItems + * @param level Level + * @param localData Local data + * @param path Path + * @throws InterruptedException + */ protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { //For detection based on debug line information @@ -1221,6 +1442,10 @@ public class Graph { } } + /** + * Expands gotos. + * @param list + */ private void expandGotos(List list) { if (!list.isEmpty() && (list.get(list.size() - 1) instanceof GotoItem)) { GotoItem gi = (GotoItem) list.get(list.size() - 1); @@ -1243,6 +1468,13 @@ public class Graph { } } + /** + * Processes if gotos. + * @param alreadyProcessedBlocks Already processed blocks + * @param allGotos All gotos + * @param list List of GraphTargetItems + * @param rootList Root list + */ private void processIfGotos2(List> alreadyProcessedBlocks, List allGotos, List list, List rootList) { for (int i = 0; i < list.size(); i++) { GraphTargetItem item = list.get(i); @@ -1279,12 +1511,17 @@ public class Graph { } /** - * if (xxx) { y ; goto a } else { z ; goto a } + * Processes if gotos. * - * => + * if (xxx) { y ; goto a } else { z ; goto a } * - * if (xxx) { y } else { z } goto a + * => * + * if (xxx) { y } else { z } goto a + * + * @param allGotos All gotos + * @param list List of GraphTargetItems + * @param rootList Root list */ private void processIfGotos(List allGotos, List list, List rootList) { for (int i = 0; i < list.size(); i++) { @@ -1353,7 +1590,11 @@ public class Graph { } } - protected void processIfs(List list) { + /** + * Processes ifs. + * @param list List of GraphTargetItems + */ + protected final void processIfs(List list) { if (debugDoNotProcess) { return; } @@ -1536,48 +1777,11 @@ public class Graph { //Same continues in onTrue and onFalse gets continue on parent level } - protected List getLoopsContinuesPreAndBreaks(List loops) { - List ret = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - ret.add(l.loopContinue); - } - if (l.loopPreContinue != null) { - ret.add(l.loopPreContinue); - } - if (l.loopBreak != null) { - ret.add(l.loopBreak); - } - } - return ret; - } - - protected List getLoopsContinuesAndPre(List loops) { - List ret = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - ret.add(l.loopContinue); - } - if (l.loopPreContinue != null) { - ret.add(l.loopPreContinue); - } - } - return ret; - } - - protected List getLoopsContinues(List loops) { - List ret = new ArrayList<>(); - for (Loop l : loops) { - if (l.loopContinue != null) { - ret.add(l.loopContinue); - } - /*if (l.loopPreContinue != null) { - ret.add(l.loopPreContinue); - }*/ - } - return ret; - } - + /** + * Checks continue at the end of block and remove it when its from nearest loop. + * @param commands List of GraphTargetItems + * @param loop Loop + */ private void checkContinueAtTheEnd(List commands, Loop loop) { if (!commands.isEmpty()) { int i = commands.size() - 1; @@ -1603,7 +1807,12 @@ public class Graph { } } - protected boolean isEmpty(List output) { + /** + * Checks whether list of items is empty. + * @param output List of GraphTargetItems + * @return True if list of items is empty + */ + protected final boolean isEmpty(List output) { if (output.isEmpty()) { return true; } @@ -1615,26 +1824,93 @@ public class Graph { return false; } + /** + * Check before decompiling next section. + * Override this method to provide custom behavior. + * @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 + */ protected List check(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, Set visited, GraphSource code, BaseLocalData localData, Set allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, List output, Loop currentLoop, int staticOperation, String path) throws InterruptedException { return null; } + /** + * Check of Part passing output. Allows you to switch part for another. + * If not overriden, then it calls checkPart. + * + * @param output List of GraphTargetItems + * @param stack Translate stack + * @param localData Local data + * @param prev Previous part + * @param part Part + * @param allParts All parts + * @return Return same part to continue processing or return another part to continue to other part. Or return null to stop. + */ protected GraphPart checkPartWithOutput(List output, TranslateStack stack, BaseLocalData localData, GraphPart prev, GraphPart part, Set allParts) { return checkPart(stack, localData, prev, part, allParts); } + /** + * Check of part. Allows you to switch part for another. + * @param stack Translate stack + * @param localData Local data + * @param prev Previous part + * @param part Part + * @param allParts All parts + * @return Return same part to continue processing or return another part to continue to other part. Or return null to stop. + */ protected GraphPart checkPart(TranslateStack stack, BaseLocalData localData, GraphPart prev, GraphPart part, Set allParts) { return part; } + /** + * Translates part and get its stack. + * @param localData Local data + * @param part Part + * @param stack Translate stack + * @param staticOperation Unused + * @return Top of the stack + * @throws InterruptedException + * @throws GraphPartChangeException + */ //@SuppressWarnings("unchecked") - protected GraphTargetItem translatePartGetStack(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation) throws InterruptedException, GraphPartChangeException { + protected final GraphTargetItem translatePartGetStack(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation) throws InterruptedException, GraphPartChangeException { stack = (TranslateStack) stack.clone(); translatePart(localData, part, stack, staticOperation, null); return stack.pop(); } - protected List translatePart(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { + /** + * Translates part. + * @param localData Local data + * @param part Part + * @param stack Translate stack + * @param staticOperation Unused + * @param path Path + * @return List of GraphTargetItems + * @throws InterruptedException + * @throws GraphPartChangeException + */ + protected final List translatePart(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { List sub = part.getSubParts(); List ret = new ArrayList<>(); int end; @@ -1654,48 +1930,16 @@ public class Graph { return ret; } - private void markBranchEnd(List items) { - if (!items.isEmpty()) { - if (items.get(items.size() - 1) instanceof BreakItem) { - return; - } - if (items.get(items.size() - 1) instanceof ContinueItem) { - return; - } - if (items.get(items.size() - 1) instanceof ExitItem) { - return; - } - } - items.add(new MarkItem("finish")); - } - - private static GraphTargetItem getLastNoEnd(List list) { - if (list.isEmpty()) { - return null; - } - if (list.get(list.size() - 1) instanceof ScriptEndItem) { - if (list.size() >= 2) { - return list.get(list.size() - 2); - } - return list.get(list.size() - 1); - } - return list.get(list.size() - 1); - } - - private static void removeLastNoEnd(List list) { - if (list.isEmpty()) { - return; - } - if (list.get(list.size() - 1) instanceof ScriptEndItem) { - if (list.size() >= 2) { - list.remove(list.size() - 2); - } - return; - } - list.remove(list.size() - 1); - } - - protected GraphTargetItem checkLoop(List output, GraphPart part, List stopPart, List loops, List throwStates) { + /** + * Checks for Continue and Break items at current part. + * @param output List of GraphTargetItems + * @param part Part + * @param stopPart Stop part + * @param loops Loops + * @param throwStates Throw states + * @return Continue or Break item or null + */ + protected final GraphTargetItem checkLoop(List output, GraphPart part, List stopPart, List loops, List throwStates) { if (stopPart.contains(part)) { return null; } @@ -1721,22 +1965,50 @@ public class Graph { return null; } + /** + * Check loop. + * Can be overriden to provide custom behavior. + * @param output List of GraphTargetItems + * @param loopItem Loop item + * @param localData Local data + * @param loops Loops + * @param throwStates Throw states + * @param stack Translate stack + * @return Return loopItem to replace current loop. Return null to continue. + */ protected GraphTargetItem checkLoop(List output, LoopItem loopItem, BaseLocalData localData, List loops, List throwStates, TranslateStack stack) { return loopItem; } + /** + * Sets loop phase to 0 on loops. + * @param loops List of loops + */ private void clearLoops(List loops) { for (Loop l : loops) { l.phase = 0; } } + /** + * Sets state to 0 on throw states. + * @param throwStates List of throw states + */ private void clearThrowStates(List throwStates) { for (ThrowState ts : throwStates) { ts.state = 0; } } + /** + * Loop detection. + * @param localData Local data + * @param part Part + * @param loops List of loops + * @param throwStates List of throw states + * @param stopPart Stop part + * @throws InterruptedException + */ private void getLoops(BaseLocalData localData, GraphPart part, List loops, List throwStates, List stopPart) throws InterruptedException { clearLoops(loops); clearThrowStates(throwStates); @@ -1745,14 +2017,34 @@ public class Graph { clearThrowStates(throwStates); } + /** + * Checks whether a part can be a break candidate. + * Can be overriden to provide custom behavior. + * @param localData Local data + * @param part Part + * @param throwStates List of throw states + * @return True if part can be a break candidate + */ protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List throwStates) { return true; } + /** + * Check part in get loops walk. + * Can be overriden to provide custom behavior. + * @param part Graph part + */ protected void checkGetLoopsPart(GraphPart part) { } + /** + * Finds parts outside try statement + * @param ts Throw state + * @param part Graph part + * @param ret List of Graph parts + * @param visited Set of Graph parts + */ private void findPartsOutsideTry(ThrowState ts, GraphPart part, List ret, Set visited) { if (visited.contains(part)) { return; @@ -1767,6 +2059,18 @@ public class Graph { } } + /** + * Walks parts to detect loops. + * @param localData Local data + * @param part Graph part + * @param loops List of loops + * @param throwStates List of throw states + * @param stopPart Stop part + * @param first First + * @param visited Set of Graph parts + * @param level Level + * @throws InterruptedException + */ private void getLoopsWalk(BaseLocalData localData, GraphPart part, List loops, List throwStates, List stopPart, boolean first, List visited, int level) throws InterruptedException { loopwalk: @@ -2163,6 +2467,12 @@ public class Graph { } } + /** + * Gets all Continue commands in sub blocks. + * @param commands List of GraphTargetItems + * @param result Result + * @param loopId Loop id + */ private void getContinuesCommands(List commands, List> result, long loopId) { for (GraphTargetItem ti : commands) { if (ti instanceof ContinueItem) { @@ -2180,14 +2490,52 @@ public class Graph { } } + /** + * Get next parts of a part. + * Can be overriden to provide custom behavior. + * @param localData Local data + * @param part Part + * @return List of GraphParts + */ protected List getNextParts(BaseLocalData localData, GraphPart part) { return part.nextParts; } + /** + * Check before processing with output. + * @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 currentLoop Current loop + * @param staticOperation Unused + * @param path Path + * @param recursionLevel Recursion level + * @return True to stop processing. False to continue. + * @throws InterruptedException + */ protected boolean checkPartOutput(List currentRet, List foundGotos, Map> partCodes, Map partCodePos, Set visited, GraphSource code, BaseLocalData localData, Set allParts, TranslateStack stack, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, Loop currentLoop, int staticOperation, String path, int recursionLevel) throws InterruptedException { return false; } + /** + * Checks whether part is loop continue, break or precontinue. + * @param part Graph part + * @param loops List of loops + * @param throwStates List of throw states + * @return True if part is loop continue, break or precontinue + */ protected boolean partIsLoopContBrePre(GraphPart part, List loops, List throwStates) { for (Loop el : loops) { if (el.phase == 1) { @@ -2205,15 +2553,38 @@ public class Graph { return false; } + /** + * Checks whether part can be continue of a loop. + * Defaults to true. + * Override this method to provide custom behavior. + * @param localData Local data + * @param part Graph part + * @param loops List of loops + * @param throwStates List of throw states + * @return True if part can be continue of a loop + */ protected boolean canHandleLoop(BaseLocalData localData, GraphPart part, List loops, List throwStates) { return true; } + /** + * Checks whether part can be checked over visited parts list. + * Defaults to true. + * Can be overriden to provide custom behavior. + * @param localData Local data + * @param part Graph part + * @return True if part can be checked over visited parts list + */ protected boolean canHandleVisited(BaseLocalData localData, GraphPart part) { return true; } - protected boolean canBeCommaised(List list) { + /** + * Checks whether the list of items can be converted to comma separated list. + * @param list List of GraphTargetItems + * @return True if the list of items can be converted to comma separated list + */ + protected final boolean canBeCommaised(List list) { for (GraphTargetItem item : list) { if (item instanceof Block) { return false; @@ -2222,11 +2593,53 @@ public class Graph { return true; } - protected List printGraph(List foundGotos, Map> partCodes, Map partCodePos, Set visited, BaseLocalData localData, TranslateStack stack, Set allParts, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, int staticOperation, String path) throws InterruptedException { + /** + * Walks graph parts and converts them to target items. + * @param foundGotos Found gotos + * @param partCodes Part codes + * @param partCodePos Part code position + * @param visited Visited + * @param localData Local data + * @param stack Translate stack + * @param allParts All parts + * @param parent Parent part + * @param part Part + * @param stopPart Stop part + * @param stopPartKind Stop part kind + * @param loops Loops + * @param throwStates Throw states + * @param staticOperation Unused + * @param path Path + * @return List of GraphTargetItems + * @throws InterruptedException + */ + protected final List printGraph(List foundGotos, Map> partCodes, Map partCodePos, Set visited, BaseLocalData localData, TranslateStack stack, Set allParts, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, int staticOperation, String path) throws InterruptedException { return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, stopPartKind, loops, throwStates, null, staticOperation, path, 0); } - protected List printGraph(List foundGotos, Map> partCodes, Map partCodePos, Set visited, BaseLocalData localData, TranslateStack stack, Set allParts, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, List ret, int staticOperation, String path, int recursionLevel) throws InterruptedException { + /** + * Walks graph parts and converts them to target items. + * @param foundGotos Found gotos + * @param partCodes Part codes + * @param partCodePos Part code position + * @param visited Visited + * @param localData Local data + * @param stack Translate stack + * @param allParts All parts + * @param parent Parent part + * @param part Part + * @param stopPart Stop part + * @param stopPartKind Stop part kind + * @param loops Loops + * @param throwStates Throw states + * @param ret Return + * @param staticOperation Unused + * @param path Path + * @param recursionLevel Recursion level + * @return List of GraphTargetItems + * @throws InterruptedException + */ + protected final List printGraph(List foundGotos, Map> partCodes, Map partCodePos, Set visited, BaseLocalData localData, TranslateStack stack, Set allParts, GraphPart parent, GraphPart part, List stopPart, List stopPartKind, List loops, List throwStates, List ret, int staticOperation, String path, int recursionLevel) throws InterruptedException { loopPrintGraph: while (true) { if (Thread.currentThread().isInterrupted()) { @@ -2250,19 +2663,6 @@ public class Graph { if (debugPrintGraph) { System.err.println("PART " + part + " nextsize:" + getNextParts(localData, part).size()); } - - /*while (((part != null) && (part.getHeight() == 1)) && (code.size() > part.start) && (code.get(part.start).isJump())) { //Parts with only jump in it gets ignored - - if (part == stopPart) { - return ret; - } - GraphTargetItem lop = checkLoop(getNextParts(localData, part).get(0), stopPart, loops); - if (lop == null) { - part = getNextParts(localData, part).get(0); - } else { - break; - } - }*/ if (part == null) { return ret; } @@ -2271,10 +2671,6 @@ public class Graph { return ret; } - if (part.ignored) { - return ret; - } - //List loopContinues = getLoopsContinues(loops); boolean isLoop = false; Loop currentLoop = null; @@ -2747,11 +3143,7 @@ public class Graph { GraphPart nextOnePart = null; if (getNextParts(localData, part).size() == 2 && !partIsSwitch(part)) { GraphTargetItem expr = stack.pop(); - /*if (expr instanceof LogicalOpItem) { - expr = ((LogicalOpItem) expr).invert(); - } else { - expr = new NotItem(null, expr); - }*/ + if (nextOnePart == null) { List nps; @@ -2759,7 +3151,6 @@ public class Graph { boolean isEmpty = nps.get(0) == nps.get(1); GraphPart next = getCommonPart(localData, part, nps, loops, throwStates); - //System.err.println("on part " + part + ", next: " + next); TranslateStack trueStack = (TranslateStack) stack.clone(); TranslateStack falseStack = (TranslateStack) stack.clone(); @@ -3134,17 +3525,42 @@ public class Graph { return ret; } + /** + * Checks switch statement. + * Override this method to add custom switch handling. + * @param localData Local data + * @param switchItem Switch item + * @param otherSides Other sides + * @param output Output + */ protected void checkSwitch(BaseLocalData localData, SwitchItem switchItem, Collection otherSides, List output) { } + /** + * Checks all parts of the graph after they are populated. + * Override this method to add custom checks. + * @param allBlocks All blocks + */ protected void checkGraph(List allBlocks) { } + /** + * Checks IP and allows to modify it. + * Override this method to add custom IP checks. + * @param ip Current IP + * @return New IP + */ protected int checkIp(int ip) { return ip; } + /** + * Searches for part by IP. + * @param ip IP + * @param allParts All parts + * @return + */ public GraphPart searchPart(int ip, Collection allParts) { if (ip < 0) { return null; @@ -3157,6 +3573,14 @@ public class Graph { return null; } + /** + * Makes connected set of GraphParts from GraphSource. + * @param code Graph source + * @param allBlocks All blocks to populate parts into. + * @param exceptions Exceptions + * @return List of entry points + * @throws InterruptedException + */ public List makeGraph(GraphSource code, List allBlocks, List exceptions) throws InterruptedException { List alternateEntries = new ArrayList<>(); for (GraphException ex : exceptions) { @@ -3177,6 +3601,19 @@ public class Graph { return ret; } + /** + * Makes connected set of GraphParts from GraphSource. + * @param parent Parent part + * @param path Path + * @param code Graph source + * @param startip Start IP + * @param lastIp Last IP + * @param allBlocks All blocks + * @param refs References + * @param visited Visited + * @return Entry point + * @throws InterruptedException + */ private GraphPart makeGraph(GraphPart parent, GraphPath path, GraphSource code, int startip, int lastIp, List allBlocks, HashMap> refs, boolean[] visited) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -3296,22 +3733,12 @@ public class Graph { } /** - * String used to indent line when converting to string - */ - public static final String INDENTOPEN = "INDENTOPEN"; - - /** - * String used to unindent line when converting to string - */ - public static final String INDENTCLOSE = "INDENTCLOSE"; - - /** - * Converts list of TreeItems to string + * Converts list of TreeItems to string. * * @param tree List of TreeItem - * @param writer - * @param localData - * @return String + * @param writer Writer + * @param localData Local data + * @return Writer * @throws java.lang.InterruptedException */ public static GraphTextWriter graphToString(List tree, GraphTextWriter writer, LocalData localData) throws InterruptedException { @@ -3326,11 +3753,22 @@ public class Graph { return writer; } + /** + * Prepares local data for branch. + * Override this method to add custom branch handling. + * @param localData Local data + * @return Local data for a branch + */ public BaseLocalData prepareBranchLocalData(BaseLocalData localData) { return localData; } - protected List getPartItems(GraphPart part) { + /** + * Get source items for a part + * @param part Part + * @return List of source items + */ + protected final List getPartItems(GraphPart part) { List ret = new ArrayList<>(); do { for (int i = 0; i < part.getHeight(); i++) { @@ -3353,6 +3791,11 @@ public class Graph { return ret; } + /** + * Moves all pushitems from commands to stack. + * @param commands Commands + * @param stack Stack + */ protected static void makeAllStack(List commands, TranslateStack stack) { int pcnt = 0; for (int i = commands.size() - 1; i >= 0; i--) { @@ -3368,6 +3811,12 @@ public class 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 commands, TranslateStack stack) { int clen = commands.size(); boolean isExit = false; @@ -3410,6 +3859,31 @@ public class Graph { } } + /** + * Handles switch statement. + * @param switchedObject Switched object + * @param switchStartItem Switch start item + * @param foundGotos Found gotos + * @param partCodes Part codes + * @param partCodePos Part code positions + * @param visited Visited + * @param allParts All parts + * @param stack Stack + * @param stopPart Stop part + * @param stopPartKind Stop part kind + * @param loops Loops + * @param throwStates Throw states + * @param localData Local data + * @param staticOperation Unused + * @param path Path + * @param caseValuesMap Case values map + * @param defaultPart Default part + * @param caseBodyParts Case body parts + * @param nextRef Next reference + * @param tiRef Target item reference + * @return Switch item + * @throws InterruptedException + */ protected SwitchItem handleSwitch(GraphTargetItem switchedObject, GraphSourceItem switchStartItem, List foundGotos, Map> partCodes, Map partCodePos, Set visited, Set allParts, TranslateStack stack, List stopPart, List stopPartKind, List loops, List throwStates, BaseLocalData localData, int staticOperation, String path, List caseValuesMap, GraphPart defaultPart, List caseBodyParts, Reference nextRef, Reference tiRef) throws InterruptedException { @@ -3656,6 +4130,13 @@ public class Graph { } + /** + * Checks if part is a switch. + * Defaults to false. + * Override this method to add custom switch handling. + * @param part Part + * @return True if part is a switch + */ protected boolean partIsSwitch(GraphPart part) { return false; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphException.java index f19675998..3420ac63b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphException.java @@ -17,15 +17,31 @@ package com.jpexs.decompiler.graph; /** - * + * Exception thrown in the graph. * @author JPEXS */ public class GraphException { + /** + * Start IP of thrown block + */ public int start; + /** + * End IP of thrown block + */ public int end; + + /** + * Target IP to go when exception is thrown + */ public int target; + /** + * Constructs a new exception + * @param start Start IP + * @param end End IP + * @param target Target IP + */ public GraphException(int start, int end, int target) { this.start = start; this.end = end; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphExceptionParts.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphExceptionParts.java deleted file mode 100644 index 3543a01ee..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphExceptionParts.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010-2024 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -/** - * - * @author JPEXS - */ -public class GraphExceptionParts { - - public GraphPart start; - public GraphPart end; - public GraphPart target; - - public GraphExceptionParts(GraphPart start, GraphPart end, GraphPart target) { - this.start = start; - this.end = end; - this.target = target; - } -} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPart.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPart.java index 53f93013d..ec3525614 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPart.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPart.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.BaseLocalData; + import java.io.Serializable; import java.util.ArrayList; import java.util.HashSet; @@ -24,90 +25,80 @@ import java.util.List; import java.util.Stack; /** - * + * Represents a part of a graph. + * Block of instructions which are executed in sequence. + * No jumps or branches are allowed inside a GraphPart. * @author JPEXS */ public class GraphPart implements Serializable { - public static final int TYPE_NONE = 0; - - public static final int TYPE_LOOP_HEADER = 1; - - public static final int TYPE_PRELOOP = 3; - - public static final int TYPE_REENTRY = 2; - - public boolean traversed = false; - - public int DFSP_pos = 0; - - public GraphPart iloop_header; - - public int type = TYPE_NONE; - - public boolean irreducible = false; - + /** + * Start IP + */ public int start = 0; + /** + * End IP + */ public int end = 0; - public int instanceCount = 0; - + /** + * Next parts + */ public List nextParts = new ArrayList<>(); - public int posX = -1; - - public int posY = -1; - + /** + * Path + */ public GraphPath path = new GraphPath(); + /** + * Previous parts + */ public List refs = new ArrayList<>(); - public boolean ignored = false; - + /** + * Level in the graph + */ public int level; + /** + * Discovered time in DFS + */ public int discoveredTime; + /** + * Finished time in DFS + * Calculated in setTime. + */ public int finishedTime; + /** + * Closed time. + * The node is closed when all its input edges are already visited. + * Calculated in Graph.calculateClosedTime. + */ public int closedTime; + /** + * Order in DFS. + * Calculated in setTime. + */ public int order; + /** + * Number of parts following this part. + * Calculated in setNumblocks. + */ public int numBlocks = Integer.MAX_VALUE; - //public List throwParts = new ArrayList<>(); - public enum StopPartType { - - NONE, AND_OR, COMMONPART - } - - //public StopPartType stopPartType = StopPartType.NONE; - //public TranslateStack andOrStack; // Stores stack when AND_OR stopPart has been reached - /*public class CommonPartStack { // Stores stack when COMMONPART stopPart has been reached - - boolean isTrueStack; - - TranslateStack trueStack; - - TranslateStack falseStack; - }/ - - //public ArrayList commonPartStacks; - - /* public void setAndOrStack(TranslateStack stack) { - andOrStack = stack; - } - - public void setCommonPartStack(TranslateStack stack) { - CommonPartStack currentStack = commonPartStacks.get(commonPartStacks.size() - 1); - if (currentStack.isTrueStack) { - currentStack.trueStack = stack; - } else { - currentStack.falseStack = stack; - } - }*/ + /** + * Sets the time of this part in DFS. + * @param time Time + * @param ordered Ordered parts + * @param visited Visited parts + * @return Time + */ public int setTime(int time, List ordered, List visited) { if (visited.contains(this)) { return time; @@ -126,6 +117,10 @@ public class GraphPart implements Serializable { return time; } + /** + * Sets the number of blocks following this part. + * @param numBlocks Number of blocks + */ public void setNumblocks(int numBlocks) { this.numBlocks = numBlocks; numBlocks++; @@ -136,72 +131,20 @@ public class GraphPart implements Serializable { } } - private boolean leadsToRecursive(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet visited, List loops, List throwStates, boolean useThrow) throws InterruptedException { - if (Thread.currentThread().isInterrupted()) { - throw new InterruptedException(); - } - - GraphPart tpart = gr.checkPart(null, localData, prev, this, null); - if (tpart == null) { - return false; - } - if (tpart != this) { - return tpart.leadsTo(localData, gr, code, null, part, visited, loops, throwStates, useThrow); - } - Loop currentLoop = null; - for (Loop l : loops) { - /*if(l.phase==0){ - if(l.loopContinue==this){ - l.leadsToMark = 1; - next = l.loopBreak; - currentLoop = l; - continue; - } - }*/ - if (l.phase == 1) { - if (l.loopContinue == this) { - return false; - } - if (l.loopPreContinue == this) { - return false; - } - if (l.loopBreak == this) { - //return false; //? - } - } - } - if (visited.contains(this)) { - return false; - } - /*if (loops.contains(this)) { - return false; - }*/ - visited.add(this); - if (end < code.size() && code.get(end).isBranch() && (code.get(end).ignoredLoops())) { - return false; - } - for (GraphPart p : nextParts) { - if (p == part) { - return true; - } else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) { - return true; - } - } - for (ThrowState ts : throwStates) { - if (ts.state != 1) { - if (ts.throwingParts.contains(this)) { - GraphPart p = ts.targetPart; - if (p == part) { - return true; - } else if (p.leadsTo(localData, gr, code, this, part, visited, loops, throwStates, useThrow)) { - return true; - } - } - } - } - return false; - } - + /** + * Checks if this part leads to another part. + * @param localData Local data + * @param gr Graph + * @param code Code + * @param prev Previous part + * @param part Part to check + * @param visited Visited parts + * @param loops Loops + * @param throwStates Throw states + * @param useThrow Use throw + * @return True if this part leads to the other part + * @throws InterruptedException + */ private boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet visited, List loops, List throwStates, boolean useThrow) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -271,6 +214,18 @@ public class GraphPart implements Serializable { return false; } + /** + * Checks if this part leads to another part. + * @param localData Local data + * @param gr Graph + * @param code Code + * @param part Part to check + * @param loops Loops + * @param throwStates Throw states + * @param useThrow Use throw + * @return True if this part leads to the other part + * @throws InterruptedException + */ public boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart part, List loops, List throwStates, boolean useThrow) throws InterruptedException { for (Loop l : loops) { l.leadsToMark = 0; @@ -278,71 +233,20 @@ public class GraphPart implements Serializable { return leadsTo(localData, gr, code, null /*???*/, part, new HashSet<>(), loops, throwStates, useThrow); } + /** + * Constructs a new GraphPart. + * @param start Start IP + * @param end End IP + */ public GraphPart(int start, int end) { this.start = start; this.end = end; } - private GraphPart getNextPartPath(GraphPart original, GraphPath path, List visited) { - if (visited.contains(this) && (this == original)) { - return null; - } - if (visited.contains(this) && (this != original)) { - return null; - } - visited.add(this); - for (GraphPart p : nextParts) { - if (p == original) { - continue; - } - if (p.path.equals(path)) { - return p; - } else if (p.path.length() >= path.length()) { - GraphPart gp = p.getNextPartPath(original, path, visited); - if (gp != null) { - return gp; - } - } - } - return null; - } - - public GraphPart getNextPartPath(List ignored) { - List visited = new ArrayList<>(); - visited.addAll(ignored); - if (visited.contains(this)) { - visited.remove(this); - } - return getNextPartPath(this, path, visited); - } - - public GraphPart getNextSuperPartPath(List ignored) { - List visited = new ArrayList<>(); - visited.addAll(ignored); - return getNextSuperPartPath(this, path, visited); - } - - private GraphPart getNextSuperPartPath(GraphPart original, GraphPath path, List visited) { - if (visited.contains(this)) { - return null; - } - visited.add(this); - for (GraphPart p : nextParts) { - if (p == original) { - continue; - } - if (p.path.length() < path.length()) { - return p; - } else { - GraphPart gp = p.getNextSuperPartPath(original, path, visited); - if (gp != null) { - return gp; - } - } - } - return null; - } - + /** + * To string. + * @return String representation + */ @Override public String toString() { if (end < start) { @@ -352,47 +256,48 @@ public class GraphPart implements Serializable { int printEnd = end + 1; return "" + (printStart < 0 ? "(" : "") + printStart + (printStart < 0 ? ")" : "") - + "-" + (printEnd < 0 ? "(" : "") + printEnd + (printEnd < 0 ? ")" : "") + (instanceCount > 1 ? "(" + instanceCount + " links)" : ""); + + "-" + (printEnd < 0 ? "(" : "") + printEnd + (printEnd < 0 ? ")" : ""); } + /** + * Checks if this part contains an IP. + * @param ip IP + * @return True if this part contains the IP + */ public boolean containsIP(int ip) { return (ip >= start) && (ip <= end); } + /** + * Gets the height of this part - number of instructions in this part. + * @return Height + */ public int getHeight() { return end - start + 1; } + /** + * Gets IP at offset from start. + * @param offset Offset + * @return IP + */ public int getPosAt(int offset) { return start + offset; } - private boolean containsPart(GraphPart part, GraphPart what, List used) { - if (used.contains(part)) { - return false; - } - used.add(part); - for (GraphPart subpart : part.nextParts) { - if (subpart == what) { - return true; - } - if (containsPart(subpart, what, used)) { - return true; - } - } - return false; - } - - public boolean containsPart(GraphPart what) { - return containsPart(this, what, new ArrayList<>()); - } - + /** + * Gets sub parts. Currently only self is allowed. + */ public List getSubParts() { List ret = new ArrayList<>(); ret.add(this); return ret; } + /** + * Hash code. + * @return Hash code + */ @Override public int hashCode() { int hash = 3; @@ -400,6 +305,11 @@ public class GraphPart implements Serializable { return hash; } + /** + * Equals. + * @param obj Object + * @return True if equals + */ @Override public boolean equals(Object obj) { if (obj == null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartChangeException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartChangeException.java index c2d051ac9..8b2b1d83b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartChangeException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartChangeException.java @@ -19,23 +19,43 @@ package com.jpexs.decompiler.graph; import java.util.List; /** - * + * Exception when part of the graph is changed. * @author JPEXS */ public class GraphPartChangeException extends Exception { + /** + * IP + */ private final int ip; + + /** + * Output + */ private final List output; + /** + * Constructs a new GraphPartChangeException + * @param output Output + * @param ip IP + */ public GraphPartChangeException(List output, int ip) { this.output = output; this.ip = ip; } + /** + * Gets the IP + * @return IP + */ public int getIp() { return ip; } + /** + * Gets the output + * @return Output + */ public List getOutput() { return output; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartDecision.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartDecision.java deleted file mode 100644 index 3e67c3b76..000000000 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartDecision.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2010-2024 JPEXS, All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. - */ -package com.jpexs.decompiler.graph; - -import java.util.Objects; - -/** - * - * @author JPEXS - */ -public class GraphPartDecision { - - public GraphPart part; - public int way; - - public GraphPartDecision(GraphPart part, int way) { - this.part = part; - this.way = way; - } - - @Override - public String toString() { - return part.toString() + ":" + way; - } - - @Override - public int hashCode() { - int hash = 3; - hash = 59 * hash + Objects.hashCode(this.part); - hash = 59 * hash + this.way; - return hash; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final GraphPartDecision other = (GraphPartDecision) obj; - if (this.way != other.way) { - return false; - } - if (!Objects.equals(this.part, other.part)) { - return false; - } - return true; - } - -} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartEdge.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartEdge.java index f269735a8..4660e0f0b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartEdge.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartEdge.java @@ -19,19 +19,35 @@ package com.jpexs.decompiler.graph; import java.util.Objects; /** - * + * Edge of a graph. Represents a connection between two GraphParts. * @author JPEXS */ public class GraphPartEdge { + /** + * From part + */ public GraphPart from; + + /** + * To part + */ public GraphPart to; + /** + * Constructs a new edge + * @param from From + * @param to To + */ public GraphPartEdge(GraphPart from, GraphPart to) { this.from = from; this.to = to; } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 3; @@ -40,6 +56,11 @@ public class GraphPartEdge { return hash; } + /** + * Equals + * @param obj Object to compare + * @return True if equals + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -61,6 +82,10 @@ public class GraphPartEdge { return true; } + /** + * To string + * @return String representation + */ @Override public String toString() { return from.toString() + " -> " + to.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java index 69540a3c8..c0155283d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartMarkedArrayList.java @@ -21,14 +21,25 @@ import java.util.Collection; import java.util.List; /** - * + * List which can store parts of the graph for each element. * @author JPEXS */ public class GraphPartMarkedArrayList extends ArrayList { + /** + * List of parts for each element. + */ private List> listParts = new ArrayList<>(); + + /** + * Current parts. + */ private List currentParts = new ArrayList<>(); + /** + * Constructs GraphPartMarkedArrayList from another collection. + * @param collection + */ @SuppressWarnings("unchecked") public GraphPartMarkedArrayList(Collection collection) { super(collection); @@ -44,33 +55,63 @@ public class GraphPartMarkedArrayList extends ArrayList { } } + /** + * Constructs GraphPartMarkedArrayList. + */ public GraphPartMarkedArrayList() { } + /** + * Starts new part. + * @param part Part + */ public void startPart(GraphPart part) { currentParts.add(part); } + /** + * Clears current parts. + */ public void clearCurrentParts() { currentParts = new ArrayList<>(); } + /** + * Adds element to the collection. + * @param e element whose presence in this collection is to be ensured + * @return true if this collection changed as a result of the call + */ @Override public boolean add(E e) { listParts.add(currentParts); return super.add(e); } + /** + * Inserts the specified element at the specified position in this list. + * @param index index at which the specified element is to be inserted + * @param element element to be inserted + */ @Override public void add(int index, E element) { listParts.add(index, currentParts); super.add(index, element); } + /** + * Returns the parts at the specified index. + * @param index index of the element + * @return parts at the specified index + */ public List getPartsAt(int index) { return listParts.get(index); } + /** + * Gets the index of the part in the list. + * @param part + * @return + */ public int indexOfPart(GraphPart part) { for (int i = 0; i < listParts.size(); i++) { List list = listParts.get(i); @@ -81,6 +122,11 @@ public class GraphPartMarkedArrayList extends ArrayList { return -1; } + /** + * Adds all elements from the collection to this collection. + * @param c collection containing elements to be added to this collection + * @return true if this collection changed as a result of the call + */ @SuppressWarnings("unchecked") @Override public boolean addAll(Collection c) { @@ -96,6 +142,13 @@ public class GraphPartMarkedArrayList extends ArrayList { return super.addAll(c); } + /** + * Inserts all elements in the specified collection into this list at the + * @param index index at which to insert the first element from the + * specified collection + * @param c collection containing elements to be added to this list + * @return true if this list changed as a result of the call + */ @SuppressWarnings("unchecked") @Override public boolean addAll(int index, Collection c) { @@ -111,6 +164,11 @@ public class GraphPartMarkedArrayList extends ArrayList { return super.addAll(index, c); } + /** + * Removes the first occurrence of the specified element from this list, if + * @param o element to be removed from this list, if present + * @return true if an element was removed as a result of this call + */ @Override public boolean remove(Object o) { if (contains(o)) { @@ -119,18 +177,32 @@ public class GraphPartMarkedArrayList extends ArrayList { return super.remove(o); } + /** + * Removes the element at the specified position in this list. Shifts any + * @param index the index of the element to be removed + * @return the element that was removed from the list + */ @Override public E remove(int index) { listParts.remove(index); return super.remove(index); } + /** + * Clears the list. + */ @Override public void clear() { listParts.clear(); super.clear(); } + /** + * Returns a view of the portion of this list between the specified + * @param fromIndex low endpoint (inclusive) of the subList + * @param toIndex high endpoint (exclusive) of the subList + * @return a view of the specified range within this list + */ @Override public List subList(int fromIndex, int toIndex) { GraphPartMarkedArrayList ret = new GraphPartMarkedArrayList(this); @@ -143,11 +215,20 @@ public class GraphPartMarkedArrayList extends ArrayList { return ret; } + /** + * Returns a shallow copy of this ArrayList instance. + * @return a clone of this ArrayList instance + */ @Override public Object clone() { return new GraphPartMarkedArrayList<>(this); } + /** + * Removes from this list all of its elements that are contained in the + * @param c collection containing elements to be removed from this list + * @return true if this list changed as a result of the call + */ @Override public boolean removeAll(Collection c) { for (Object o : c) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartQueue.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartQueue.java index 6f8a897c5..40aead9f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartQueue.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPartQueue.java @@ -20,17 +20,24 @@ import java.util.Collection; import java.util.LinkedList; /** - * + * Queue of GraphPart objects. * @author JPEXS */ public class GraphPartQueue extends LinkedList { public Loop currentLoop; + /** + * Constructs a GraphPartQueue containing the elements of the specified collection. + * @param c + */ public GraphPartQueue(Collection c) { super(c); } + /** + * Constructs an empty GraphPartQueue. + */ public GraphPartQueue() { } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPath.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPath.java index ee782769e..792741935 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPath.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphPath.java @@ -22,93 +22,159 @@ import java.util.List; import java.util.Objects; /** - * + * Represents a path in a graph. * @author JPEXS */ public class GraphPath implements Serializable { - private final List keys = new ArrayList<>(); + /** + * List of IPs where the Path branched + */ + private final List branchIps = new ArrayList<>(); - private final List vals = new ArrayList<>(); + /** + * List of branch indices of which way the path went + */ + private final List branchIndices = new ArrayList<>(); + /** + * Name of the root + */ public final String rootName; - public GraphPath(String rootName, List keys, List vals) { + /** + * Constructs a GraphPath with the given root name, branch IPs and branch indices. + * @param rootName Root name + * @param branchIps Branch IPs + * @param branchIndices Branch indices + */ + public GraphPath(String rootName, List branchIps, List branchIndices) { this.rootName = rootName; - this.keys.addAll(keys); - this.vals.addAll(vals); + this.branchIps.addAll(branchIps); + this.branchIndices.addAll(branchIndices); } - public GraphPath(List keys, List vals) { + /** + * Constructs a GraphPath with the given branch IPs and branch indices. + * @param branchIps Branch IPs + * @param branchIndices Branch indices + */ + public GraphPath(List branchIps, List branchIndices) { rootName = ""; - this.keys.addAll(keys); - this.vals.addAll(vals); + this.branchIps.addAll(branchIps); + this.branchIndices.addAll(branchIndices); } + /** + * Constructs a GraphPath + */ public GraphPath() { rootName = ""; } + /** + * Checks whether the path starts with the given path. + * @param p + * @return True if the path starts with the given path, false otherwise + */ public boolean startsWith(GraphPath p) { if (p.length() > length()) { return false; } - List otherKeys = new ArrayList<>(p.keys); - List otherVals = new ArrayList<>(p.vals); + List otherKeys = new ArrayList<>(p.branchIps); + List otherVals = new ArrayList<>(p.branchIndices); for (int i = 0; i < p.length(); i++) { - if (!Objects.equals(keys.get(i), otherKeys.get(i))) { + if (!Objects.equals(branchIps.get(i), otherKeys.get(i))) { return false; } - if (!Objects.equals(vals.get(i), otherVals.get(i))) { + if (!Objects.equals(branchIndices.get(i), otherVals.get(i))) { return false; } } return true; } + /** + * Returns a new parent GraphPath with the given length. + * @param len Length + * @return + */ public GraphPath parent(int len) { GraphPath par = new GraphPath(rootName); for (int i = 0; i < len; i++) { - par.keys.add(keys.get(i)); - par.vals.add(vals.get(i)); + par.branchIps.add(branchIps.get(i)); + par.branchIndices.add(branchIndices.get(i)); } return par; } - public GraphPath sub(int part, int codePos) { - GraphPath next = new GraphPath(rootName, this.keys, this.vals); - next.keys.add(codePos); - next.vals.add(part); + /** + * Returns a new sub GraphPath with the given branch index and code position. + * @param branchIndex Branch index + * @param codePos Code position + * @return New sub GraphPath + */ + public GraphPath sub(int branchIndex, int codePos) { + GraphPath next = new GraphPath(rootName, this.branchIps, this.branchIndices); + next.branchIps.add(codePos); + next.branchIndices.add(branchIndex); return next; } + /** + * Constructs a GraphPath with the given root name. + * @param rootName Root name + */ public GraphPath(String rootName) { this.rootName = rootName; } + /** + * Gets length of the path. + * @return Length + */ public int length() { - return vals.size(); + return branchIndices.size(); } + /** + * Gets the branch index at the given index. + * @param index Index + * @return Branch index + */ public int get(int index) { - return vals.get(index); + return branchIndices.get(index); } + /** + * Gets the IP at the given index. + * @param index Index + * @return IP + */ public int getKey(int index) { - return keys.get(index); + return branchIps.get(index); } + /** + * Hash code. + * @return Hash code + */ @Override public int hashCode() { int hash = 5; - hash = 23 * hash + arrHashCode(keys); - hash = 23 * hash + arrHashCode(vals); + hash = 23 * hash + arrHashCode(branchIps); + hash = 23 * hash + arrHashCode(branchIndices); hash = 23 * hash + Objects.hashCode(rootName); return hash; } + /** + * Equals. + * @param obj Eq + * @return + */ @Override public boolean equals(Object obj) { if (obj == null) { @@ -126,17 +192,22 @@ public class GraphPath implements Serializable { return false; } - if (!arrMatch(keys, other.keys)) { + if (!arrMatch(branchIps, other.branchIps)) { return false; } - if (!arrMatch(vals, other.vals)) { + if (!arrMatch(branchIndices, other.branchIndices)) { return false; } return true; } + /** + * Hash code for a list of integers. + * @param arr List of integers + * @return Hash code + */ private static int arrHashCode(List arr) { if (arr == null || arr.isEmpty()) { return 0; @@ -150,6 +221,12 @@ public class GraphPath implements Serializable { return hash; } + /** + * Checks whether two lists of integers match. + * @param arr List of integers + * @param arr2 List of integers + * @return True if the lists match, false otherwise + */ private static boolean arrMatch(List arr, List arr2) { if (arr.size() != arr2.size()) { return false; @@ -162,11 +239,15 @@ public class GraphPath implements Serializable { return true; } + /** + * Returns a string representation of the GraphPath. + * @return String representation + */ @Override public String toString() { String ret = rootName; - for (int i = 0; i < keys.size(); i++) { - ret += "/" + keys.get(i) + ":" + vals.get(i); + for (int i = 0; i < branchIps.size(); i++) { + ret += "/" + branchIps.get(i) + ":" + branchIndices.get(i); } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java index 3cf5c4862..c53a8e638 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.action.Action; + import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; @@ -25,23 +26,67 @@ import java.util.List; import java.util.Set; /** - * + * Graph source abstract class * @author JPEXS */ public abstract class GraphSource implements Serializable { + /** + * Gets the size of the graph source + * @return The size of the graph source + */ public abstract int 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 + */ public abstract GraphSourceItem get(int pos); + /** + * Checks if the graph source is empty + * @return True if the graph source is empty, false otherwise + */ public abstract boolean 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 + */ public abstract List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException; + /** + * Gets the important addresses + * @return Set of important addresses + */ public abstract Set getImportantAddresses(); + /** + * Converts instruction at the specified position to string + * @param pos Position of the instruction + * @return Instruction as string + */ public abstract String insToString(int pos); + /** + * Visits the code + * @param ip Start position + * @param lastIp Last position + * @param refs References + * @param endIp End position + * @throws InterruptedException + */ private void visitCode(int ip, int lastIp, HashMap> refs, int endIp) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -96,6 +141,12 @@ public abstract class GraphSource implements Serializable { } } + /** + * Visits the code + * @param alternateEntries Alternate entries + * @return References + * @throws InterruptedException + */ public HashMap> visitCode(List alternateEntries) throws InterruptedException { HashMap> refs = new HashMap<>(); int siz = size(); @@ -111,10 +162,25 @@ public abstract class GraphSource implements Serializable { return refs; } + /** + * Converts address to position + * @param adr Address + * @return Position + */ public abstract int adr2pos(long adr); + /** + * Converts address to position + * @param adr Address + * @param nearest Nearest + * @return Position + */ public abstract int adr2pos(long adr, boolean nearest); + /** + * Gets the address after the code + * @return Address after the code + */ public long getAddressAfterCode() { if (isEmpty()) { return 0; @@ -123,8 +189,19 @@ public abstract class GraphSource implements Serializable { return lastAddr + get(size() - 1).getBytesLength(); } + /** + * Converts position to address + * @param pos Position + * @return Address + */ public abstract long pos2adr(int pos); + /** + * Converts position to address + * @param pos Position + * @param allowPosAfterCode Allow position after code + * @return Address + */ public final long pos2adr(int pos, boolean allowPosAfterCode) { if (pos == size() && allowPosAfterCode) { return getAddressAfterCode(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java index 17a8cf469..c91361948 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItem.java @@ -17,62 +17,144 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.BaseLocalData; + import java.io.Serializable; import java.util.List; /** - * + * Item of Graph source. Usually an instruction. * @author JPEXS */ public interface GraphSourceItem extends Serializable, Cloneable { + /** + * 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 + */ public void translate(BaseLocalData localData, TranslateStack stack, List output, int staticOperation, String path) throws InterruptedException; + /** + * 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 + */ public int getStackPopCount(BaseLocalData localData, TranslateStack stack); + /** + * 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 + */ public int getStackPushCount(BaseLocalData localData, TranslateStack stack); + /** + * Gets file offset. + * @return File offset + */ public long getFileOffset(); + /** + * Checks whether this item is a jump. + * @return True if this item is a jump, false otherwise + */ public boolean isJump(); + /** + * Checks whether this item is a branch. + * @return True if this item is a branch, false otherwise + */ public boolean isBranch(); + /** + * Checks whether this item is an exit (throw, return, etc.). + * @return True if this item is an exit, false otherwise + */ public boolean isExit(); + /** + * Gets the address. + * @return Address + */ public long getAddress(); + /** + * Gets the line offset. + * @return Line offset + */ public long getLineOffset(); + /** + * Checks whether the loops are ignored. + * FIXME: What is this, how to use it? + * @return True if the loops are ignored, false otherwise + */ public boolean ignoredLoops(); + /** + * Gets branches + * @param code Code + * @return List of IPs to branch to + */ public List getBranches(GraphSource code); + /** + * Checks whether this item is ignored. + * @return True if this item is ignored, false otherwise + */ public boolean isIgnored(); + /** + * Sets whether this item is ignored. + * @param ignored True if this item is ignored, false otherwise + * @param pos Sub position + */ public void setIgnored(boolean ignored, int pos); + /** + * 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 + */ public boolean isDeobfuscatePop(); + /** + * Gets the line in the high level source code. + * @return Line + */ public int getLine(); + /** + * Gets the high level source code file name. + * @return File name + */ public String getFile(); + /** + * Gets length of the item in bytes. + * @return Length of the item in bytes + */ public abstract int getBytesLength(); /** - * Gets virtual address. A virtual adress can be used for storing original - * address before applying deobfuscation + * Gets virtual address. A virtual address can be used for storing original + * address before applying deobfuscation. * - * @return + * @return Virtual address */ public long getVirtualAddress(); /** - * Sets virtual address. A virtual adress can be used for storing original - * address before applying deobfuscation + * Sets virtual address. A virtual address can be used for storing original + * address before applying deobfuscation. * - * @param virtualAddress + * @param virtualAddress Virtual address */ public void setVirtualAddress(long virtualAddress); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemContainer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemContainer.java index 9b66e7196..2df4c79fe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemContainer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemContainer.java @@ -17,28 +17,71 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.action.parser.pcode.FlasmLexer; + import java.util.HashMap; import java.util.List; /** - * + * Container for source items. * @author JPEXS */ public interface GraphSourceItemContainer { + /** + * Gets the size of the header. + * @return The size of the header. + */ public long getHeaderSize(); + /** + * Gets the sizes of the container parts. + * @return List of sizes of the container parts. + */ public List getContainerSizes(); + /** + * Sets the size of the container part. + * @param index Index of the container part. + * @param size Size of the container part. + */ public void setContainerSize(int index, long size); + /** + * Gets the ASM source between the specified position. + * @param pos Index of container part + * @return ASM source between the specified position + */ public String getASMSourceBetween(int pos); + /** + * Parses the division + * @param size Size up to this point + * @param lexer Lexer + * @return + */ public boolean parseDivision(long size, FlasmLexer lexer); + /** + * Gets the names of the registers. + * @return The names of the registers. Map of register index and register name. + */ public HashMap getRegNames(); + /** + * Translates the container to high level code. + * @param contents List of contents of the container parts + * @param lineStartItem Start source item of the line + * @param stack Stack + * @param output Output + * @param regNames Register names + * @param variables Variables + * @param functions Functions + */ public void translateContainer(List> contents, GraphSourceItem lineStartItem, TranslateStack stack, List output, HashMap regNames, HashMap variables, HashMap functions); + /** + * Gets the name of the container. + * @return The name of the container + */ public String getName(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemPos.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemPos.java index 77d65bc5e..d60fbb90e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemPos.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSourceItemPos.java @@ -19,15 +19,26 @@ package com.jpexs.decompiler.graph; import java.io.Serializable; /** - * + * Graph source item with a position. * @author JPEXS */ public class GraphSourceItemPos implements Serializable { + /** + * Source item + */ public GraphSourceItem item; + /** + * Position + */ public int pos; + /** + * Constructs a GraphSourceItemPos + * @param item Source item + * @param pos Position + */ public GraphSourceItemPos(GraphSourceItem item, int pos) { this.item = item; this.pos = pos; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 5fedcf3e0..80e868111 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -17,44 +17,28 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair; -import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.*; import com.jpexs.decompiler.flash.action.model.DirectValueActionItem; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.ecma.ArrayType; -import com.jpexs.decompiler.flash.ecma.EcmaScript; -import com.jpexs.decompiler.flash.ecma.Null; -import com.jpexs.decompiler.flash.ecma.ObjectType; -import com.jpexs.decompiler.flash.ecma.Undefined; +import com.jpexs.decompiler.flash.ecma.*; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; -import com.jpexs.decompiler.graph.model.BinaryOp; -import com.jpexs.decompiler.graph.model.FalseItem; -import com.jpexs.decompiler.graph.model.LocalData; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.TrueItem; +import com.jpexs.decompiler.graph.model.*; import com.jpexs.helpers.Reference; + import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** - * + * Graph target item - an item in high level representation of the code. + * Decompilation target. * @author JPEXS */ public abstract class GraphTargetItem implements Serializable, Cloneable { + //Precedence levels + public static final int PRECEDENCE_PRIMARY = 0; public static final int PRECEDENCE_POSTFIX = 1; @@ -89,24 +73,54 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { public static final int NOPRECEDENCE = 16; + /** + * Source item + */ private GraphSourceItem src; + /** + * Precedence level + */ protected int precedence; + /** + * More source items + */ private List moreSrc; + /** + * First part of the graph + */ public GraphPart firstPart; + /** + * Value + */ public GraphTargetItem value; + /** + * Source hilight data + */ private HighlightData srcData; + /** + * Line start item + */ public GraphSourceItem lineStartItem; + /** + * Gets the line start item + * @return Line start item + */ public GraphSourceItem getLineStartItem() { return lineStartItem; } + /** + * Converts a value to an item + * @param r Value + * @return Graph target item + */ protected static GraphTargetItem valToItem(Object r) { if (r == null) { return null; @@ -156,6 +170,12 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return null; } + /** + * Simplifies something + * @param it Graph target item + * @param implicitCoerce Implicit coerce + * @return Simplified graph target item + */ public static GraphTargetItem simplifySomething(GraphTargetItem it, String implicitCoerce) { if ((it instanceof SimpleValue) && implicitCoerce.isEmpty()) { if (((SimpleValue) it).isSimpleValue()) { @@ -189,10 +209,19 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return it2; } + /** + * Simplifies this. + * @param implicitCoerce Implicit coerce + * @return Simplified graph target item + */ public GraphTargetItem simplify(String implicitCoerce) { return simplifySomething(this, implicitCoerce); } + /** + * Gets line. + * @return Line + */ public int getLine() { if (src != null) { return src.getLine(); @@ -200,6 +229,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return 0; } + /** + * Gets file. + * @return File + */ public String getFile() { if (src != null) { return src.getFile(); @@ -207,6 +240,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return null; } + /** + * Gets first graph part. + * @return First graph part + */ public GraphPart getFirstPart() { if (value == null) { return firstPart; @@ -218,14 +255,30 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ret; } + /** + * Constructs GraphTargetItem + */ public GraphTargetItem() { this(null, null, NOPRECEDENCE); } + /** + * Constructs GraphTargetItem + * @param src Source item + * @param lineStartItem Line start item + * @param precedence Precedence + */ public GraphTargetItem(GraphSourceItem src, GraphSourceItem lineStartItem, int precedence) { this(src, lineStartItem, precedence, null); } + /** + * Constructs GraphTargetItem + * @param src Source item + * @param lineStartItem Line start item + * @param precedence Precedence + * @param value Value + */ public GraphTargetItem(GraphSourceItem src, GraphSourceItem lineStartItem, int precedence, GraphTargetItem value) { this.src = src; this.lineStartItem = lineStartItem; @@ -233,10 +286,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { this.value = value; } + /** + * Gets source item + * @return Source item + */ public GraphSourceItem getSrc() { return src; } + /** + * Gets more source items + * @return More source items + */ public List getMoreSrc() { if (moreSrc == null) { moreSrc = new ArrayList<>(); @@ -245,6 +306,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return moreSrc; } + /** + * Gets highlight src data + * @return + */ protected HighlightData getSrcData() { if (srcData == null) { srcData = new HighlightData(); @@ -253,10 +318,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return srcData; } + /** + * Gets position + * @return Position + */ protected int getPos() { return 0; } + /** + * Gets needed sources + * @return Needed sources + */ public List getNeededSources() { List ret = new ArrayList<>(); ret.add(new GraphSourceItemPos(src, getPos())); @@ -271,6 +344,13 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ret; } + /** + * Converts this to string semicoloned. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringSemicoloned(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -285,31 +365,74 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer; } + /** + * Checks if semicolon is needed + * @return True if semicolon is needed + */ public boolean needsSemicolon() { return true; } + /** + * Converts this to string as Boolean. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData, "Boolean"); } + /** + * Converts this to string as String. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringString(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData, "String"); } + /** + * Converts this to string as int. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringInt(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData, "int"); } + /** + * Converts this to string as Number. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringNumber(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData, "Number"); } + /** + * Converts this to string. + * @return String + */ @Override public String toString() { return getClass().getName(); } + /** + * Converts this to string. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); @@ -321,10 +444,22 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer; } + /** + * Converts this to string. + * @param localData Local data + * @return String + * @throws InterruptedException + */ public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData, ""); } + /** + * Converts this to string. + * @param localData Local data + * @return String + * @throws InterruptedException + */ public String toString(LocalData localData) throws InterruptedException { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toString(writer, localData); @@ -332,12 +467,34 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer.toString(); } + /** + * Append this to a writer. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException; + /** + * Append this to a writer. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData) throws InterruptedException { return appendTry(writer, localData, ""); } + /** + * Append this to a writer. + * @param writer Writer + * @param localData Local data + * @param implicitCoerce Implicit coerce + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException { GraphTargetItem t = this; if (!implicitCoerce.isEmpty()) { //if implicit oerce equals explicit @@ -366,10 +523,18 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { } + /** + * Gets precedence. + * @return Precedence + */ public int getPrecedence() { return precedence; } + /** + * Checks if this can be evaluated statically. + * @return True if this can be evaluated statically + */ public boolean isCompileTime() { Set dependencies = new HashSet<>(); if (!((this instanceof SimpleValue) && ((SimpleValue) this).isSimpleValue())) { @@ -378,14 +543,29 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return isCompileTime(dependencies); } + /** + * Checks if this can be evaluated statically. + * @param dependencies Dependencies + * @return True if this can be evaluated statically + */ public boolean isCompileTime(Set dependencies) { return false; } + /** + * Checks if this can be evaluated statically. + * @param dependencies Dependencies + * @return True if this can be evaluated statically + */ public boolean isConvertedCompileTime(Set dependencies) { return isCompileTime(); } + /** + * Checks whether this has side effects. + * For example function call has side effect, but variable access does not. + * @return True if this has side effects + */ public boolean hasSideEffect() { Reference ref = new Reference<>(false); visitRecursively(new AbstractGraphTargetVisitor() { @@ -399,26 +579,51 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ref.getVal(); } + /** + * Checks whether it is computed via variables. + * @return True if it is computed via variables + */ public boolean isVariableComputed() { return false; } + /** + * Computes EcmaScript result. + * @return EcmaScript result + */ public Object getResult() { return null; } + /** + * Computes EcmaScript result as number. + * @return EcmaScript result as number + */ public Double getResultAsNumber() { return EcmaScript.toNumberAs2(getResult()); } + /** + * Computes EcmaScript result as string. + * @return EcmaScript result as string + */ public String getResultAsString() { return EcmaScript.toString(getResult()); } + /** + * Computes EcmaScript result as boolean. + * @return EcmaScript result as boolean + */ public Boolean getResultAsBoolean() { return EcmaScript.toBoolean(getResult()); } + /** + * Converts this to string without quotes. + * @param localData Local data + * @return String + */ public String toStringNoQuotes(LocalData localData) { try { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); @@ -431,6 +636,13 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ""; } + /** + * Converts this to string without quotes. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.startOffset(src, getLineStartItem(), getPos(), srcData); appendToNoQuotes(writer, localData); @@ -438,30 +650,64 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer; } + /** + * Appends this to a writer without quotes. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter appendToNoQuotes(GraphTextWriter writer, LocalData localData) throws InterruptedException { return toString(writer, localData); } + /** + * Gets this without coercion. + * @return This without coercion + */ public GraphTargetItem getNotCoerced() { return this; } + /** + * Gets this without coercion and without duplicates. + * @return This without coercion and without duplicates + */ public GraphTargetItem getNotCoercedNoDup() { return getNotCoerced(); } + /** + * Gets this through registers. + * @return This through registers + */ public GraphTargetItem getThroughRegister() { return this; } + /** + * Checks whether this needs a new line. + * @return True if this needs a new line + */ public boolean needsNewLine() { return false; } + /** + * Checks whether this handles new line. + * @return True if this handles new line + */ public boolean handlesNewLine() { return false; } + /** + * Converts this to string with new line. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.startOffset(src, getLineStartItem(), getPos(), srcData); appendTry(writer, localData); @@ -472,26 +718,57 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer; } + /** + * Checks whether this is empty. + * @return True if this is empty + */ public boolean isEmpty() { return false; } + /** + * Gets through items that cannot be statically computed. + * @return Through item that cannot be statically computed + */ public GraphTargetItem getThroughNotCompilable() { return this; } + /** + * Gets item through duplicates. + * @return Item through duplicates + */ public GraphTargetItem getThroughDuplicate() { return this; } + /** + * Checks whether the value equals. + * @param target Target + * @return True if the value equals + */ public boolean valueEquals(GraphTargetItem target) { return equals(target); } + /** + * Converts this to source (low level code). + * @param localData Local data + * @param generator Source generator + * @return Source + * @throws CompilationException + */ public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return new ArrayList<>(); } + /** + * Converts this to source (low level code) and ignore return value. + * @param localData Local data + * @param generator Source generator + * @return Source + * @throws CompilationException + */ public List toSourceIgnoreReturnValue(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { if (!hasReturnValue()) { return toSource(localData, generator); @@ -499,12 +776,26 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return generator.generateDiscardValue(localData, this); } + /** + * Converts this to source (low level code). with BinaryOp + * @param op Binary operation + * @param action Action + * @return Source + */ protected List toSourceBinary(BinaryOp op, GraphSourceItem action) { List ret = new ArrayList<>(); return ret; } + /** + * Merges Object list to one list of GraphTargetItems + * @param localData Local data + * @param gen Source generator + * @param tar Objects + * @return List of GraphTargetItems + * @throws CompilationException + */ public static List toSourceMerge(SourceGeneratorLocalData localData, SourceGenerator gen, Object... tar) throws CompilationException { List ret = new ArrayList<>(); for (Object o : tar) { @@ -532,8 +823,16 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ret; } + /** + * Checks whether this has return value. + * @return True if this has return value + */ public abstract boolean hasReturnValue(); + /** + * Gets all sub items. + * @return All sub items + */ public List getAllSubItems() { List ret = new ArrayList<>(); visit(new AbstractGraphTargetVisitor() { @@ -547,6 +846,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ret; } + /** + * Gets all sub items recursively. + * @return All sub items recursively + */ public Set getAllSubItemsRecursively() { Set ret = new HashSet<>(); visitRecursively(new AbstractGraphTargetVisitor() { @@ -558,6 +861,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return ret; } + /** + * Visits this recursively. + * @param visitor Visitor + */ public final void visitRecursively(GraphTargetVisitorInterface visitor) { Set visitedItems = new HashSet<>(); visit(new AbstractGraphTargetVisitor() { @@ -572,6 +879,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { }); } + /** + * Visits this recursively without using Blocks. + * @param visitor Visitor + */ public final void visitRecursivelyNoBlock(GraphTargetVisitorInterface visitor) { Set visitedItems = new HashSet<>(); visitNoBlock(new AbstractGraphTargetVisitor() { @@ -586,18 +897,34 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { }); } + /** + * Visits this. + * @param visitor Visitor + */ public void visit(GraphTargetVisitorInterface visitor) { if (value != null) { visitor.visit(value); } } + /** + * Visits this without using Blocks. + * @param visitor + */ public void visitNoBlock(GraphTargetVisitorInterface visitor) { visit(visitor); } + /** + * Gets return type. + * @return + */ public abstract GraphTargetItem returnType(); + /** + * Clone this. + * @return Cloned item + */ @Override public GraphTargetItem clone() { try { @@ -607,10 +934,25 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { } } + /** + * Inverts this item. + * @param src Source item + * @return Inverted item + */ public GraphTargetItem invert(GraphSourceItem src) { return new NotItem(src, getLineStartItem(), this); } + /** + * Appends this to a writer. + * @param prevLineItem Previous line item + * @param writer Writer + * @param localData Local data + * @param commands Commands + * @param asBlock As block + * @return Writer + * @throws InterruptedException + */ public GraphTextWriter appendCommands(GraphTargetItem prevLineItem, GraphTextWriter writer, LocalData localData, List commands, boolean asBlock) throws InterruptedException { //This may be useful in the future, but we must handle obfuscated SWFs where there is only one debugline instruction on the beggining. @@ -642,11 +984,24 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return writer; } + /** + * Append this to a writer as a Block. + * @param prevLineItem + * @param writer + * @param localData + * @param commands + * @return + * @throws InterruptedException + */ public GraphTextWriter appendBlock(GraphTargetItem prevLineItem, GraphTextWriter writer, LocalData localData, List commands) throws InterruptedException { appendCommands(prevLineItem, writer, localData, commands, true); return writer; } + /** + * Gets this as long. + * @return + */ public long getAsLong() { if (this instanceof DirectValueActionItem) { DirectValueActionItem dvai = (DirectValueActionItem) this; @@ -656,10 +1011,21 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { return 0; } + /** + * Checks whether this is identical to other. + * @param other Other + * @return True if this is identical to other + */ public boolean isIdentical(GraphTargetItem other) { return this == other; } + /** + * Alternative of Objects.equals() for GraphTargetItem. + * @param o1 Object 1 + * @param o2 Object 2 + * @return True if objects are value equal + */ public static boolean objectsValueEquals(Object o1, Object o2) { if (o1 == null && o2 == null) { return true; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetVisitorInterface.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetVisitorInterface.java index 33345436e..a04e661d7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetVisitorInterface.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetVisitorInterface.java @@ -19,12 +19,20 @@ package com.jpexs.decompiler.graph; import java.util.Collection; /** - * + * Graph source visitor interface. * @author JPEXS */ public interface GraphTargetVisitorInterface { + /** + * Visits a graph target item. + * @param item Graph target item + */ public void visit(GraphTargetItem item); + /** + * Visits all graph target items. + * @param items Collection of graph target items + */ public void visitAll(Collection items); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Loop.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Loop.java index cfd50b30a..971870a79 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Loop.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Loop.java @@ -17,48 +17,88 @@ package com.jpexs.decompiler.graph; import java.io.Serializable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; /** - * + * A loop in a graph. * @author JPEXS */ public class Loop implements Serializable { + /** + * Continue part of the loop + */ public GraphPart loopContinue; + /** + * Break part of the loop + */ public GraphPart loopBreak; + /** + * Precontinue part of the loop. + * A precontinue is a part of the loop that is executed before the continue part. + * Example of this is a for loop with continue statement. + */ public GraphPart loopPreContinue; + /** + * Back edges of the loop + */ public Set backEdges = new HashSet<>(); + /** + * Break candidates of the loop + */ public List breakCandidates = new ArrayList<>(); + /** + * Levels of the break candidates + */ public List breakCandidatesLevels = new ArrayList<>(); + /** + * Unique id of the loop + */ public final long id; + /** + * Mark for leads to method + */ public int leadsToMark; + /** + * Mark for reachable method + */ public int reachableMark; + /** + * Phase of the loop. + * The decompiler marks here whether the loop is already processed or not. + */ public int phase; + /** + * Break candidates are locked + */ public int breakCandidatesLocked = 0; - public List precontinueCommands = null; - + /** + * Constructs a loop + * @param id Unique id of the loop + * @param loopContinue Continue part of the loop + * @param loopBreak Break part of the loop + */ public Loop(long id, GraphPart loopContinue, GraphPart loopBreak) { this.loopContinue = loopContinue; this.loopBreak = loopBreak; this.id = id; } + /** + * To string method + * @return String representation of the loop + */ @Override public String toString() { Set edgesAsStr = new HashSet<>(); @@ -73,6 +113,10 @@ public class Loop implements Serializable { return "loop(id:" + id + (loopPreContinue != null ? ",precontinue:" + loopPreContinue : "") + ",continue:" + loopContinue + ", break:" + loopBreak + ", phase:" + phase + ", backedges: " + String.join(",", edgesAsStr) + ", breakCandidates: " + String.join(",", bcAsStr) + ")"; } + /** + * Hash code + * @return Hash code of the loop + */ @Override public int hashCode() { int hash = 3; @@ -80,6 +124,11 @@ public class Loop implements Serializable { return hash; } + /** + * Equals + * @param obj Object to compare + * @return True if the object is equal to this loop + */ @Override public boolean equals(Object obj) { if (obj == null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/MarkItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/MarkItem.java index 43eb0025d..c36269e5f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/MarkItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/MarkItem.java @@ -21,37 +21,66 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.model.LocalData; /** - * + * Special item for marking a position in the graph. * @author JPEXS */ public class MarkItem extends GraphTargetItem { + /** + * Mark string + */ private final String mark; + /** + * Constructs a new mark item. + * @param mark Mark string + */ public MarkItem(String mark) { super(null, null, NOPRECEDENCE); this.mark = mark; } + /** + * Appends this item to the writer. + * @param writer Writer + * @param localData Local data + * @return + */ @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) { return writer.append("// ").append(AppResources.translate("decompilerMark")).append(":").append(mark); } + /** + * Gets the mark string. + * @return + */ public String getMark() { return mark; } + /** + * Checks if this item is empty. + * @return Always true + */ @Override public boolean isEmpty() { return true; } + /** + * Checks if this item has a return value. + * @return Always false + */ @Override public boolean hasReturnValue() { return false; } + /** + * Gets the return type of this item. + * @return Unbounded + */ @Override public GraphTargetItem returnType() { return TypeItem.UNBOUNDED; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotCompileTimeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotCompileTimeItem.java index 4627e49be..e545aca38 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotCompileTimeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotCompileTimeItem.java @@ -18,26 +18,46 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.model.LocalData; + import java.util.Set; /** - * + * An item that cannot be statically computed. * @author JPEXS */ public class NotCompileTimeItem extends GraphTargetItem { + /** + * Object that cannot be statically computed. + */ public GraphTargetItem object; + /** + * Constructs a new NotCompileTimeItem. + * @param instruction Instruction + * @param lineStartIns Line start instruction + * @param object Object that cannot be statically computed + */ public NotCompileTimeItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem object) { super(instruction, lineStartIns, NOPRECEDENCE); this.object = object; } + /** + * Whether this item can be computed statically. + * @param dependencies Dependencies + * @return Whether this item can be computed statically + */ @Override public boolean isCompileTime(Set dependencies) { return false; } + + /** + * Gets through the object that cannot be statically computed. + * @return Through the object that cannot be statically computed + */ @Override public GraphTargetItem getThroughNotCompilable() { if (object == null) { @@ -46,16 +66,31 @@ public class NotCompileTimeItem extends GraphTargetItem { return object.getThroughNotCompilable(); } + /** + * Appends this item to the writer. + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { return object.toString(writer, localData); } + /** + * Whether this item has a return value. + * @return Whether this item has a return value + */ @Override public boolean hasReturnValue() { return object.hasReturnValue(); } + /** + * Gets the return type of this item. + * @return Return type of this item + */ @Override public GraphTargetItem returnType() { return TypeItem.UNBOUNDED; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotEqualsTypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotEqualsTypeItem.java index b20b39aab..f09875412 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotEqualsTypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/NotEqualsTypeItem.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.graph.model.BinaryOp; /** - * + * Not equals type item. * @author JPEXS */ public interface NotEqualsTypeItem extends BinaryOp { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java index a7b0e01d3..a41e1ecf1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ScopeStack.java @@ -17,15 +17,22 @@ package com.jpexs.decompiler.graph; /** - * + * Stack for scope. * @author JPEXS */ public class ScopeStack extends TranslateStack { + /** + * Constructs a new ScopeStack. + * @param allowEmpty Whether empty stack is allowed + */ public ScopeStack(boolean allowEmpty) { super(allowEmpty ? "scope" : null); } + /** + * Constructs a new ScopeStack. + */ public ScopeStack() { this(true); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassData.java index b5abf7468..a68467329 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassData.java @@ -20,10 +20,13 @@ import java.util.HashSet; import java.util.Set; /** - * + * Second pass data. * @author JPEXS */ public class SecondPassData { + /** + * All switch parts. + */ public Set allSwitchParts = new HashSet<>(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassException.java index 2190c3e6b..cd9d0eb7c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SecondPassException.java @@ -17,17 +17,28 @@ package com.jpexs.decompiler.graph; /** - * + * Second pass exception. * @author JPEXS */ public class SecondPassException extends RuntimeException { + /** + * Second pass data. + */ private final SecondPassData data; + /** + * Constructs a new SecondPassException. + * @param data Second pass data + */ public SecondPassException(SecondPassData data) { this.data = data; } + /** + * Gets the second pass data. + * @return Second pass data + */ public SecondPassData getData() { return data; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java index 7bb079bf3..08452d75e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SimpleValue.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.graph; /** - * + * Simple value interface. * @author JPEXS */ public interface SimpleValue { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java index 758776519..90a0e6d46 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/SourceGenerator.java @@ -17,68 +17,194 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; -import com.jpexs.decompiler.graph.model.AndItem; -import com.jpexs.decompiler.graph.model.BreakItem; -import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.ContinueItem; -import com.jpexs.decompiler.graph.model.DoWhileItem; -import com.jpexs.decompiler.graph.model.DuplicateItem; -import com.jpexs.decompiler.graph.model.FalseItem; -import com.jpexs.decompiler.graph.model.ForItem; -import com.jpexs.decompiler.graph.model.IfItem; -import com.jpexs.decompiler.graph.model.NotItem; -import com.jpexs.decompiler.graph.model.OrItem; -import com.jpexs.decompiler.graph.model.PopItem; -import com.jpexs.decompiler.graph.model.PushItem; -import com.jpexs.decompiler.graph.model.SwitchItem; -import com.jpexs.decompiler.graph.model.TernarOpItem; -import com.jpexs.decompiler.graph.model.TrueItem; -import com.jpexs.decompiler.graph.model.WhileItem; +import com.jpexs.decompiler.graph.model.*; + import java.util.List; /** - * + * Source generator interface. A low-level code generator. * @author JPEXS */ public interface SourceGenerator { + /** + * Generates source code for PushItem. + * @param localData Local data + * @param item PushItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, PushItem item) throws CompilationException; + /** + * Generates source code for PopItem. + * @param localData Local data + * @param item PopItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, PopItem item) throws CompilationException; + /** + * Generates source code for TrueItem. + * @param localData Local data + * @param item TrueItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, TrueItem item) throws CompilationException; + /** + * Generates source code for FalseItem. + * @param localData Local data + * @param item FalseItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, FalseItem item) throws CompilationException; + /** + * Generates source code for AndItem. + * @param localData Local data + * @param item AndItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, AndItem item) throws CompilationException; + /** + * Generates source code for OrItem. + * @param localData Local data + * @param item OrItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, OrItem item) throws CompilationException; + /** + * Generates source code for IfItem. + * @param localData Local data + * @param item IfItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, IfItem item) throws CompilationException; + /** + * Generates source code for TernarOpItem. + * @param localData Local data + * @param item TernarOpItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, TernarOpItem item) throws CompilationException; + /** + * Generates source code for WhileItem. + * @param localData Local data + * @param item WhileItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, WhileItem item) throws CompilationException; + /** + * Generates source code for DoWhileItem. + * @param localData Local data + * @param item DoWhileItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, DoWhileItem item) throws CompilationException; + /** + * Generates source code for ForItem. + * @param localData Local data + * @param item ForItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, ForItem item) throws CompilationException; + /** + * Generates source code for SwitchItem. + * @param localData Local data + * @param item SwitchItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, SwitchItem item) throws CompilationException; + /** + * Generates source code for NotItem. + * @param localData Local data + * @param item NotItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, NotItem item) throws CompilationException; + /** + * Generates source code for DuplicateItem. + * @param localData Local data + * @param item DuplicateItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, DuplicateItem item) throws CompilationException; + /** + * Generates source code for BreakItem. + * @param localData Local data + * @param item BreakItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, BreakItem item) throws CompilationException; + /** + * Generates source code for ContinueItem. + * @param localData Local data + * @param item ContinueItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, ContinueItem item) throws CompilationException; + /** + * Generates source code for commands. + * @param localData Local data + * @param commands List of GraphTargetItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, List commands) throws CompilationException; + /** + * Generates source code for CommaExpressionItem. + * @param localData Local data + * @param item CommaExpressionItem + * @param withReturnValue If true, the return value is used + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, CommaExpressionItem item, boolean withReturnValue) throws CompilationException; + /** + * Generates source code for TypeItem. + * @param localData Local data + * @param item TypeItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generate(SourceGeneratorLocalData localData, TypeItem item) throws CompilationException; + /** + * Generates DiscardValue action. + * @param localData Local data + * @param item GraphTargetItem + * @return List of GraphSourceItem + * @throws CompilationException + */ public List generateDiscardValue(SourceGeneratorLocalData localData, GraphTargetItem item) throws CompilationException; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/StopPartKind.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/StopPartKind.java index 712b94aad..63ef25a9c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/StopPartKind.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/StopPartKind.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.graph; /** - * + * Kind of stop part. * @author JPEXS */ public enum StopPartKind { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java index 8c76f5065..431abe6b5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java @@ -20,19 +20,45 @@ import java.util.HashSet; import java.util.Set; /** - * + * State of throwing exception in a method. * @author JPEXS */ public class ThrowState { + /** + * Exception id + */ public int exceptionId; + + /** + * Throw state + */ public int state; + /** + * Throwing parts + */ public Set throwingParts = new HashSet<>(); + + /** + * Target part + */ public GraphPart targetPart; + + /** + * Start part + */ public GraphPart startPart; + + /** + * Catch parts + */ public Set catchParts = new HashSet<>(); + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 3; @@ -40,6 +66,11 @@ public class ThrowState { return hash; } + /** + * Equals + * @param obj Object + * @return True if equals + */ @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateException.java index 15cbba5b7..2aecee761 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateException.java @@ -17,11 +17,15 @@ package com.jpexs.decompiler.graph; /** - * + * Exception thrown when there is a problem with translating the graph. * @author JPEXS */ public class TranslateException extends RuntimeException { + /** + * Constructs new TranslateException with the specified detail message. + * @param s The detail message. + */ public TranslateException(String s) { super(s); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index 68332a899..ec4af674f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -17,34 +17,56 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.graph.model.PopItem; + import java.util.Stack; import java.util.logging.Level; import java.util.logging.Logger; /** - * + * Stack for translation. * @author JPEXS */ public class TranslateStack extends Stack { + /** + * Pop item + */ private PopItem pop; + /** + * Path + */ private final String path; + /** + * Simplifies all items in the stack. + */ public void simplify() { for (int i = 0; i < size(); i++) { set(i, get(i).simplify("")); } } + /** + * Constructs new TranslateStack with the specified path. + * @param path The path. + */ public TranslateStack(String path) { this.path = path; } + /** + * Gets the path. + * @return The path. + */ public String getPath() { return path; } + /** + * Gets the pop item. + * @return The pop item. + */ private PopItem getPop() { if (pop == null) { pop = new PopItem(null, null); //TODO: linestart? @@ -53,6 +75,11 @@ public class TranslateStack extends Stack { return pop; } + /** + * Gets the item at the specified index. + * @param index index of the element to return + * @return The element at the specified position in this list + */ @Override public synchronized GraphTargetItem get(int index) { if (path != null) { @@ -64,6 +91,10 @@ public class TranslateStack extends Stack { return super.get(index); } + /** + * Gets the item at the top of the stack. + * @return The item at the top of the stack. + */ @Override public synchronized GraphTargetItem peek() { if (path != null) { @@ -75,6 +106,11 @@ public class TranslateStack extends Stack { return super.peek(); } + /** + * Gets the item at the specified index from the top of the stack. + * @param index The index. + * @return The item at the specified index from the top of the stack. + */ public synchronized GraphTargetItem peek(int index) { if (path != null) { if (index > this.size()) { @@ -85,6 +121,10 @@ public class TranslateStack extends Stack { return super.get(size() - index); } + /** + * Pop the item at the top of the stack. + * @return The item at the top of the stack. + */ @Override public synchronized GraphTargetItem pop() { if (path != null) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeFunctionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeFunctionItem.java index 79aad5fec..6c8a5d191 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeFunctionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeFunctionItem.java @@ -19,29 +19,40 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; + import java.util.Objects; /** - * + * Represents a function type. * @author JPEXS */ public class TypeFunctionItem extends GraphTargetItem { + //Basic function items public static TypeFunctionItem BOOLEAN = new TypeFunctionItem("Boolean"); - public static TypeFunctionItem STRING = new TypeFunctionItem("String"); - public static TypeFunctionItem ARRAY = new TypeFunctionItem("Array"); public static UnboundedTypeItem UNBOUNDED = TypeItem.UNBOUNDED; + /** + * Full type name + */ public String fullTypeName; + /** + * Creates a new instance of TypeFunctionItem + * @param fullTypeName Full type name + */ public TypeFunctionItem(String fullTypeName) { super(null, null, NOPRECEDENCE); this.fullTypeName = fullTypeName; } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 7; @@ -49,6 +60,11 @@ public class TypeFunctionItem extends GraphTargetItem { return hash; } + /** + * Equals + * @param obj Object to compare + * @return True if equal + */ @Override public boolean equals(Object obj) { if (obj == null) { @@ -61,22 +77,42 @@ public class TypeFunctionItem extends GraphTargetItem { return Objects.equals(fullTypeName, other.fullTypeName); } + /** + * Appends to writer + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append(fullTypeName); return writer; } + /** + * Gets the return type + * @return Return type + */ @Override public GraphTargetItem returnType() { return this; } + + /** + * Checks whether this function has a return value + * @return True if has a return value + */ @Override public boolean hasReturnValue() { return true; } + /** + * Returns a string representation of this function + * @return String representation + */ @Override public String toString() { return "Function[" + fullTypeName + "]"; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java index 16af16a25..35177b960 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -22,16 +22,19 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; + import java.util.ArrayList; import java.util.List; import java.util.Objects; /** - * + * Type item. * @author JPEXS */ public class TypeItem extends GraphTargetItem { + //Basic type items + public static TypeItem BOOLEAN = new TypeItem(DottedChain.BOOLEAN); public static TypeItem STRING = new TypeItem(DottedChain.STRING); @@ -50,34 +53,66 @@ public class TypeItem extends GraphTargetItem { public static TypeItem UNKNOWN = new TypeItem("--UNKNOWN--"); + /** + * Full type name + */ public final DottedChain fullTypeName; - public boolean printRaw = false; - + /** + * Namespace + */ public String ns; + /** + * Constructs a new instance of TypeItem + * @param s Full type name + */ public TypeItem(String s) { this(s, null); } + /** + * Constructs a new instance of TypeItem + * @param s Full type name + * @param ns Namespace + */ public TypeItem(String s, String ns) { this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s), ns); } + /** + * Constructs a new instance of TypeItem + * @param fullTypeName Full type name + */ public TypeItem(DottedChain fullTypeName) { this(fullTypeName, (String) null); } + /** + * Constructs a new instance of TypeItem + * @param fullTypeName Full type name + * @param ns Namespace + */ public TypeItem(DottedChain fullTypeName, String ns) { this(fullTypeName, new ArrayList<>(), ns); } + /** + * Constructs a new instance of TypeItem + * @param fullTypeName Full type name + * @param subtypes Subtypes + * @param ns Namespace + */ public TypeItem(DottedChain fullTypeName, List subtypes, String ns) { super(null, null, NOPRECEDENCE); this.fullTypeName = fullTypeName; this.ns = ns; } + /** + * Hash code + * @return Hash code + */ @Override public int hashCode() { int hash = 5; @@ -86,6 +121,11 @@ public class TypeItem extends GraphTargetItem { return hash; } + /** + * Equals + * @param obj Object to compare + * @return True if equal + */ @Override public boolean equals(Object obj) { if (this == obj) { @@ -104,6 +144,13 @@ public class TypeItem extends GraphTargetItem { return Objects.equals(this.fullTypeName, other.fullTypeName); } + /** + * Appends to writer + * @param writer Writer + * @param localData Local data + * @return Writer + * @throws InterruptedException + */ @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { boolean as3 = localData.constantsAvm2 != null; @@ -117,21 +164,40 @@ public class TypeItem extends GraphTargetItem { return writer; } + /** + * Gets the return type + * @return Return type + */ @Override public GraphTargetItem returnType() { return this; } + /** + * Checks whether this function has a return value + * @return True if has a return value + */ @Override public boolean hasReturnValue() { return true; } + /** + * Returns a string representation of this function + * @return String representation + */ @Override public String toString() { return fullTypeName.toRawString(); } + /** + * Converts this item to low-level source code. + * @param localData Local data + * @param generator Source generator + * @return List of graph source items + * @throws CompilationException + */ @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { return generator.generate(localData, this); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/package-info.java new file mode 100644 index 000000000..341ad45ca --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/package-info.java @@ -0,0 +1,4 @@ +/** + * High-level model of the graph. + */ +package com.jpexs.decompiler.graph.model; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/package-info.java new file mode 100644 index 000000000..c956d64d1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/package-info.java @@ -0,0 +1,4 @@ +/** + * Control flow graph and its decompiling. + */ +package com.jpexs.decompiler.graph; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/package-info.java new file mode 100644 index 000000000..b1a1b1db4 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/precontinues/package-info.java @@ -0,0 +1,4 @@ +/** + * Detection of precontinues in loops. + */ +package com.jpexs.decompiler.graph.precontinues; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/package-info.java new file mode 100644 index 000000000..100816b1d --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/package-info.java @@ -0,0 +1,4 @@ +/** + * Helpers. + */ +package com.jpexs.helpers; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/plugin/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/plugin/package-info.java new file mode 100644 index 000000000..fc3607693 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/plugin/package-info.java @@ -0,0 +1,4 @@ +/** + * Plugin support. + */ +package com.jpexs.helpers.plugin; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/properties/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/properties/package-info.java new file mode 100644 index 000000000..5c6a92510 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/properties/package-info.java @@ -0,0 +1,4 @@ +/** + * Working with properties files. + */ +package com.jpexs.helpers.properties; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/resource/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/resource/package-info.java new file mode 100644 index 000000000..64a858e5b --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/resource/package-info.java @@ -0,0 +1,4 @@ +/** + * Resources. + */ +package com.jpexs.helpers.resource; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/sound/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/sound/package-info.java new file mode 100644 index 000000000..933cf6ca2 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/sound/package-info.java @@ -0,0 +1,4 @@ +/** + * Sound helpers. + */ +package com.jpexs.helpers.sound; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/stat/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/stat/package-info.java new file mode 100644 index 000000000..265a75ec1 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/stat/package-info.java @@ -0,0 +1,4 @@ +/** + * Collecting statistics. + */ +package com.jpexs.helpers.stat; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/streams/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/streams/package-info.java new file mode 100644 index 000000000..5607476a7 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/streams/package-info.java @@ -0,0 +1,4 @@ +/** + * Stream helpets. + */ +package com.jpexs.helpers.streams; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/charset/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/charset/package-info.java new file mode 100644 index 000000000..7c15c63f0 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/charset/package-info.java @@ -0,0 +1,4 @@ +/** + * Charset helpers. + */ +package com.jpexs.helpers.utf8.charset; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/package-info.java new file mode 100644 index 000000000..e1ee028d0 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/package-info.java @@ -0,0 +1,4 @@ +/** + * UTF-8 encoding and decoding helpers. + */ +package com.jpexs.helpers.utf8; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/video/package-info.java b/libsrc/ffdec_lib/src/com/jpexs/video/package-info.java new file mode 100644 index 000000000..0d8833e6c --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/video/package-info.java @@ -0,0 +1,4 @@ +/** + * Video playback. + */ +package com.jpexs.video; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/sun/jna/platform/win32/package-info.java b/libsrc/ffdec_lib/src/com/sun/jna/platform/win32/package-info.java new file mode 100644 index 000000000..96043c7b5 --- /dev/null +++ b/libsrc/ffdec_lib/src/com/sun/jna/platform/win32/package-info.java @@ -0,0 +1,4 @@ +/** + * Windows API functions and structures accessible via JNA. + */ +package com.sun.jna.platform.win32; \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/natorder/package-info.java b/libsrc/ffdec_lib/src/natorder/package-info.java new file mode 100644 index 000000000..8a34937bb --- /dev/null +++ b/libsrc/ffdec_lib/src/natorder/package-info.java @@ -0,0 +1,4 @@ +/** + * Natural sorting of strings. + */ +package natorder; \ No newline at end of file