mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 21:08:08 +00:00
merge of honfika changes
This commit is contained in:
@@ -46,7 +46,6 @@
|
||||
<property name="INSTALLERCONFIG" value="${basedir}/installer.cfg"/>
|
||||
<property name="INSTALLERPROJECT" value="${basedir}/installer.iss"/>
|
||||
<property name="EXECONFIG" value="${basedir}/build_exe.xml"/>
|
||||
|
||||
<property name="RUNPARAMS" value="" />
|
||||
<property name="RUNPARAMS" value="d:\swf\327\100000.swf" />
|
||||
<import file="build_common.xml"/>
|
||||
</project>
|
||||
|
||||
@@ -273,6 +273,8 @@ Please follow instructions on http://www.free-decompiler.com/flash/translations.
|
||||
<target name="run" depends="build">
|
||||
<java jar="${DISTRIBUTIONDIR}/${JARFILENAME}.jar" fork="true">
|
||||
<jvmarg value="-Xmx${MAXHEAPSIZE}m"/>
|
||||
<jvmarg value="-XX:MinHeapFreeRatio=0"/>
|
||||
<jvmarg value="-XX:MaxHeapFreeRatio=0"/>
|
||||
<arg line="${RUNPARAMS}" />
|
||||
</java>
|
||||
</target>
|
||||
|
||||
@@ -22,9 +22,12 @@ package com.jpexs.decompiler.flash;
|
||||
*/
|
||||
public interface AbortRetryIgnoreHandler {
|
||||
|
||||
public static int UNDEFINED = -1;
|
||||
public static int ABORT = 0;
|
||||
public static int RETRY = 1;
|
||||
public static int IGNORE = 2;
|
||||
|
||||
public int handle(Throwable thrown);
|
||||
|
||||
public AbortRetryIgnoreHandler getNewInstance();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,15 @@ public class Configuration {
|
||||
* Limit of code subs (for obfuscated code)
|
||||
*/
|
||||
public static final int SUBLIMITER = 500;
|
||||
//using parameter names in decompiling may cause problems because oficial programs like Flash CS 5.5 inserts wrong parameter names indices
|
||||
/**
|
||||
* Decompilation timeout in seconds
|
||||
*/
|
||||
public static final int DECOMPILATION_TIMEOUT = 30 * 60;
|
||||
/**
|
||||
* Decompilation timeout for a single method in AS3 or single action in AS1/2 in seconds
|
||||
*/
|
||||
public static final int DECOMPILATION_TIMEOUT_SINGLE_METHOD = 5;
|
||||
//using parameter names in decompiling may cause problems because official programs like Flash CS 5.5 inserts wrong parameter names indices
|
||||
public static final boolean PARAM_NAMES_ENABLE = false;
|
||||
private static HashMap<String, Object> config = new HashMap<>();
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2013 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ConsoleAbortRetryIgnoreHandler implements AbortRetryIgnoreHandler {
|
||||
int errorCount = 0;
|
||||
int errorMode;
|
||||
int retryCount;
|
||||
|
||||
public ConsoleAbortRetryIgnoreHandler(int errorMode, int retryCount) {
|
||||
this.errorMode = errorMode;
|
||||
this.retryCount = retryCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int handle(Throwable thrown) {
|
||||
if (errorMode != AbortRetryIgnoreHandler.UNDEFINED){
|
||||
int result = errorMode;
|
||||
|
||||
if (errorMode == AbortRetryIgnoreHandler.RETRY && errorCount < retryCount) {
|
||||
errorCount++;
|
||||
}
|
||||
else {
|
||||
result = AbortRetryIgnoreHandler.IGNORE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.println("Error occured: " + thrown.getLocalizedMessage());
|
||||
String n = null;
|
||||
do {
|
||||
System.out.print("Select action: (A)bort, (R)Retry, (I)Ignore:");
|
||||
n = sc.nextLine();
|
||||
switch (n.toLowerCase()) {
|
||||
case "a":
|
||||
return AbortRetryIgnoreHandler.ABORT;
|
||||
case "r":
|
||||
return AbortRetryIgnoreHandler.RETRY;
|
||||
case "i":
|
||||
return AbortRetryIgnoreHandler.IGNORE;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbortRetryIgnoreHandler getNewInstance() {
|
||||
return new ConsoleAbortRetryIgnoreHandler(errorMode, retryCount);
|
||||
}
|
||||
}
|
||||
@@ -591,12 +591,14 @@ public class SWF {
|
||||
outdir += File.separator;
|
||||
}
|
||||
outdir += "scripts" + File.separator;
|
||||
ret.addAll(TagNode.exportNodeAS(tags, handler, list, outdir, isPcode, evl));
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
int totalCount = TagNode.getTagCountRecursive(list);
|
||||
ret.addAll(TagNode.exportNodeAS(tags, handler, list, outdir, isPcode, cnt, totalCount, evl));
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<File> exportActionScript3(AbortRetryIgnoreHandler handler, String outdir, boolean isPcode, boolean parallel) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(20);
|
||||
ExecutorService executor = Executors.newFixedThreadPool(parallel ? 20 : 1);
|
||||
List<Future<File>> futureResults = new ArrayList<>();
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
List<ABCContainerTag> abcTags = new ArrayList<>();
|
||||
@@ -622,9 +624,9 @@ public class SWF {
|
||||
|
||||
try {
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(30, TimeUnit.MINUTES);
|
||||
executor.awaitTermination(Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, "30 minutes ActionScript export limit reached", ex);
|
||||
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,9 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class TagNode {
|
||||
|
||||
@@ -231,11 +234,30 @@ public class TagNode {
|
||||
}
|
||||
}
|
||||
|
||||
public static int getTagCountRecursive(List<TagNode> nodeList) {
|
||||
int count = 0;
|
||||
|
||||
for (TagNode node : nodeList) {
|
||||
if (node.subItems.isEmpty()) {
|
||||
if ((node.tag instanceof ASMSource) && (node.export)) {
|
||||
count += 1;
|
||||
}
|
||||
} else {
|
||||
count += getTagCountRecursive(node.subItems);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public static List<File> exportNodeAS(List<Tag> allTags, AbortRetryIgnoreHandler handler, List<TagNode> nodeList, String outdir, boolean isPcode) throws IOException {
|
||||
return exportNodeAS(allTags, handler, nodeList, outdir, isPcode, null);
|
||||
AtomicInteger cnt = new AtomicInteger(1);
|
||||
int totalCount = TagNode.getTagCountRecursive(nodeList);
|
||||
return exportNodeAS(allTags, handler, nodeList, outdir, isPcode, cnt, totalCount, null);
|
||||
}
|
||||
|
||||
public static List<File> exportNodeAS(List<Tag> allTags, AbortRetryIgnoreHandler handler, List<TagNode> nodeList, String outdir, boolean isPcode, EventListener ev) throws IOException {
|
||||
public static List<File> exportNodeAS(List<Tag> allTags, AbortRetryIgnoreHandler handler, List<TagNode> nodeList, String outdir, boolean isPcode, AtomicInteger index, int count, EventListener ev) throws IOException {
|
||||
File dir = new File(outdir);
|
||||
List<File> ret = new ArrayList<>();
|
||||
if (!outdir.endsWith(File.separator)) {
|
||||
@@ -269,11 +291,10 @@ public class TagNode {
|
||||
do {
|
||||
retry = false;
|
||||
try {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
String f = outdir + name + ".as";
|
||||
File file = new File(f);
|
||||
if (ev != null) {
|
||||
ev.handleEvent("export", "Exporting " + f + " ...");
|
||||
}
|
||||
String res;
|
||||
ASMSource asm = ((ASMSource) node.tag);
|
||||
if (isPcode) {
|
||||
@@ -286,10 +307,19 @@ public class TagNode {
|
||||
try (FileOutputStream fos = new FileOutputStream(f)) {
|
||||
fos.write(res.getBytes("utf-8"));
|
||||
}
|
||||
|
||||
long stopTime = System.currentTimeMillis();
|
||||
|
||||
if (ev != null) {
|
||||
long time = stopTime - startTime;
|
||||
ev.handleEvent("export", "Exported " + index.getAndIncrement() + "/" + count + " " + f + ", " + Helper.formatTimeSec(time));
|
||||
}
|
||||
|
||||
ret.add(file);
|
||||
} catch (Exception ex) {
|
||||
} catch (Exception | OutOfMemoryError | StackOverflowError ex) {
|
||||
Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
|
||||
if (handler != null) {
|
||||
int action = handler.handle(ex);
|
||||
int action = handler.getNewInstance().handle(ex);
|
||||
switch (action) {
|
||||
case AbortRetryIgnoreHandler.ABORT:
|
||||
throw ex;
|
||||
@@ -305,7 +335,7 @@ public class TagNode {
|
||||
} while (retry);
|
||||
}
|
||||
} else {
|
||||
ret.addAll(exportNodeAS(allTags, handler, node.subItems, outdir + name, isPcode, ev));
|
||||
ret.addAll(exportNodeAS(allTags, handler, node.subItems, outdir + name, isPcode, index, count, ev));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,12 +19,6 @@ package com.jpexs.decompiler.flash.abc.avm2.model.operations;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaType;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.BOOLEAN;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.NULL;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.NUMBER;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.OBJECT;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.STRING;
|
||||
import static com.jpexs.decompiler.flash.ecma.EcmaType.UNDEFINED;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.model.UnaryOpItem;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
@@ -31,6 +32,10 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -103,7 +108,7 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toString(String path, boolean pcode, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<GraphTargetItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
|
||||
public String toString(final String path, boolean pcode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final ConstantPool constants, final MethodInfo method_info[], final Stack<GraphTargetItem> scopeStack, final boolean isStaticInitializer, final boolean hilight, final List<String> fullyQualifiedNames, final Traits initTraits) {
|
||||
if (debugMode) {
|
||||
System.err.println("Decompiling " + path);
|
||||
}
|
||||
@@ -118,30 +123,46 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
if (pcode) {
|
||||
s += code.toASMSource(constants, this, false);
|
||||
} else {
|
||||
AVM2Code deobfuscated = null;
|
||||
MethodBody b = (MethodBody) Helper.deepCopy(this);
|
||||
deobfuscated = b.code;
|
||||
deobfuscated.markMappedOffsets();
|
||||
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true)) {
|
||||
try {
|
||||
deobfuscated.removeTraps(constants, b, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} catch (Exception | StackOverflowError ex) {
|
||||
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps in " + path, ex);
|
||||
}
|
||||
}
|
||||
//deobfuscated.restoreControlFlow(constants, b);
|
||||
//try {
|
||||
s += deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<Integer, Integer>(), deobfuscated.visitCode(b));
|
||||
s = s.trim();
|
||||
if (s.equals("")) {
|
||||
s = " ";
|
||||
}
|
||||
if (hilight) {
|
||||
s = Highlighting.hilighMethod(s, this.method_info);
|
||||
try {
|
||||
s += Helper.timedCall(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, scopeStack, isStaticInitializer, hilight, fullyQualifiedNames, initTraits);
|
||||
}
|
||||
}, Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
|
||||
s += "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD) + ") was reached\r\n */";
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<GraphTargetItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
|
||||
AVM2Code deobfuscated = null;
|
||||
MethodBody b = (MethodBody) Helper.deepCopy(this);
|
||||
deobfuscated = b.code;
|
||||
deobfuscated.markMappedOffsets();
|
||||
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true)) {
|
||||
try {
|
||||
deobfuscated.removeTraps(constants, b, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} catch (Exception | StackOverflowError ex) {
|
||||
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps in " + path, ex);
|
||||
}
|
||||
}
|
||||
//deobfuscated.restoreControlFlow(constants, b);
|
||||
//try {
|
||||
String s = deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<Integer, Integer>(), deobfuscated.visitCode(b));
|
||||
s = s.trim();
|
||||
if (s.equals("")) {
|
||||
s = " ";
|
||||
}
|
||||
if (hilight) {
|
||||
s = Highlighting.hilighMethod(s, this.method_info);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.Configuration;
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -49,6 +50,7 @@ import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -62,6 +64,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -408,7 +413,7 @@ public class Action implements GraphSourceItem {
|
||||
* @param path
|
||||
* @return ASM source as String
|
||||
*/
|
||||
public static String actionsToString(List<DisassemblyListener> listeners, long address, List<Action> list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos, String path) {
|
||||
private static String actionsToString(List<DisassemblyListener> listeners, long address, List<Action> list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos, String path) {
|
||||
long offset;
|
||||
if (importantOffsets == null) {
|
||||
//setActionsAddresses(list, 0, version);
|
||||
@@ -434,6 +439,10 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
pos++;
|
||||
if (hex) {
|
||||
if (lastPush) {
|
||||
ret.append("\r\n");
|
||||
lastPush = false;
|
||||
}
|
||||
ret.append("<ffdec:hex>");/* +"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/;
|
||||
ret.append(Helper.bytesToHexString(a.getBytes(version)));
|
||||
ret.append("</ffdec:hex>\r\n");
|
||||
@@ -707,15 +716,22 @@ public class Action implements GraphSourceItem {
|
||||
* @param path
|
||||
* @return String with Source code
|
||||
*/
|
||||
public static String actionsToSource(List<Action> actions, int version, String path) {
|
||||
public static String actionsToSource(final List<Action> actions, final int version, final String path) {
|
||||
try {
|
||||
//List<ActionItem> tree = actionsToTree(new HashMap<Integer, String>(), actions, version);
|
||||
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
|
||||
return Helper.timedCall(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
//List<ActionItem> tree = actionsToTree(new HashMap<Integer, String>(), actions, version);
|
||||
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
|
||||
|
||||
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
|
||||
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
|
||||
|
||||
|
||||
return Graph.graphToString(tree);
|
||||
return Graph.graphToString(tree);
|
||||
}
|
||||
}, Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD, TimeUnit.SECONDS);
|
||||
} catch (TimeoutException ex) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
|
||||
return "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD) + ") was reached\r\n */";
|
||||
} catch (Exception | OutOfMemoryError | StackOverflowError ex2) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex2);
|
||||
if (ex2 instanceof OutOfMemoryError) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.jpexs.decompiler.flash.action.parser.script.ActionSourceGenerator;
|
||||
import com.jpexs.decompiler.flash.action.swf4.ActionGetURL2;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import static com.jpexs.decompiler.graph.GraphTargetItem.PRECEDENCE_PRIMARY;
|
||||
import com.jpexs.decompiler.graph.SourceGenerator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.Configuration;
|
||||
import com.jpexs.decompiler.flash.ConsoleAbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.EventListener;
|
||||
import com.jpexs.decompiler.flash.PercentListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -529,6 +530,8 @@ public class Main {
|
||||
System.out.println(" Values are boolean, you can use 0/1, true/false or yes/no.");
|
||||
System.out.println(" If no other parameters passed, configuration is saved. Otherwise it is used only once.");
|
||||
System.out.println(" DO NOT PUT space between comma (,) and next value.");
|
||||
System.out.println(" 9) -onerror (abort|retryN|ignore)");
|
||||
System.out.println(" ...error handling mode. \"abort\" stops the exporting, \"retry\" tries the exporting N times, \"ignore\" ignores the current file");
|
||||
System.out.println();
|
||||
System.out.println("Examples:");
|
||||
System.out.println("java -jar ffdec.jar myfile.swf");
|
||||
@@ -540,6 +543,8 @@ public class Main {
|
||||
System.out.println("java -jar ffdec.jar -dumpSWF myfile.swf");
|
||||
System.out.println("java -jar ffdec.jar -compress myfile.swf myfiledec.swf");
|
||||
System.out.println("java -jar ffdec.jar -decompress myfiledec.swf myfile.swf");
|
||||
System.out.println("java -jar ffdec.jar -onerror ignore -export as \"C:\\decompiled\\\" myfile.swf");
|
||||
System.out.println("java -jar ffdec.jar -onerror retry 5 -export as \"C:\\decompiled\\\" myfile.swf");
|
||||
System.out.println("java -jar ffdec.jar -config autoDeobfuscate=1,parallelSpeedUp=0 -export as \"C:\\decompiled\\\" myfile.swf");
|
||||
System.out.println("");
|
||||
System.out.println("Instead of \"java -jar ffdec.jar\" you can use ffdec.bat on Windows, ffdec.sh on Linux/MacOs");
|
||||
@@ -690,61 +695,100 @@ public class Main {
|
||||
} else {
|
||||
Cache.setStorageType(Cache.STORAGE_MEMORY);
|
||||
}
|
||||
|
||||
int errorMode = AbortRetryIgnoreHandler.UNDEFINED;
|
||||
int retryCount = 0;
|
||||
|
||||
if (args.length < pos + 1) {
|
||||
autoCheckForUpdates();
|
||||
offerAssociation();
|
||||
showModeFrame();
|
||||
} else {
|
||||
if (args[pos].equals("-config")) {
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
System.err.println("Config values expected");
|
||||
badArguments();
|
||||
}
|
||||
String cfgStr = args[pos];
|
||||
String cfgs[];
|
||||
if (cfgStr.contains(",")) {
|
||||
cfgs = cfgStr.split(",");
|
||||
} else {
|
||||
cfgs = new String[]{cfgStr};
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (String c : cfgs) {
|
||||
String cp[];
|
||||
if (c.contains("=")) {
|
||||
cp = c.split("=");
|
||||
boolean parameterProcessed = true;
|
||||
while (parameterProcessed) {
|
||||
parameterProcessed = false;
|
||||
if (args[pos].equals("-config")) {
|
||||
parameterProcessed = true;
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
System.err.println("Config values expected");
|
||||
badArguments();
|
||||
}
|
||||
String cfgStr = args[pos];
|
||||
String cfgs[];
|
||||
if (cfgStr.contains(",")) {
|
||||
cfgs = cfgStr.split(",");
|
||||
} else {
|
||||
cp = new String[]{c, "1"};
|
||||
cfgs = new String[]{cfgStr};
|
||||
}
|
||||
String key = cp[0];
|
||||
String value = cp[1];
|
||||
if (key.toLowerCase().equals("paralelSpeedUp".toLowerCase())) {
|
||||
key = "parallelSpeedUp";
|
||||
}
|
||||
for (String bk : commandlineConfigBoolean) {
|
||||
if (key.toLowerCase().equals(bk.toLowerCase())) {
|
||||
Boolean bValue = null;
|
||||
if (value.equals("0") || value.toLowerCase().equals("false") || value.toLowerCase().equals("no") || value.toLowerCase().equals("off")) {
|
||||
bValue = false;
|
||||
}
|
||||
if (value.equals("1") || value.toLowerCase().equals("true") || value.toLowerCase().equals("yes") || value.toLowerCase().equals("on")) {
|
||||
bValue = true;
|
||||
}
|
||||
if (bValue != null) {
|
||||
System.out.println("Config " + bk + " set to " + bValue);
|
||||
Configuration.setConfig(bk, bValue);
|
||||
|
||||
for (String c : cfgs) {
|
||||
String cp[];
|
||||
if (c.contains("=")) {
|
||||
cp = c.split("=");
|
||||
} else {
|
||||
cp = new String[]{c, "1"};
|
||||
}
|
||||
String key = cp[0];
|
||||
String value = cp[1];
|
||||
if (key.toLowerCase().equals("paralelSpeedUp".toLowerCase())) {
|
||||
key = "parallelSpeedUp";
|
||||
}
|
||||
for (String bk : commandlineConfigBoolean) {
|
||||
if (key.toLowerCase().equals(bk.toLowerCase())) {
|
||||
Boolean bValue = null;
|
||||
if (value.equals("0") || value.toLowerCase().equals("false") || value.toLowerCase().equals("no") || value.toLowerCase().equals("off")) {
|
||||
bValue = false;
|
||||
}
|
||||
if (value.equals("1") || value.toLowerCase().equals("true") || value.toLowerCase().equals("yes") || value.toLowerCase().equals("on")) {
|
||||
bValue = true;
|
||||
}
|
||||
if (bValue != null) {
|
||||
System.out.println("Config " + bk + " set to " + bValue);
|
||||
Configuration.setConfig(bk, bValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
saveConfig();
|
||||
System.out.println("Configuration saved");
|
||||
return;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
saveConfig();
|
||||
System.out.println("Configuration saved");
|
||||
return;
|
||||
if (args[pos].equals("-onerror")) {
|
||||
parameterProcessed = true;
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
System.err.println("onerror parameter expected");
|
||||
badArguments();
|
||||
}
|
||||
String errorModeParameter = args[pos];
|
||||
switch (errorModeParameter) {
|
||||
case "abort":
|
||||
errorMode = AbortRetryIgnoreHandler.ABORT;
|
||||
break;
|
||||
case "retry":
|
||||
errorMode = AbortRetryIgnoreHandler.RETRY;
|
||||
pos++;
|
||||
if (args.length <= pos) {
|
||||
System.err.println("onerror retry count parameter expected");
|
||||
badArguments();
|
||||
}
|
||||
|
||||
try {
|
||||
retryCount = Integer.parseInt(args[pos]);
|
||||
} catch (NumberFormatException nex) {
|
||||
System.err.println("Bad retry count number");
|
||||
}
|
||||
break;
|
||||
case "ignore":
|
||||
errorMode = AbortRetryIgnoreHandler.IGNORE;
|
||||
break;
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
if (args[pos].equals("-removefromcontextmenu")) {
|
||||
@@ -793,26 +837,7 @@ public class Main {
|
||||
"xfl"
|
||||
};
|
||||
|
||||
AbortRetryIgnoreHandler handler = new AbortRetryIgnoreHandler() {
|
||||
@Override
|
||||
public int handle(Throwable thrown) {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
System.out.println("Error occured: " + thrown.getLocalizedMessage());
|
||||
String n = null;
|
||||
do {
|
||||
System.out.print("Select action: (A)bort, (R)Retry, (I)Ignore:");
|
||||
n = sc.nextLine();
|
||||
switch (n.toLowerCase()) {
|
||||
case "a":
|
||||
return AbortRetryIgnoreHandler.ABORT;
|
||||
case "r":
|
||||
return AbortRetryIgnoreHandler.RETRY;
|
||||
case "i":
|
||||
return AbortRetryIgnoreHandler.IGNORE;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
};
|
||||
AbortRetryIgnoreHandler handler = new ConsoleAbortRetryIgnoreHandler(errorMode, retryCount);
|
||||
String exportFormat = args[pos + 1].toLowerCase();
|
||||
if (!Arrays.asList(validExportFormats).contains(exportFormat)) {
|
||||
System.err.println("Invalid export format:" + exportFormat);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.Configuration;
|
||||
import com.jpexs.decompiler.flash.ConsoleAbortRetryIgnoreHandler;
|
||||
import com.jpexs.decompiler.flash.FrameNode;
|
||||
import com.jpexs.decompiler.flash.PackageNode;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -288,6 +289,12 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
return View.showOptionDialog(null, translate("error.occured").replace("%error%", thrown.getLocalizedMessage()), translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbortRetryIgnoreHandler getNewInstance() {
|
||||
// there are no non-static field in this class, so return the original instance
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
public void setPercent(int percent) {
|
||||
@@ -1404,6 +1411,12 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
@Override
|
||||
public void run() {
|
||||
if (record.getLevel() == Level.SEVERE) {
|
||||
if (errorNotificationButton == null) {
|
||||
// todo: honfika
|
||||
// why null?
|
||||
return;
|
||||
}
|
||||
|
||||
errorNotificationButton.setIcon(View.getIcon("error16"));
|
||||
errorNotificationButton.setToolTipText(translate("errors.present"));
|
||||
if (timer != null) {
|
||||
|
||||
@@ -168,7 +168,7 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
private void cacheScript(ASMSource src) {
|
||||
if (!cache.contains(src)) {
|
||||
List<Action> as = src.getActions(SWF.DEFAULT_VERSION);
|
||||
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/);
|
||||
String s = Action.actionsToSource(as, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/);
|
||||
List<Highlighting> hilights = Highlighting.getInstrHighlights(s);
|
||||
String srcNoHex = Highlighting.stripHilights(s);
|
||||
cache.put(src, new CachedScript(srcNoHex, hilights));
|
||||
@@ -567,6 +567,10 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
}
|
||||
|
||||
public void setDecompiledEditMode(boolean val) {
|
||||
if (lastASM == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String pref = lastASM.getActionSourcePrefix();
|
||||
int lastPos = decompiledEditor.getCaretPosition();
|
||||
int lastLine = decompiledEditor.getLine();
|
||||
|
||||
@@ -34,6 +34,13 @@ import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -46,6 +53,8 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class Helper {
|
||||
|
||||
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
|
||||
|
||||
/**
|
||||
* Converts array of int values to string
|
||||
*
|
||||
@@ -504,8 +513,41 @@ public class Helper {
|
||||
timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3);
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
public static void freeMem(){
|
||||
Cache.clearAll();
|
||||
System.gc();
|
||||
}
|
||||
public static String formatTimeToText(int timeS) {
|
||||
long timeM = timeS / 60;
|
||||
timeS = timeS % 60;
|
||||
long timeH = timeM / 60;
|
||||
timeM = timeM % 60;
|
||||
|
||||
String timeStr = "";
|
||||
if (timeH > 0) {
|
||||
timeStr += timeH + (timeH > 1 ? " hours" : " hour");
|
||||
}
|
||||
if (timeM > 0) {
|
||||
if (timeStr.length() > 0) {
|
||||
timeStr += " and ";
|
||||
}
|
||||
timeStr += timeM + (timeM > 1 ? " minutes" : " minute");
|
||||
}
|
||||
if (timeS > 0) {
|
||||
if (timeStr.length() > 0) {
|
||||
timeStr += " and ";
|
||||
}
|
||||
timeStr += timeS + (timeS > 1 ? " seconds" : " second");
|
||||
}
|
||||
|
||||
// (currently) used only in log, so no localization is required
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
public static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
FutureTask<T> task = new FutureTask<T>(c);
|
||||
THREAD_POOL.execute(task);
|
||||
return task.get(timeout, timeUnit);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user