From 0579ac38cb45d42eea66c443c16820b0f2d46993 Mon Sep 17 00:00:00 2001 From: Honfika Date: Tue, 5 Nov 2013 17:59:35 +0100 Subject: [PATCH] export: write to file directly, cancelable decompilation (cancel button in the status panel) --- .../jpexs/decompiler/flash/Configuration.java | 4 + trunk/src/com/jpexs/decompiler/flash/SWF.java | 25 ++-- .../decompiler/flash/SWFInputStream.java | 2 +- .../com/jpexs/decompiler/flash/TagNode.java | 74 +++++----- .../com/jpexs/decompiler/flash/abc/ABC.java | 3 - .../decompiler/flash/abc/ScriptPack.java | 94 ++++++++++--- .../flash/abc/avm2/model/AVM2Item.java | 1 - .../abc/avm2/model/NewFunctionAVM2Item.java | 2 +- .../model/clauses/DeclarationAVM2Item.java | 1 - .../flash/abc/types/MethodBody.java | 23 +-- .../flash/abc/types/traits/Trait.java | 37 +---- .../flash/abc/types/traits/TraitClass.java | 35 ++--- .../flash/abc/types/traits/TraitFunction.java | 9 +- .../types/traits/TraitMethodGetterSetter.java | 11 +- .../abc/types/traits/TraitSlotConst.java | 3 +- .../flash/abc/types/traits/Traits.java | 21 ++- .../abc/usages/ConstVarMultinameUsage.java | 8 +- .../abc/usages/MethodMultinameUsage.java | 8 +- .../jpexs/decompiler/flash/action/Action.java | 9 +- .../flash/action/ActionListReader.java | 4 +- .../flash/gui/GuiAbortRetryIgnoreHandler.java | 42 ++++++ .../com/jpexs/decompiler/flash/gui/Main.java | 77 ++++++---- .../jpexs/decompiler/flash/gui/MainFrame.java | 117 ++++++++++------ .../decompiler/flash/gui/SWFPreviwPanel.java | 5 +- .../decompiler/flash/gui/abc/ABCPanel.java | 26 ++-- .../flash/gui/abc/ClassesListTree.java | 3 +- .../flash/gui/abc/ClassesListTreeModel.java | 4 +- .../flash/gui/abc/DecompiledEditorPane.java | 30 ++-- .../decompiler/flash/gui/abc/DetailPanel.java | 18 +-- .../gui/abc/DialogMissingSymbolHandler.java | 10 +- .../flash/gui/abc/MethodCodePanel.java | 8 +- .../gui/abc/SlotConstTraitDetailPanel.java | 6 +- .../flash/gui/abc/TraitsListItem.java | 5 +- .../flash/gui/action/ActionPanel.java | 100 ++++++++----- .../flash/gui/locales/MainFrame.properties | 2 + .../flash/gui/locales/MainFrame_hu.properties | 4 +- .../flash/helpers/FileTextWriter.java | 132 ++++++++++++++++++ .../flash/helpers/GraphTextWriter.java | 25 ++-- .../flash/helpers/HilightedTextWriter.java | 45 +----- .../decompiler/flash/helpers/NulWriter.java | 49 +++++++ .../decompiler/flash/xfl/XFLConverter.java | 4 +- trunk/src/com/jpexs/helpers/AsyncResult.java | 34 +++++ trunk/src/com/jpexs/helpers/Callback.java | 27 ++++ trunk/src/com/jpexs/helpers/Helper.java | 37 ++++- .../flash/ActionScript2AssemblerTest.java | 2 +- .../flash/ActionScript2DeobfuscatorTest.java | 2 +- .../decompiler/flash/ActionScript2Test.java | 2 +- .../flash/generators/AS2Generator.java | 2 +- 48 files changed, 803 insertions(+), 389 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/GuiAbortRetryIgnoreHandler.java create mode 100644 trunk/src/com/jpexs/decompiler/flash/helpers/FileTextWriter.java create mode 100644 trunk/src/com/jpexs/helpers/AsyncResult.java create mode 100644 trunk/src/com/jpexs/helpers/Callback.java diff --git a/trunk/src/com/jpexs/decompiler/flash/Configuration.java b/trunk/src/com/jpexs/decompiler/flash/Configuration.java index c815b0872..dac18b5fc 100644 --- a/trunk/src/com/jpexs/decompiler/flash/Configuration.java +++ b/trunk/src/com/jpexs/decompiler/flash/Configuration.java @@ -57,6 +57,10 @@ public class Configuration { * Decompilation timeout in seconds */ public static final int DECOMPILATION_TIMEOUT = 30 * 60; + /** + * Decompilation timeout in seconds for a single file + */ + public static final int DECOMPILATION_TIMEOUT_FILE = 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 config = new HashMap<>(); diff --git a/trunk/src/com/jpexs/decompiler/flash/SWF.java b/trunk/src/com/jpexs/decompiler/flash/SWF.java index 0502b6e90..9816c25e7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWF.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWF.java @@ -552,8 +552,10 @@ public class SWF { cnt = "script " + (i + 1) + "/" + abc.script_info.length + " "; } String exStr = "Exporting " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ..."; - informListeners("export", exStr); + informListeners("exporting", exStr); scr.export(outdir, abcTags, exportMode, parallel); + exStr = "Exported " + "tag " + (i + 1) + "/" + abcTags.size() + " " + cnt + scr.getPath() + " ..."; + informListeners("exported", exStr); return true; } } @@ -625,10 +627,15 @@ public class SWF { stopTime = System.currentTimeMillis(); } }; + int currentIndex = index.getAndIncrement(); + synchronized (ABC.class) { + long time = stopTime - startTime; + informListeners("exporting", "Exporting script " + currentIndex + "/" + count + " " + path); + } new RetryTask(rio, handler).run(); synchronized (ABC.class) { long time = stopTime - startTime; - informListeners("export", "Exported script " + index.getAndIncrement() + "/" + count + " " + path + ", " + Helper.formatTimeSec(time)); + informListeners("exported", "Exported script " + currentIndex + "/" + count + " " + path + ", " + Helper.formatTimeSec(time)); } return null; } @@ -645,9 +652,7 @@ public class SWF { outdir += File.separator; } outdir += "scripts" + File.separator; - AtomicInteger cnt = new AtomicInteger(1); - int totalCount = TagNode.getTagCountRecursive(list); - ret.addAll(TagNode.exportNodeAS(tags, handler, list, outdir, exportMode, cnt, totalCount, evl)); + ret.addAll(TagNode.exportNodeAS(tags, handler, list, outdir, exportMode, evl)); return ret; } @@ -675,10 +680,10 @@ public class SWF { return null; } }, Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); - } catch (ExecutionException ex) { - Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, "Error during ABC export", ex); - } catch (InterruptedException | TimeoutException ex) { + } catch (TimeoutException ex) { Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex); + } catch (Exception ex) { + Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, "Error during ABC export", ex); } } else { ExecutorService executor = Executors.newFixedThreadPool(20); @@ -697,8 +702,8 @@ public class SWF { } try { - executor.shutdown(); executor.awaitTermination(Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); + executor.shutdownNow(); } catch (InterruptedException ex) { Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex); } @@ -713,7 +718,7 @@ public class SWF { final EventListener evl = new EventListener() { @Override public void handleEvent(String event, Object data) { - if (event.equals("export")) { + if (event.equals("exporting") || event.equals("exported")) { informListeners(event, data); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java index 2248b350b..f07d642a9 100644 --- a/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/trunk/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -88,7 +88,7 @@ public class SWFInputStream extends InputStream { private long percentMax; private List buffered = new ArrayList<>(); private ByteArrayOutputStream buffer; - private static boolean DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG = Configuration.getConfig("deobfuscateUsePrevTagOnly", true); + private static boolean DEOBFUSCATION_ALL_CODE_IN_PREVIOUS_TAG = Configuration.getConfig("deobfuscateUsePrevTagOnly"); public int getVersion() { return version; diff --git a/trunk/src/com/jpexs/decompiler/flash/TagNode.java b/trunk/src/com/jpexs/decompiler/flash/TagNode.java index 66681cc6a..ac3384e32 100644 --- a/trunk/src/com/jpexs/decompiler/flash/TagNode.java +++ b/trunk/src/com/jpexs/decompiler/flash/TagNode.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.action.Action; -import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.helpers.FileTextWriter; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG2Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG3Tag; import com.jpexs.decompiler.flash.tags.DefineBitsJPEG4Tag; @@ -54,6 +54,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; @@ -252,10 +256,21 @@ public class TagNode { return count; } - public static List exportNodeAS(List allTags, AbortRetryIgnoreHandler handler, List nodeList, String outdir, ExportMode exportMode) throws IOException { - AtomicInteger cnt = new AtomicInteger(1); - int totalCount = TagNode.getTagCountRecursive(nodeList); - return exportNodeAS(allTags, handler, nodeList, outdir, exportMode, cnt, totalCount, null); + public static List exportNodeAS(final List allTags, final AbortRetryIgnoreHandler handler, final List nodeList, final String outdir, final ExportMode exportMode, final EventListener ev) throws IOException { + try { + List result = Helper.timedCall(new Callable>() { + + @Override + public List call() throws Exception { + AtomicInteger cnt = new AtomicInteger(1); + int totalCount = TagNode.getTagCountRecursive(nodeList); + return exportNodeAS(allTags, handler, nodeList, outdir, exportMode, cnt, totalCount, ev); + } + }, Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS); + return result; + } catch (ExecutionException | InterruptedException | TimeoutException ex) { + } + return null; } public static List exportNodeAS(List allTags, AbortRetryIgnoreHandler handler, List nodeList, String outdir, ExportMode exportMode, AtomicInteger index, int count, EventListener ev) throws IOException { @@ -292,46 +307,41 @@ public class TagNode { do { retry = false; try { + String f = outdir + name + ".as"; + int currentIndex = index.getAndIncrement(); + if (ev != null) { + ev.handleEvent("exporting", "Exporting " + currentIndex + "/" + count + " " + f); + } + long startTime = System.currentTimeMillis(); - String f = outdir + name + ".as"; File file = new File(f); - String res; ASMSource asm = ((ASMSource) node.tag); - if (exportMode == ExportMode.HEX) { - HilightedTextWriter writer = new HilightedTextWriter(false); - asm.getActionSourcePrefix(writer); - asm.getActionBytesAsHex(writer); - asm.getActionSourceSuffix(writer); - res = writer.toString(); - } else if (exportMode != ExportMode.SOURCE) { - HilightedTextWriter writer = new HilightedTextWriter(false); - asm.getActionSourcePrefix(writer); - asm.getASMSource(SWF.DEFAULT_VERSION, exportMode, writer, null); - asm.getActionSourceSuffix(writer); - res = writer.toString(); - } else { - List as = asm.getActions(SWF.DEFAULT_VERSION); - Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); - HilightedTextWriter writer = new HilightedTextWriter(false); - asm.getActionSourcePrefix(writer); - Action.actionsToSource(as, SWF.DEFAULT_VERSION, ""/*FIXME*/, writer); - asm.getActionSourceSuffix(writer); - res = writer.toString(); - } - try (FileOutputStream fos = new FileOutputStream(f)) { - fos.write(res.getBytes("utf-8")); + try (FileTextWriter writer = new FileTextWriter(new FileOutputStream(f))) { + if (exportMode == ExportMode.HEX) { + asm.getActionSourcePrefix(writer); + asm.getActionBytesAsHex(writer); + asm.getActionSourceSuffix(writer); + } else if (exportMode != ExportMode.SOURCE) { + asm.getActionSourcePrefix(writer); + asm.getASMSource(SWF.DEFAULT_VERSION, exportMode, writer, null); + asm.getActionSourceSuffix(writer); + } else { + List as = asm.getActions(SWF.DEFAULT_VERSION); + Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION); + Action.actionsToSource(asm, as, SWF.DEFAULT_VERSION, ""/*FIXME*/, writer); + } } long stopTime = System.currentTimeMillis(); if (ev != null) { long time = stopTime - startTime; - ev.handleEvent("export", "Exported " + index.getAndIncrement() + "/" + count + " " + f + ", " + Helper.formatTimeSec(time)); + ev.handleEvent("exported", "Exported " + currentIndex + "/" + count + " " + f + ", " + Helper.formatTimeSec(time)); } ret.add(file); - } catch (Exception | OutOfMemoryError | StackOverflowError ex) { + } catch (IOException | OutOfMemoryError | StackOverflowError ex) { Logger.getLogger(TagNode.class.getName()).log(Level.SEVERE, "Decompilation error", ex); if (handler != null) { int action = handler.getNewInstance().handle(ex); diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java index 329f5b0a9..b6054b171 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -734,9 +734,6 @@ public class ABC { } } - /*public void export(String directory, ExportMode exportMode, List abcList, boolean parallel) throws IOException { - export(directory, pcode, abcList, "", parallel); - }*/ public List> getScriptPacks() { List> ret = new ArrayList<>(); for (int i = 0; i < script_info.length; i++) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 682c5d2bd..1372a67fc 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -16,9 +16,14 @@ */ package com.jpexs.decompiler.flash.abc; +import com.jpexs.decompiler.flash.Configuration; +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.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.helpers.FileTextWriter; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.helpers.Helper; @@ -27,6 +32,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +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,6 +114,67 @@ public class ScriptPack { return Helper.joinStrings(pathParts, File.separator); } + public void convert(final NulWriter writer, final List abcList, final Trait[] traits, final ExportMode exportMode, final boolean parallel) { + for (int t : traitIndices) { + Trait trait = traits[t]; + Multiname name = trait.getName(abc); + Namespace ns = name.getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + trait.convertPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); + } else { + trait.convert(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); + } + } + } + + public void appendTo(GraphTextWriter writer, List abcList, Trait[] traits, ExportMode exportMode, boolean parallel) { + for (int t : traitIndices) { + Trait trait = traits[t]; + Multiname name = trait.getName(abc); + Namespace ns = name.getNamespace(abc.constants); + if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + trait.toStringPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); + } else { + trait.toString(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); + } + } + } + + public void toSource(GraphTextWriter writer, final List abcList, final Trait[] traits, final ExportMode exportMode, final boolean parallel) { + writer.suspendMeasure(); + try { + Helper.timedCall(new Callable() { + @Override + public Void call() throws Exception { + convert(new NulWriter(), abcList, traits, exportMode, parallel); + return null; + } + }, Configuration.DECOMPILATION_TIMEOUT_FILE, TimeUnit.SECONDS); + } catch (TimeoutException ex) { + writer.continueMeasure(); + Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Decompilation error", ex); + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Timeout (" + Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT_FILE) + ") was reached").newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to timeout\");").newLine(); + return; + } catch (InterruptedException | ExecutionException ex) { + writer.continueMeasure(); + Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Decompilation error", ex); + writer.appendNoHilight("/*").newLine(); + writer.appendNoHilight(" * Decompilation error").newLine(); + writer.appendNoHilight(" * Code may be obfuscated").newLine(); + writer.appendNoHilight(" * Error type: " + ex.getClass().getSimpleName()).newLine(); + writer.appendNoHilight(" */").newLine(); + writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to error\");").newLine(); + return; + } + writer.continueMeasure(); + + appendTo(writer, abcList, traits, exportMode, parallel); + } + public File export(String directory, List abcList, ExportMode exportMode, boolean parallel) throws IOException { String scriptName = getPathScriptName(); String packageName = getPathPackage(); @@ -115,24 +187,10 @@ public class ScriptPack { } } String fileName = outDir.toString() + File.separator + Helper.makeFileName(scriptName) + ".as"; + File file = new File(fileName); - try (FileOutputStream fos = new FileOutputStream(file)) { - for (int t : traitIndices) { - Multiname name = abc.script_info[scriptIndex].traits.traits[t].getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - abc.script_info[scriptIndex].traits.traits[t].convertPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, new ArrayList(), parallel); - } else { - abc.script_info[scriptIndex].traits.traits[t].convert(null, "", abcList, abc, false, exportMode, scriptIndex, -1, new ArrayList(), parallel); - } - HilightedTextWriter writer = new HilightedTextWriter(false); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - abc.script_info[scriptIndex].traits.traits[t].toStringPackaged(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); - } else { - abc.script_info[scriptIndex].traits.traits[t].toString(null, "", abcList, abc, false, exportMode, scriptIndex, -1, writer, new ArrayList(), parallel); - } - fos.write(writer.toString().getBytes("utf-8")); - } + try (FileTextWriter writer = new FileTextWriter(new FileOutputStream(file))) { + toSource(writer, abcList, abc.script_info[scriptIndex].traits.traits, exportMode, parallel); } return file; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java index acd028cac..807b31868 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java @@ -20,7 +20,6 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; 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.model.LocalData; import java.util.HashMap; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java index cd1ca502d..7f9000c13 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/NewFunctionAVM2Item.java @@ -74,7 +74,7 @@ public class NewFunctionAVM2Item extends AVM2Item { if (body != null) { try { if (writer instanceof NulWriter) { - body.convert(path + "/inner", ExportMode.SOURCE, isStatic, scriptIndex, classIndex, abc, null, constants, methodInfo, new Stack()/*scopeStack*/, false, fullyQualifiedNames, null); + body.convert(path + "/inner", ExportMode.SOURCE, isStatic, scriptIndex, classIndex, abc, null, constants, methodInfo, new Stack()/*scopeStack*/, false, fullyQualifiedNames, null, false); } else { body.toString(path + "/inner", ExportMode.SOURCE, isStatic, scriptIndex, classIndex, abc, null, constants, methodInfo, new Stack()/*scopeStack*/, false, writer, fullyQualifiedNames, null); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index 5d7769959..f54c970e8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -17,7 +17,6 @@ package com.jpexs.decompiler.flash.abc.avm2.model.clauses; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; -import static com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item.localRegName; 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.SetLocalAVM2Item; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index abd7f6b7f..b363cdce1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -115,30 +115,35 @@ public class MethodBody implements Cloneable, Serializable { } public HilightedTextWriter toString(final String path, ExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ConstantPool constants, final MethodInfo[] method_info, final Stack scopeStack, final boolean isStaticInitializer, final List fullyQualifiedNames, final Traits initTraits) { - convert(path, exportMode, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits); + convert(path, exportMode, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, true); HilightedTextWriter writer = new HilightedTextWriter(false); toString(path, exportMode, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, writer, fullyQualifiedNames, initTraits); return writer; } - public void convert(final String path, ExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ConstantPool constants, final MethodInfo[] method_info, final Stack scopeStack, final boolean isStaticInitializer, final List fullyQualifiedNames, final Traits initTraits) { + public void convert(final String path, ExportMode exportMode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ConstantPool constants, final MethodInfo[] method_info, final Stack scopeStack, final boolean isStaticInitializer, final List fullyQualifiedNames, final Traits initTraits, boolean firstLevel) { if (debugMode) { System.err.println("Decompiling " + path); } if (exportMode == ExportMode.SOURCE) { - int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod", 60); + int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod"); try { - Helper.timedCall(new Callable() { + Callable callable = new Callable() { @Override - public Void call() throws Exception { + public Void call() { MethodBody converted = convertMethodBody(path, isStatic, scriptIndex, classIndex, abc, trait, constants, method_info, scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits); HashMap localRegNames = getLocalRegNames(abc); convertedItems = converted.code.toGraphTargetItems(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, converted, localRegNames, scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap(), converted.code.visitCode(converted)); Graph.graphToString(convertedItems, new NulWriter(), LocalData.create(constants, localRegNames, fullyQualifiedNames)); return null; } - }, timeout, TimeUnit.SECONDS); - } catch (InterruptedException | TimeoutException | ExecutionException ex) { + }; + if (firstLevel) { + Helper.timedCall(callable, timeout, TimeUnit.SECONDS); + } else { + callable.call(); + } + } catch (Exception ex) { Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Decompilation error", ex); convertException = ex; if (ex instanceof ExecutionException && ex.getCause() instanceof Exception) { @@ -163,7 +168,7 @@ public class MethodBody implements Cloneable, Serializable { return writer; } writer.indent(); - int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod", 60); + int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod"); if (convertException == null) { HashMap localRegNames = getLocalRegNames(abc); @@ -195,7 +200,7 @@ public class MethodBody implements Cloneable, Serializable { MethodBody b = (MethodBody) Helper.deepCopy(this); AVM2Code deobfuscated = b.code; deobfuscated.markMappedOffsets(); - if (Configuration.getConfig("autoDeobfuscate", true)) { + if (Configuration.getConfig("autoDeobfuscate")) { try { deobfuscated.removeTraps(constants, trait, method_info[this.method_info], b, abc, scriptIndex, classIndex, isStatic, path); } catch (Exception | StackOverflowError ex) { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 3ccd755c2..f25e98423 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -20,13 +20,10 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.helpers.Helper; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -121,7 +118,7 @@ public abstract class Trait implements Serializable { return writer; } - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } public GraphTextWriter toStringPackaged(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel) { @@ -139,11 +136,11 @@ public abstract class Trait implements Serializable { return writer; } - public void convertPackaged(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convertPackaged(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { Namespace ns = abc.constants.constant_multiname[name_index].getNamespace(abc.constants); if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { String nsname = ns.getName(abc.constants); - convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); } } @@ -152,8 +149,8 @@ public abstract class Trait implements Serializable { return writer; } - public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { - convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { + convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); } public Multiname getName(ABC abc) { @@ -173,26 +170,4 @@ public abstract class Trait implements Serializable { String objectName = name.getName(abc.constants, new ArrayList()); return packageName + "." + objectName; } - - public void export(Trait parent, String directory, ABC abc, List abcList, ExportMode exportMode, int scriptIndex, int classIndex, boolean isStatic, boolean parallel) throws IOException { - Multiname name = getName(abc); - Namespace ns = name.getNamespace(abc.constants); - String packageName = ns.getName(abc.constants); - String objectName = name.getName(abc.constants, new ArrayList()); - File outDir = new File(directory + File.separatorChar + packageName.replace('.', File.separatorChar)); - if (!outDir.exists()) { - if (!outDir.mkdirs()) { - if (!outDir.exists()) { - throw new IOException("Cannot create directory " + outDir); - } - } - } - String fileName = outDir.toString() + File.separator + objectName + ".as"; - try (FileOutputStream fos = new FileOutputStream(fileName)) { - convertPackaged(parent, "", abcList, abc, isStatic, exportMode, scriptIndex, classIndex, new ArrayList(), parallel); - HilightedTextWriter writer = new HilightedTextWriter(false); - toStringPackaged(parent, "", abcList, abc, isStatic, exportMode, scriptIndex, classIndex, writer, new ArrayList(), parallel); - fos.write(writer.toString().getBytes("utf-8")); - } - } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 165e3030d..300067554 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -32,6 +32,7 @@ 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.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -45,6 +46,8 @@ public class TraitClass extends Trait implements TraitWithSlot { public int slot_id; public int class_info; private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"}; + + private boolean classInitializerIsEmpty; @Override public int getSlotIndex() { @@ -329,7 +332,7 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } @Override @@ -433,17 +436,13 @@ public class TraitClass extends Trait implements TraitWithSlot { int bodyIndex = abc.findBodyIndex(abc.class_info[class_info].cinit_index); if (bodyIndex != -1) { - int writerPos = writer.getLength(); - writer.startTrait(abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length + 1); - writer.appendNoHilight("{").newLine(); - writer.mark(); - abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", exportMode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, writer, fullyQualifiedNames, abc.class_info[class_info].static_traits); - boolean empty = !writer.getMark(); - writer.appendNoHilight("}").newLine(); - writer.endTrait(); - writer.newLine(); - if (empty) { - writer.setLength(writerPos); + if (!classInitializerIsEmpty) { + writer.startTrait(abc.class_info[class_info].static_traits.traits.length + abc.instance_info[class_info].instance_traits.traits.length + 1); + writer.appendNoHilight("{").newLine(); + abc.bodies[bodyIndex].toString(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", exportMode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, writer, fullyQualifiedNames, abc.class_info[class_info].static_traits); + writer.appendNoHilight("}").newLine(); + writer.endTrait(); + writer.newLine(); } } else { //"/*classInitializer*/"; @@ -499,27 +498,29 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { fullyQualifiedNames = new ArrayList<>(); int bodyIndex = abc.findBodyIndex(abc.class_info[class_info].cinit_index); if (bodyIndex != -1) { - abc.bodies[bodyIndex].convert(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", exportMode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, fullyQualifiedNames, abc.class_info[class_info].static_traits); + writer.mark(); + abc.bodies[bodyIndex].convert(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".staticinitializer", exportMode, true, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), true, fullyQualifiedNames, abc.class_info[class_info].static_traits, true); + classInitializerIsEmpty = !writer.getMark(); } //constructor if (!abc.instance_info[class_info].isInterface()) { bodyIndex = abc.findBodyIndex(abc.instance_info[class_info].iinit_index); if (bodyIndex != -1) { - abc.bodies[bodyIndex].convert(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".initializer", exportMode, false, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, abc.instance_info[class_info].instance_traits); + abc.bodies[bodyIndex].convert(path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames) + ".initializer", exportMode, false, scriptIndex, class_info, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, abc.instance_info[class_info].instance_traits, true); } } //static variables,constants & methods - abc.class_info[class_info].static_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, true, exportMode, false, scriptIndex, class_info, fullyQualifiedNames, parallel); + abc.class_info[class_info].static_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, true, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel); - abc.instance_info[class_info].instance_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, false, exportMode, false, scriptIndex, class_info, fullyQualifiedNames, parallel); + abc.instance_info[class_info].instance_traits.convert(this, path +/*packageName +*/ "/" + abc.instance_info[class_info].getName(abc.constants).getName(abc.constants, fullyQualifiedNames), abcTags, abc, false, exportMode, false, scriptIndex, class_info, writer, fullyQualifiedNames, parallel); } @Override diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index cd70f5833..c4a45b3ae 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -62,7 +63,7 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } @Override @@ -84,12 +85,12 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { - convertHeader(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { + convertHeader(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); if (!abc.instance_info[classIndex].isInterface()) { int bodyIndex = abc.findBodyIndex(method_info); if (bodyIndex != -1) { - abc.bodies[bodyIndex].convert(path + "." + abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), exportMode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, null); + abc.bodies[bodyIndex].convert(path + "." + abc.constants.constant_multiname[name_index].getName(abc.constants, fullyQualifiedNames), exportMode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, null, true); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 3ce9fa487..f7eb82a0c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -18,9 +18,8 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.MethodBody; -import static com.jpexs.decompiler.flash.abc.types.traits.Trait.TRAIT_GETTER; -import static com.jpexs.decompiler.flash.abc.types.traits.Trait.TRAIT_SETTER; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -39,7 +38,7 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convertHeader(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } @Override @@ -72,13 +71,13 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames); - convertHeader(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + convertHeader(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); int bodyIndex = abc.findBodyIndex(method_info); if (!(classIndex != -1 && abc.instance_info[classIndex].isInterface() || bodyIndex == -1)) { if (bodyIndex != -1) { - abc.bodies[bodyIndex].convert(path, exportMode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, null); + abc.bodies[bodyIndex].convert(path, exportMode, isStatic, scriptIndex, classIndex, abc, this, abc.constants, abc.method_info, new Stack(), false, fullyQualifiedNames, null, true); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index acd92b3c9..544ca0596 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -22,6 +22,7 @@ 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.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -148,7 +149,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } @Override - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { } public boolean isConst() { diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 16092fd1d..9c0873e7e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.abc.types.traits; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import java.io.Serializable; @@ -84,12 +85,13 @@ public class Traits implements Serializable { ExportMode exportMode; int scriptIndex; int classIndex; + NulWriter writer; List fullyQualifiedNames; int traitIndex; boolean parallel; Trait parent; - public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, List fullyQualifiedNames, int traitIndex, boolean parallel) { + public TraitConvertTask(Trait trait, Trait parent, boolean makePackages, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, int traitIndex, boolean parallel) { this.trait = trait; this.parent = parent; this.makePackages = makePackages; @@ -100,6 +102,7 @@ public class Traits implements Serializable { this.exportMode = exportMode; this.scriptIndex = scriptIndex; this.classIndex = classIndex; + this.writer = writer; this.fullyQualifiedNames = fullyQualifiedNames; this.traitIndex = traitIndex; this.parallel = parallel; @@ -107,16 +110,10 @@ public class Traits implements Serializable { @Override public Void call() { - int h = traitIndex; - if (classIndex != -1) { - if (!isStatic) { - h = h + abc.class_info[classIndex].static_traits.traits.length; - } - } if (makePackages) { - trait.convertPackaged(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + trait.convertPackaged(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); } else { - trait.convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, parallel); + trait.convert(parent, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel); } return null; } @@ -153,10 +150,10 @@ public class Traits implements Serializable { return writer; } - public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, List fullyQualifiedNames, boolean parallel) { + public void convert(Trait parent, String path, List abcTags, ABC abc, boolean isStatic, ExportMode exportMode, boolean makePackages, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel) { if (!parallel || traits.length < 2) { for (int t = 0; t < traits.length; t++) { - TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, t, parallel); + TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel); task.call(); } } else { @@ -165,7 +162,7 @@ public class Traits implements Serializable { futureResults = new ArrayList<>(); for (int t = 0; t < traits.length; t++) { - TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, fullyQualifiedNames, t, parallel); + TraitConvertTask task = new TraitConvertTask(traits[t], parent, makePackages, path, abcTags, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, t, parallel); Future future = executor.submit(task); futureResults.add(future); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java b/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java index 4084adcdb..8406e3ff3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java @@ -21,6 +21,7 @@ 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.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import java.util.ArrayList; @@ -38,13 +39,15 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { @Override public String toString(List abcTags, ABC abc) { + NulWriter nulWriter = new NulWriter(); if (parentTraitIndex > -1) { if (isStatic) { - ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); + ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); } else { - ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); + ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); } } + ((TraitSlotConst) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); HilightedTextWriter writer = new HilightedTextWriter(false); writer.appendNoHilight(super.toString(abcTags, abc) + " "); @@ -55,7 +58,6 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).toStringHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); } } - ((TraitSlotConst) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); ((TraitSlotConst) traits.traits[traitIndex]).toStringHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, writer, new ArrayList(), false); return writer.toString(); } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java b/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java index 81bfcd1f8..1e00e7ee5 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import java.util.ArrayList; @@ -44,15 +45,16 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage { @Override public String toString(List abcTags, ABC abc) { + NulWriter nulWriter = new NulWriter(); if (!isInitializer) { if (parentTraitIndex > -1) { if (isStatic){ - ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); + ((TraitMethodGetterSetter) abc.class_info[classIndex].static_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); } else { - ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); + ((TraitMethodGetterSetter) abc.instance_info[classIndex].instance_traits.traits[parentTraitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); } } - ((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, new ArrayList(), false); + ((TraitMethodGetterSetter) traits.traits[traitIndex]).convertHeader(null, "", abcTags, abc, isStatic, ExportMode.SOURCE, -1/*FIXME*/, classIndex, nulWriter, new ArrayList(), false); } HilightedTextWriter writer = new HilightedTextWriter(false); diff --git a/trunk/src/com/jpexs/decompiler/flash/action/Action.java b/trunk/src/com/jpexs/decompiler/flash/action/Action.java index 7a9fec799..5600e600f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/Action.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/Action.java @@ -51,6 +51,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; +import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphSource; @@ -697,10 +698,11 @@ public class Action implements GraphSourceItem { * @param path * @return String with Source code */ - public static void actionsToSource(final List actions, final int version, final String path, HilightedTextWriter writer) { + public static void actionsToSource(ASMSource asm, final List actions, final int version, final String path, GraphTextWriter writer) { + writer.suspendMeasure(); List tree = null; Throwable convertException = null; - int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod", 60); + int timeout = Configuration.getConfig("decompilationTimeoutSingleMethod"); try { tree = Helper.timedCall(new Callable>() { @Override @@ -718,7 +720,9 @@ public class Action implements GraphSourceItem { convertException = (Exception) ex.getCause(); } } + writer.continueMeasure(); + asm.getActionSourcePrefix(writer); if (convertException == null) { Graph.graphToString(tree, writer, new LocalData()); } else if (convertException instanceof TimeoutException) { @@ -737,6 +741,7 @@ public class Action implements GraphSourceItem { writer.appendNoHilight(" */").newLine(); writer.appendNoHilight("throw new IllegalOperationError(\"Not decompiled due to error\");").newLine(); } + asm.getActionSourceSuffix(writer); } /** diff --git a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java index f014ae2c8..388f6fda9 100644 --- a/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/trunk/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -80,7 +80,7 @@ public class ActionListReader { * @throws IOException */ public static List readActionList(List listeners, long containerSWFOffset, ReReadableInputStream rri, int version, int ip, int endIp, String path) throws IOException { - boolean deobfuscate = Configuration.getConfig("autoDeobfuscate", true); + boolean deobfuscate = Configuration.getConfig("autoDeobfuscate"); ConstantPool cpool = new ConstantPool(); @@ -225,7 +225,7 @@ public class ActionListReader { } } - if (Configuration.getConfig("removeNops", true)) { + if (Configuration.getConfig("removeNops")) { ret = Action.removeNops(0, ret, version, 0, path); } List reta = new ArrayList<>(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/GuiAbortRetryIgnoreHandler.java b/trunk/src/com/jpexs/decompiler/flash/gui/GuiAbortRetryIgnoreHandler.java new file mode 100644 index 000000000..03fb4e5d9 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/GuiAbortRetryIgnoreHandler.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010-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 . + */ +package com.jpexs.decompiler.flash.gui; + +import com.jpexs.decompiler.flash.AbortRetryIgnoreHandler; +import javax.swing.JOptionPane; + +/** + * + * @author JPEXS + */ +public class GuiAbortRetryIgnoreHandler implements AbortRetryIgnoreHandler { + + @Override + public int handle(Throwable thrown) { + synchronized (GuiAbortRetryIgnoreHandler.class) { + String[] options = new String[]{AppStrings.translate("button.abort"), AppStrings.translate("button.retry"), AppStrings.translate("button.ignore")}; + return View.showOptionDialog(null, AppStrings.translate("error.occured").replace("%error%", thrown.getLocalizedMessage()), AppStrings.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; + } + +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java index 131cbad25..5d5a0f333 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/Main.java @@ -23,7 +23,6 @@ import com.jpexs.decompiler.flash.EventListener; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.Version; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; import com.jpexs.decompiler.flash.gui.player.FlashPlayerPanel; import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame; import com.jpexs.decompiler.graph.ExportMode; @@ -178,16 +177,24 @@ public class Main { } public static void startWork(String name) { - startWork(name, -1); + startWork(name, -1, null); } - public static void startWork(final String name, final int percent) { + public static void startWork(String name, int percent) { + startWork(name, percent, null); + } + + public static void startWork(String name, Runnable cancelCallback) { + startWork(name, -1, cancelCallback); + } + + public static void startWork(final String name, final int percent, final Runnable cancelCallback) { working = true; View.execInEventDispatch(new Runnable() { @Override public void run() { if (mainFrame != null) { - mainFrame.setWorkStatus(name); + mainFrame.setWorkStatus(name, cancelCallback); if (percent == -1) { mainFrame.hidePercent(); } else { @@ -213,7 +220,7 @@ public class Main { public static void stopWork() { working = false; if (mainFrame != null) { - mainFrame.setWorkStatus(""); + mainFrame.setWorkStatus("", null); } if (loadingDialog != null) { loadingDialog.setDetail(""); @@ -229,23 +236,23 @@ public class Main { locswf = new SWF(fis, new ProgressListener() { @Override public void progress(int p) { - startWork(translate("work.reading.swf"), p); + startWork(AppStrings.translate("work.reading.swf"), p); } }, Configuration.getConfig("parallelSpeedUp", true)); locswf.addEventListener(new EventListener() { @Override public void handleEvent(String event, Object data) { - if (event.equals("export")) { + if (event.equals("exporting")) { startWork((String) data); } if (event.equals("getVariables")) { - startWork(translate("work.gettingvariables") + "..." + (String) data); + startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data); } if (event.equals("deobfuscate")) { - startWork(translate("work.deobfuscating") + "..." + (String) data); + startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data); } if (event.equals("rename")) { - startWork(translate("work.renaming") + "..." + (String) data); + startWork(AppStrings.translate("work.renaming") + "..." + (String) data); } } }); @@ -276,7 +283,7 @@ public class Main { @Override protected Object doInBackground() throws Exception { try { - Main.startWork(translate("work.reading.swf") + "..."); + Main.startWork(AppStrings.translate("work.reading.swf") + "..."); swf = parseSWF(Main.inputStream); if (Main.inputStream instanceof FileInputStream) { Main.inputStream.close(); @@ -294,11 +301,15 @@ public class Main { } try { - Main.startWork(translate("work.creatingwindow") + "..."); + Main.startWork(AppStrings.translate("work.creatingwindow") + "..."); View.execInEventDispatch(new Runnable() { @Override public void run() { + try{ mainFrame = new MainFrame(swf); + } catch(Exception ex) { + String a = ex.toString(); + } if (errorState) { mainFrame.setErrorState(); } @@ -427,7 +438,7 @@ public class Main { @Override public String getDescription() { - return translate("filter.swf"); + return AppStrings.translate("filter.swf"); } }; if (!swf.gfx) { @@ -443,7 +454,7 @@ public class Main { @Override public String getDescription() { - return translate("filter.gfx"); + return AppStrings.translate("filter.gfx"); } }; if (swf.gfx) { @@ -478,7 +489,7 @@ public class Main { readOnly = false; return true; } catch (IOException ex) { - View.showMessageDialog(null, translate("error.file.write")); + View.showMessageDialog(null, AppStrings.translate("error.file.write")); } } return false; @@ -498,7 +509,7 @@ public class Main { @Override public String getDescription() { - return translate("filter.supported"); + return AppStrings.translate("filter.supported"); } }; fc.setFileFilter(allSupportedFilter); @@ -510,7 +521,7 @@ public class Main { @Override public String getDescription() { - return translate("filter.swf"); + return AppStrings.translate("filter.swf"); } }; fc.addChoosableFileFilter(swfFilter); @@ -522,7 +533,7 @@ public class Main { @Override public String getDescription() { - return translate("filter.gfx"); + return AppStrings.translate("filter.gfx"); } }; fc.addChoosableFileFilter(gfxFilter); @@ -746,7 +757,7 @@ public class Main { } private static void offerAssociation() { - boolean offered = Configuration.getConfig("offeredAssociation", false); + boolean offered = Configuration.getConfig("offeredAssociation"); if (!offered) { if (Platform.isWindows()) { if ((!isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) { @@ -901,6 +912,7 @@ public class Main { int errorMode = AbortRetryIgnoreHandler.UNDEFINED; int retryCount = 0; + Level traceLevel = Level.WARNING; if (args.length < pos + 1) { initGui(); @@ -1029,6 +1041,10 @@ public class Main { } else { System.err.println("Process priority setting is only available on Windows platform."); } + } else if (args[pos].equals("-verbose")) { + parameterProcessed = true; + pos++; + traceLevel = Level.FINE; } } if (args[pos].equals("-removefromcontextmenu")) { @@ -1097,10 +1113,14 @@ public class Main { try { printHeader(); SWF exfile = new SWF(new FileInputStream(inFile), Configuration.getConfig("parallelSpeedUp", true)); + final Level level = traceLevel; exfile.addEventListener(new EventListener() { @Override public void handleEvent(String event, Object data) { - if (event.equals("export")) { + if (level.intValue() <= Level.FINE.intValue() && event.equals("exporting")) { + System.out.println((String) data); + } + if (event.equals("exported")) { System.out.println((String) data); } } @@ -1142,13 +1162,14 @@ public class Main { case "pcodehex": case "hex": ExportMode exportMode = strToExportFormat(exportFormat); + boolean parallel = Configuration.getConfig("parallelSpeedUp", true); if ((pos + 5 < args.length) && (args[pos + 4].equals("-selectas3class"))) { exportOK = true; for (int i = pos + 5; i < args.length; i++) { - exportOK = exportOK && exfile.exportAS3Class(args[i], outDir.getAbsolutePath(), exportMode, Configuration.getConfig("parallelSpeedUp", true)); + exportOK = exportOK && exfile.exportAS3Class(args[i], outDir.getAbsolutePath(), exportMode, parallel); } } else { - exportOK = !exfile.exportActionScript(handler, outDir.getAbsolutePath(), exportMode, Configuration.getConfig("parallelSpeedUp", true)).isEmpty(); + exportOK = exfile.exportActionScript(handler, outDir.getAbsolutePath(), exportMode, parallel) != null; } break; case "movie": @@ -1334,9 +1355,9 @@ public class Main { proxyFrame.switchState(); if (stopMenuItem != null) { if (proxyFrame.isRunning()) { - stopMenuItem.setLabel(translate("proxy.stop")); + stopMenuItem.setLabel(AppStrings.translate("proxy.stop")); } else { - stopMenuItem.setLabel(translate("proxy.start")); + stopMenuItem.setLabel(AppStrings.translate("proxy.start")); } } } @@ -1347,7 +1368,7 @@ public class Main { } if (SystemTray.isSupported()) { SystemTray tray = SystemTray.getSystemTray(); - trayIcon = new TrayIcon(View.loadImage("proxy16"), vendor + " " + shortApplicationName + " " + translate("proxy")); + trayIcon = new TrayIcon(View.loadImage("proxy16"), vendor + " " + shortApplicationName + " " + AppStrings.translate("proxy")); trayIcon.setImageAutoSize(true); PopupMenu trayPopup = new PopupMenu(); @@ -1371,16 +1392,16 @@ public class Main { }; - MenuItem showMenuItem = new MenuItem(translate("proxy.show")); + MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show")); showMenuItem.setActionCommand("SHOW"); showMenuItem.addActionListener(trayListener); trayPopup.add(showMenuItem); - stopMenuItem = new MenuItem(translate("proxy.start")); + stopMenuItem = new MenuItem(AppStrings.translate("proxy.start")); stopMenuItem.setActionCommand("SWITCH"); stopMenuItem.addActionListener(trayListener); trayPopup.add(stopMenuItem); trayPopup.addSeparator(); - MenuItem exitMenuItem = new MenuItem(translate("exit")); + MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit")); exitMenuItem.setActionCommand("EXIT"); exitMenuItem.addActionListener(trayListener); trayPopup.add(exitMenuItem); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 8a180763f..a0e34211e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -98,7 +98,9 @@ import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.TEXTRECORD; import com.jpexs.decompiler.graph.ExportMode; +import com.jpexs.helpers.AsyncResult; import com.jpexs.helpers.Cache; +import com.jpexs.helpers.Callback; import com.jpexs.helpers.Helper; import com.jpexs.process.ProcessTools; import java.awt.BorderLayout; @@ -159,6 +161,8 @@ import java.util.Stack; import java.util.Timer; import java.util.TimerTask; import java.util.TreeSet; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Box; @@ -235,6 +239,8 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel public LoadingPanel loadingPanel = new LoadingPanel(20, 20); public JLabel statusLabel = new JLabel(""); public JPanel statusPanel = new JPanel(); + public JButton cancelButton = new JButton(); + public Runnable cancelButtonPressed; public JProgressBar progressBar = new JProgressBar(0, 100); private DeobfuscationDialog deobfuscationDialog; public JTree tagTree; @@ -296,21 +302,8 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel public static final String FLASH_VIEWER_CARD = "FLASHVIEWER"; public static final String INTERNAL_VIEWER_CARD = "INTERNALVIEWER"; private Map sourceFontsMap = new HashMap<>(); - private AbortRetryIgnoreHandler errorHandler = new AbortRetryIgnoreHandler() { - @Override - public int handle(Throwable thrown) { - synchronized (MainFrame.class) { - String[] options = new String[]{translate("button.abort"), translate("button.retry"), translate("button.ignore")}; - 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; - } - }; + private AbortRetryIgnoreHandler errorHandler = new GuiAbortRetryIgnoreHandler(); + private FutureTask setSourceTask; public void setPercent(int percent) { progressBar.setValue(percent); @@ -346,13 +339,15 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel statusLabel.setText(s); } - public void setWorkStatus(String s) { + public void setWorkStatus(String s, Runnable cancelCallback) { if (s.equals("")) { loadingPanel.setVisible(false); } else { loadingPanel.setVisible(true); } statusLabel.setText(s); + cancelButtonPressed = cancelCallback; + cancelButton.setVisible(cancelCallback != null); } private String fixCommandTitle(String title) { @@ -1044,14 +1039,31 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel }; tagTree.setCellRenderer(tcr); + JPanel statusLeftPanel = new JPanel(); + statusLeftPanel.setLayout(new BoxLayout(statusLeftPanel, BoxLayout.X_AXIS)); loadingPanel.setPreferredSize(new Dimension(30, 30)); + // todo: this button is a little bit ugly in the UI. Maybe it can be changed to an icon (as in NetBeans) + cancelButton.setText(translate("button.cancel")); + cancelButton.setPreferredSize(new Dimension(100, 30)); + cancelButton.setBorderPainted(false); + cancelButton.setOpaque(false); + cancelButton.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + if (cancelButtonPressed != null) { + cancelButtonPressed.run(); + } + } + }); + statusLeftPanel.add(loadingPanel); + statusLeftPanel.add(statusLabel); + statusLeftPanel.add(cancelButton); statusPanel = new JPanel(); statusPanel.setPreferredSize(new Dimension(1, 30)); statusPanel.setBorder(new BevelBorder(BevelBorder.LOWERED)); statusPanel.setLayout(new BorderLayout()); - statusPanel.add(loadingPanel, BorderLayout.WEST); - statusPanel.add(statusLabel, BorderLayout.CENTER); - + statusPanel.add(statusLeftPanel, BorderLayout.WEST); errorNotificationButton = new JButton(""); errorNotificationButton.setIcon(View.getIcon("okay16")); @@ -1065,8 +1077,8 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel errorNotificationButton.setToolTipText(translate("errors.none")); statusPanel.add(errorNotificationButton, BorderLayout.EAST); - loadingPanel.setVisible(false); + cancelButton.setVisible(false); cnt.add(statusPanel, BorderLayout.SOUTH); if (swf != null) { @@ -2185,7 +2197,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel allNodes.add(asn); TagNode.setExport(allNodes, false); TagNode.setExport(actionNodes, true); - ret.addAll(TagNode.exportNodeAS(swf.tags, handler, allNodes, selFile, exportMode)); + ret.addAll(TagNode.exportNodeAS(swf.tags, handler, allNodes, selFile, exportMode, null)); } } return ret; @@ -2790,7 +2802,7 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel case "RESTORECONTROLFLOW": case "RESTORECONTROLFLOWALL": - Main.startWork("Restoring control flow..."); + Main.startWork(translate("work.restoringControlFlow")); final boolean all = e.getActionCommand().endsWith("ALL"); if ((!all) || confirmExperimental()) { new SwingWorker() { @@ -2982,33 +2994,48 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel if (tagObj instanceof ScriptPack) { final ScriptPack scriptLeaf = (ScriptPack) tagObj; if (!Main.isWorking()) { - Main.startWork(translate("work.decompiling") + "..."); - (new Thread() { + Main.startWork(translate("work.decompiling") + "...", new Runnable() { + @Override public void run() { - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - int classIndex = -1; - for (Trait t : scriptLeaf.abc.script_info[scriptLeaf.scriptIndex].traits.traits) { - if (t instanceof TraitClass) { - classIndex = ((TraitClass) t).class_info; - break; - } - } - abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setCode(""); - abcPanel.navigator.setABC(abcList, scriptLeaf.abc); - abcPanel.navigator.setClassIndex(classIndex, scriptLeaf.scriptIndex); - abcPanel.setAbc(scriptLeaf.abc); - abcPanel.decompiledTextArea.setScript(scriptLeaf, abcList); - abcPanel.decompiledTextArea.setClassIndex(classIndex); - abcPanel.decompiledTextArea.setNoTrait(); - Main.stopWork(); - } - }); + if (setSourceTask != null) { + setSourceTask.cancel(true); + } + abcPanel.decompiledTextArea.setText("//" + AppStrings.translate("work.canceled")); } - }).start(); + }); + + FutureTask task = Helper.callAsync(new Callable() { + + @Override + public Void call() throws Exception { + int classIndex = -1; + for (Trait t : scriptLeaf.abc.script_info[scriptLeaf.scriptIndex].traits.traits) { + if (t instanceof TraitClass) { + classIndex = ((TraitClass) t).class_info; + break; + } + } + abcPanel.detailPanel.methodTraitPanel.methodCodePanel.setCode(""); + abcPanel.navigator.setABC(abcList, scriptLeaf.abc); + abcPanel.navigator.setClassIndex(classIndex, scriptLeaf.scriptIndex); + abcPanel.setAbc(scriptLeaf.abc); + abcPanel.decompiledTextArea.setScript(scriptLeaf, abcList); + abcPanel.decompiledTextArea.setClassIndex(classIndex); + abcPanel.decompiledTextArea.setNoTrait(); + return null; + } + }, new Callback>() { + + @Override + public void call(AsyncResult arg1) { + setSourceTask = null; + Main.stopWork(); + } + }); + setSourceTask = task; } + showDetail(DETAILCARDAS3NAVIGATOR); showCard(CARDACTIONSCRIPTPANEL); return; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviwPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviwPanel.java index ac4d764b3..7d80efb2f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviwPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/SWFPreviwPanel.java @@ -17,7 +17,6 @@ package com.jpexs.decompiler.flash.gui; import com.jpexs.decompiler.flash.SWF; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; import com.jpexs.decompiler.flash.gui.player.FlashDisplay; import com.jpexs.decompiler.flash.gui.player.PlayerControls; import java.awt.BorderLayout; @@ -42,7 +41,7 @@ public class SWFPreviwPanel extends JPanel implements FlashDisplay { Timer timer; int frame = 1; List frameImages = new ArrayList<>(); - JLabel buffering = new JLabel(translate("work.buffering") + "..."); + JLabel buffering = new JLabel(AppStrings.translate("work.buffering") + "..."); public SWFPreviwPanel() { pan = new ImagePanel(); @@ -51,7 +50,7 @@ public class SWFPreviwPanel extends JPanel implements FlashDisplay { add(new JScrollPane(pan), BorderLayout.CENTER); buffering.setHorizontalAlignment(JLabel.CENTER); buffering.setVisible(false); - JLabel prevLabel = new HeaderLabel(translate("swfpreview.internal")); + JLabel prevLabel = new HeaderLabel(AppStrings.translate("swfpreview.internal")); prevLabel.setHorizontalAlignment(SwingConstants.CENTER); //prevLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); add(prevLabel, BorderLayout.NORTH); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 0fecb8693..6b5e7704e 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -36,7 +36,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; 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 static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.Freed; import com.jpexs.decompiler.flash.gui.HeaderLabel; import com.jpexs.decompiler.flash.gui.Main; @@ -90,8 +90,8 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr //public JSplitPane splitPaneTreeNavVSDecompiledDetail; private JTable constantTable; public JComboBox constantTypeList; - public JLabel asmLabel = new HeaderLabel(translate("panel.disassembled")); - public JLabel decLabel = new HeaderLabel(translate("panel.decompiled")); + public JLabel asmLabel = new HeaderLabel(AppStrings.translate("panel.disassembled")); + public JLabel decLabel = new HeaderLabel(AppStrings.translate("panel.decompiled")); public DetailPanel detailPanel; public JTextField filterField = new MyTextField(); public JPanel navPanel; @@ -124,10 +124,10 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr int pos = 0; for (MyEntry item : allpacks) { pos++; - String workText = translate("work.searching"); + String workText = AppStrings.translate("work.searching"); String decAdd = ""; if (!decompiledTextArea.isCached(item.value)) { - decAdd = ", " + translate("work.decompiling"); + decAdd = ", " + AppStrings.translate("work.decompiling"); } Main.startWork(workText + " \"" + txt + "\"" + decAdd + " - (" + pos + "/" + allpacks.size() + ") " + item.key.toString() + "... "); decompiledTextArea.cacheScriptPack(item.value, list); @@ -148,7 +148,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr searchPanel.setVisible(true); searchFor = txt; updateSearchPos(); - searchForLabel.setText(translate("search.info").replace("%text%", txt) + " "); + searchForLabel.setText(AppStrings.translate("search.info").replace("%text%", txt) + " "); } return true; } @@ -310,7 +310,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr newTraitButton.setMargin(new Insets(5, 5, 5, 5)); newTraitButton.addActionListener(this); newTraitButton.setActionCommand("ADDTRAIT"); - newTraitButton.setToolTipText(translate("button.addtrait")); + newTraitButton.setToolTipText(AppStrings.translate("button.addtrait")); iconsPanel.add(newTraitButton); @@ -371,7 +371,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr } }); - Main.startWork(translate("work.buildingscripttree") + "..."); + Main.startWork(AppStrings.translate("work.buildingscripttree") + "..."); filterField.setActionCommand("FILTERSCRIPT"); filterField.addActionListener(this); @@ -418,10 +418,10 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr cancelSearchButton.addActionListener(this); cancelSearchButton.setActionCommand("SEARCHCANCEL"); searchPos = new JLabel("0/0"); - searchForLabel = new JLabel(translate("search.info").replace("%text%", "") + " "); + searchForLabel = new JLabel(AppStrings.translate("search.info").replace("%text%", "") + " "); searchPanel.add(searchForLabel); searchPanel.add(prevSearchButton); - searchPanel.add(new JLabel(translate("search.script") + " ")); + searchPanel.add(new JLabel(AppStrings.translate("search.script") + " ")); searchPanel.add(searchPos); searchPanel.add(nextSearchButton); searchPanel.add(cancelSearchButton); @@ -436,7 +436,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr splitPaneTreeVSNavigator.setResizeWeight(0.5); splitPaneTreeVSNavigator.setContinuousLayout(true);*/ tabbedPane = new JTabbedPane(); - tabbedPane.addTab(translate("traits"), navPanel); + tabbedPane.addTab(AppStrings.translate("traits"), navPanel); //tabbedPane.setTabPlacement(JTabbedPane.BOTTOM); //pan2.add(tabbedPane, BorderLayout.CENTER); @@ -490,7 +490,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr constantTypeList.addItemListener(this); panConstants.add(constantTypeList, BorderLayout.NORTH); panConstants.add(new JScrollPane(constantTable), BorderLayout.CENTER); - tabbedPane.addTab(translate("constants"), panConstants); + tabbedPane.addTab(AppStrings.translate("constants"), panConstants); } public void doFilter() { @@ -597,7 +597,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr loopm: do { if (again) { - View.showMessageDialog(null, translate("error.trait.exists").replace("%name%", name), translate("error"), JOptionPane.ERROR_MESSAGE); + View.showMessageDialog(null, AppStrings.translate("error.trait.exists").replace("%name%", name), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); } again = false; if (!newTraitDialog.display()) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTree.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTree.java index 5afd813cb..bebd73295 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTree.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTree.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; @@ -125,7 +126,7 @@ public class ClassesListTree extends JTree implements TreeSelectionListener { if (item instanceof ScriptPack) { final ScriptPack scriptLeaf = (ScriptPack) item; if (!Main.isWorking()) { - Main.startWork("Decompiling..."); + Main.startWork(AppStrings.translate("work.decompiling") + "..."); (new Thread() { @Override public void run() { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java index 60625f992..159e976b7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ClassesListTreeModel.java @@ -20,7 +20,7 @@ import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.abc.types.traits.TraitClass; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import java.util.List; import javax.swing.event.TreeModelListener; @@ -164,6 +164,6 @@ public class ClassesListTreeModel implements TreeModel { @Override public String toString() { - return translate("node.scripts"); + return AppStrings.translate("node.scripts"); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index b04214d75..4b0cd08d6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -26,7 +26,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait; 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 static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.helpers.HilightedText; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; @@ -452,13 +452,9 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL script = abc.script_info[scriptIndex]; } if (!cache.contains(scriptLeaf)) { - for (int scriptTraitIndex : scriptLeaf.traitIndices) { - script.traits.traits[scriptTraitIndex].convertPackaged(null, scriptLeaf.getPath().toString(), abcList, abc, false, ExportMode.SOURCE, scriptIndex, -1, new ArrayList(), Configuration.getConfig("parallelSpeedUp", true)); - } + boolean parallel = Configuration.getConfig("parallelSpeedUp", true); HilightedTextWriter writer = new HilightedTextWriter(true); - for (int scriptTraitIndex : scriptLeaf.traitIndices) { - script.traits.traits[scriptTraitIndex].toStringPackaged(null, scriptLeaf.getPath().toString(), abcList, abc, false, ExportMode.SOURCE, scriptIndex, -1, writer, new ArrayList(), Configuration.getConfig("parallelSpeedUp", true)); - } + scriptLeaf.toSource(writer, abcList, script.traits.traits, ExportMode.SOURCE, parallel); hilightedCode = new HilightedText(writer); cache.put(scriptLeaf, new CachedDecompilation(hilightedCode)); } @@ -480,7 +476,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL this.script = scriptLeaf; return; } - setText("//" + translate("pleasewait") + "..."); + setText("//" + AppStrings.translate("pleasewait") + "..."); this.abc = abc; this.abcList = abcList; @@ -494,18 +490,12 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL traitHighlights = cd.getTraitHighlights(); methodHighlights = cd.getMethodHighlights(); classHighlights = cd.getClassHighlights(); - View.execInEventDispatch(new Runnable() { - @Override - public void run() { - if (hilightedCode.length() > 1024 * 1024 * 2/*2MB*/) { - setContentType("text/plain"); - } else { - setContentType("text/actionscript"); - } - setText(hilightedCode); - } - }); - + if (hilightedCode.length() > 1024 * 1024 * 2/*2MB*/) { + setContentType("text/plain"); + } else { + setContentType("text/actionscript"); + } + setText(hilightedCode); } public void reloadClass() { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java index 60468c3ea..340ced501 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.HeaderLabel; import com.jpexs.decompiler.flash.gui.View; import java.awt.BorderLayout; @@ -40,13 +40,13 @@ public class DetailPanel extends JPanel implements ActionListener { public MethodTraitDetailPanel methodTraitPanel; public JPanel unsupportedTraitPanel; public SlotConstTraitDetailPanel slotConstTraitPanel; - public static final String METHOD_TRAIT_CARD = translate("abc.detail.methodtrait"); - public static final String UNSUPPORTED_TRAIT_CARD = translate("abc.detail.unsupported"); - public static final String SLOT_CONST_TRAIT_CARD = translate("abc.detail.slotconsttrait"); + public static final String METHOD_TRAIT_CARD = AppStrings.translate("abc.detail.methodtrait"); + public static final String UNSUPPORTED_TRAIT_CARD = AppStrings.translate("abc.detail.unsupported"); + public static final String SLOT_CONST_TRAIT_CARD = AppStrings.translate("abc.detail.slotconsttrait"); private JPanel innerPanel; - public JButton saveButton = new JButton(translate("button.save"), View.getIcon("save16")); - public JButton editButton = new JButton(translate("button.edit"), View.getIcon("edit16")); - public JButton cancelButton = new JButton(translate("button.cancel"), View.getIcon("cancel16")); + public JButton saveButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); + public JButton editButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); + public JButton cancelButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); private HashMap cardMap = new HashMap<>(); private String selectedCard; private JLabel selectedLabel; @@ -64,7 +64,7 @@ public class DetailPanel extends JPanel implements ActionListener { cardMap.put(METHOD_TRAIT_CARD, methodTraitPanel); unsupportedTraitPanel = new JPanel(new BorderLayout()); - JLabel unsup = new JLabel(translate("info.selecttrait"), SwingConstants.CENTER); + JLabel unsup = new JLabel(AppStrings.translate("info.selecttrait"), SwingConstants.CENTER); unsupportedTraitPanel.add(unsup, BorderLayout.CENTER); cardMap.put(UNSUPPORTED_TRAIT_CARD, unsupportedTraitPanel); @@ -175,7 +175,7 @@ public class DetailPanel extends JPanel implements ActionListener { int lasttrait = abcPanel.decompiledTextArea.lastTraitIndex; abcPanel.decompiledTextArea.reloadClass(); abcPanel.decompiledTextArea.gotoTrait(lasttrait); - View.showMessageDialog(this, translate("message.trait.saved")); + View.showMessageDialog(this, AppStrings.translate("message.trait.saved")); } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DialogMissingSymbolHandler.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DialogMissingSymbolHandler.java index 0a7c8130b..7956665fd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DialogMissingSymbolHandler.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DialogMissingSymbolHandler.java @@ -17,7 +17,7 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.abc.avm2.parser.MissingSymbolHandler; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.View; import javax.swing.JOptionPane; @@ -25,21 +25,21 @@ public class DialogMissingSymbolHandler implements MissingSymbolHandler { @Override public boolean missingString(String value) { - return View.showConfirmDialog(null, translate("message.constant.new.string").replace("%value%", value), translate("message.constant.new.string.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; + return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.string").replace("%value%", value), AppStrings.translate("message.constant.new.string.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; } @Override public boolean missingInt(long value) { - return View.showConfirmDialog(null, translate("message.constant.new.integer").replace("%value%", "" + value), translate("message.constant.new.integer.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; + return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.integer").replace("%value%", "" + value), AppStrings.translate("message.constant.new.integer.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; } @Override public boolean missingUInt(long value) { - return View.showConfirmDialog(null, translate("message.constant.new.unsignedinteger").replace("%value%", "" + value), translate("message.constant.new.unsignedinteger.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; + return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.unsignedinteger").replace("%value%", "" + value), AppStrings.translate("message.constant.new.unsignedinteger.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; } @Override public boolean missingDouble(double value) { - return View.showConfirmDialog(null, translate("message.constant.new.double").replace("%value%", "" + value), translate("message.constant.new.double.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; + return View.showConfirmDialog(null, AppStrings.translate("message.constant.new.double").replace("%value%", "" + value), AppStrings.translate("message.constant.new.double.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java index 5b3a3f329..55baa8ce4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/MethodCodePanel.java @@ -19,7 +19,7 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.avm2.ConstantPool; import com.jpexs.decompiler.flash.abc.types.traits.Trait; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.graph.ExportMode; @@ -99,20 +99,20 @@ public class MethodCodePanel extends JPanel implements ActionListener { JButton graphButton = new JButton(View.getIcon("graph16")); graphButton.setActionCommand("GRAPH"); graphButton.addActionListener(this); - graphButton.setToolTipText(translate("button.viewgraph")); + graphButton.setToolTipText(AppStrings.translate("button.viewgraph")); graphButton.setMargin(new Insets(3, 3, 3, 3)); hexButton = new JToggleButton(View.getIcon("hex16")); hexButton.setActionCommand("HEX"); hexButton.addActionListener(this); - hexButton.setToolTipText(translate("button.viewhex")); + hexButton.setToolTipText(AppStrings.translate("button.viewhex")); hexButton.setMargin(new Insets(3, 3, 3, 3)); // todo: find icon, and set visible hexOnlyButton = new JToggleButton(View.getIcon("hex16")); hexOnlyButton.setActionCommand("HEXONLY"); hexOnlyButton.addActionListener(this); - hexOnlyButton.setToolTipText(translate("button.viewhex")); + hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex")); hexOnlyButton.setMargin(new Insets(3, 3, 3, 3)); hexOnlyButton.setVisible(false); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java index 80ce266ec..0201ad8cb 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java @@ -21,7 +21,7 @@ import com.jpexs.decompiler.flash.abc.avm2.parser.ASM3Parser; import com.jpexs.decompiler.flash.abc.avm2.parser.ParseException; import com.jpexs.decompiler.flash.abc.types.ValueKind; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.View; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; @@ -114,7 +114,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { return false; } } catch (ParseException ex) { - View.showMessageDialog(slotConstEditor, ex.text, translate("error.slotconst.typevalue"), JOptionPane.ERROR_MESSAGE); + View.showMessageDialog(slotConstEditor, ex.text, AppStrings.translate("error.slotconst.typevalue"), JOptionPane.ERROR_MESSAGE); return false; } catch (UnsupportedEncodingException ex) { Logger.getLogger(SlotConstTraitDetailPanel.class.getName()).log(Level.SEVERE, null, ex); @@ -129,7 +129,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { @Override public void setEditMode(boolean val) { if (val && active) { - JOptionPane.showMessageDialog(null, translate("warning.initializers"), translate("message.warning"), JOptionPane.WARNING_MESSAGE); + JOptionPane.showMessageDialog(null, AppStrings.translate("warning.initializers"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE); } slotConstEditor.setEditable(val); } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java index 19c85daf5..c6085b0af 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java @@ -6,6 +6,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.helpers.HilightedTextWriter; +import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.ExportMode; import java.util.ArrayList; @@ -68,12 +69,12 @@ public class TraitsListItem { public String toString() { String s = ""; if ((type != Type.INITIALIZER) && isStatic) { - abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, ExportMode.SOURCE, scriptIndex, classIndex, new ArrayList(), false); + abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, ExportMode.SOURCE, scriptIndex, classIndex, new NulWriter(), new ArrayList(), false); HilightedTextWriter writer = new HilightedTextWriter(false); abc.class_info[classIndex].static_traits.traits[index].toStringHeader(null, "", abcTags, abc, true, ExportMode.SOURCE, scriptIndex, classIndex, writer, new ArrayList(), false); s = writer.toString(); } else if ((type != Type.INITIALIZER) && (!isStatic)) { - abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, ExportMode.SOURCE, scriptIndex, classIndex, new ArrayList(), false); + abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, ExportMode.SOURCE, scriptIndex, classIndex, new NulWriter(), new ArrayList(), false); HilightedTextWriter writer = new HilightedTextWriter(false); abc.instance_info[classIndex].instance_traits.traits[index].toStringHeader(null, "", abcTags, abc, false, ExportMode.SOURCE, scriptIndex, classIndex, writer, new ArrayList(), false); s = writer.toString(); diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 249c841a1..7bb2b7b65 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -27,7 +27,7 @@ import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser; import com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser; import com.jpexs.decompiler.flash.action.swf4.ActionPush; import com.jpexs.decompiler.flash.action.swf4.ConstantIndex; -import static com.jpexs.decompiler.flash.gui.AppStrings.translate; +import com.jpexs.decompiler.flash.gui.AppStrings; import com.jpexs.decompiler.flash.gui.GraphFrame; import com.jpexs.decompiler.flash.gui.HeaderLabel; import com.jpexs.decompiler.flash.gui.Main; @@ -41,7 +41,9 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.graph.ExportMode; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.helpers.AsyncResult; import com.jpexs.helpers.Cache; +import com.jpexs.helpers.Callback; import com.jpexs.helpers.Helper; import java.awt.BorderLayout; import java.awt.FlowLayout; @@ -59,6 +61,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Scanner; +import java.util.concurrent.Callable; +import java.util.concurrent.FutureTask; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; @@ -84,17 +88,17 @@ public class ActionPanel extends JPanel implements ActionListener { public LineMarkedEditorPane decompiledEditor; public List list; public JSplitPane splitPane; - public JButton saveButton = new JButton(translate("button.save"), View.getIcon("save16")); - public JButton editButton = new JButton(translate("button.edit"), View.getIcon("edit16")); - public JButton cancelButton = new JButton(translate("button.cancel"), View.getIcon("cancel16")); - public JLabel experimentalLabel = new JLabel(translate("action.edit.experimental")); - public JButton editDecompiledButton = new JButton(translate("button.edit"), View.getIcon("edit16")); - public JButton saveDecompiledButton = new JButton(translate("button.save"), View.getIcon("save16")); - public JButton cancelDecompiledButton = new JButton(translate("button.cancel"), View.getIcon("cancel16")); + public JButton saveButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); + public JButton editButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); + public JButton cancelButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); + public JLabel experimentalLabel = new JLabel(AppStrings.translate("action.edit.experimental")); + public JButton editDecompiledButton = new JButton(AppStrings.translate("button.edit"), View.getIcon("edit16")); + public JButton saveDecompiledButton = new JButton(AppStrings.translate("button.save"), View.getIcon("save16")); + public JButton cancelDecompiledButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16")); public JToggleButton hexButton; public JToggleButton hexOnlyButton; - public JLabel asmLabel = new HeaderLabel(translate("panel.disassembled")); - public JLabel decLabel = new HeaderLabel(translate("panel.decompiled")); + public JLabel asmLabel = new HeaderLabel(AppStrings.translate("panel.disassembled")); + public JLabel decLabel = new HeaderLabel(AppStrings.translate("panel.decompiled")); public List decompiledHilights = new ArrayList<>(); public List disassembledHilights = new ArrayList<>(); private boolean ignoreCarret = false; @@ -117,7 +121,8 @@ public class ActionPanel extends JPanel implements ActionListener { private boolean searchIgnoreCase; private boolean searchRegexp; private Cache cache = Cache.getInstance(true); - + private FutureTask setSourceTask; + public void clearCache() { cache.clear(); } @@ -175,9 +180,7 @@ public class ActionPanel extends JPanel implements ActionListener { actions = src.getActions(SWF.DEFAULT_VERSION); } HilightedTextWriter writer = new HilightedTextWriter(true); - src.getActionSourcePrefix(writer); - Action.actionsToSource(actions, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/, writer); - src.getActionSourceSuffix(writer); + Action.actionsToSource(src, actions, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/, writer); List hilights = writer.instructionHilights; String srcNoHex = writer.toString(); cache.put(src, new CachedScript(srcNoHex, hilights)); @@ -220,10 +223,10 @@ public class ActionPanel extends JPanel implements ActionListener { int pos = 0; for (Entry item : asms.entrySet()) { pos++; - String workText = translate("work.searching"); + String workText = AppStrings.translate("work.searching"); String decAdd = ""; if (!isCached(item.getValue())) { - decAdd = ", " + translate("work.decompiling"); + decAdd = ", " + AppStrings.translate("work.decompiling"); } Main.startWork(workText + " \"" + txt + "\"" + decAdd + " - (" + pos + "/" + asms.size() + ") " + item.getKey() + "... "); @@ -243,7 +246,7 @@ public class ActionPanel extends JPanel implements ActionListener { searchPanel.setVisible(true); searchFor = txt; updateSearchPos(); - searchForLabel.setText(translate("search.info").replace("%text%", txt) + " "); + searchForLabel.setText(AppStrings.translate("search.info").replace("%text%", txt) + " "); } return true; } @@ -260,7 +263,7 @@ public class ActionPanel extends JPanel implements ActionListener { lastH = h; } String offset = lastH == null ? "0" : lastH.getPropertyString("offset"); - editor.setText("; " + translate("work.gettinghilights") + "..."); + editor.setText("; " + AppStrings.translate("work.gettinghilights") + "..."); disassembledHilights = text.instructionHilights; String stripped = text.text; /*if(stripped.length()>30000){ @@ -323,7 +326,7 @@ public class ActionPanel extends JPanel implements ActionListener { if (((newpercent > percent) || (!this.phase.equals(phase))) && newpercent <= 100) { percent = newpercent; this.phase = phase; - editor.setText("; " + translate("work.disassembling") + " - " + phase + " " + percent + "%..."); + editor.setText("; " + AppStrings.translate("work.disassembling") + " - " + phase + " " + percent + "%..."); } } }; @@ -331,15 +334,30 @@ public class ActionPanel extends JPanel implements ActionListener { } public void setSource(final ASMSource src, final boolean useCache) { + if (setSourceTask != null) { + setSourceTask.cancel(true); + } + this.src = src; - Main.startWork(translate("work.decompiling") + "..."); - final ASMSource asm = (ASMSource) src; - (new Thread() { + Main.startWork(AppStrings.translate("work.decompiling") + "...", new Runnable() { + @Override public void run() { - editor.setText("; " + translate("work.disassembling") + "..."); + if (setSourceTask != null) { + setSourceTask.cancel(true); + } + editor.setText("; " + AppStrings.translate("work.canceled")); + } + }); + final ASMSource asm = (ASMSource) src; + + FutureTask task = Helper.callAsync(new Callable() { + + @Override + public Void call() throws Exception { + editor.setText("; " + AppStrings.translate("work.disassembling") + "..."); if (Configuration.getConfig("decompile", true)) { - decompiledEditor.setText("//" + translate("work.waitingfordissasembly") + "..."); + decompiledEditor.setText("//" + AppStrings.translate("work.waitingfordissasembly") + "..."); } DisassemblyListener listener = getDisassemblyListener(); asm.addDisassemblyListener(listener); @@ -351,7 +369,7 @@ public class ActionPanel extends JPanel implements ActionListener { srcHexOnly = null; setHex(getExportMode()); if (Configuration.getConfig("decompile", true)) { - decompiledEditor.setText("//" + translate("work.decompiling") + "..."); + decompiledEditor.setText("//" + AppStrings.translate("work.decompiling") + "..."); if (!useCache) { uncache(asm); } @@ -364,9 +382,19 @@ public class ActionPanel extends JPanel implements ActionListener { } setEditMode(false); setDecompiledEditMode(false); + return null; + } + }, new Callback>() { + + @Override + public void call(AsyncResult arg1) { + setSourceTask = null; Main.stopWork(); } - }).start(); + + }); + + setSourceTask = task; } public void hilightOffset(long offset) { @@ -394,7 +422,7 @@ public class ActionPanel extends JPanel implements ActionListener { cancelSearchButton.addActionListener(this); cancelSearchButton.setActionCommand("SEARCHCANCEL"); searchPos = new JLabel("0/0"); - searchForLabel = new JLabel(translate("search.info").replace("%text%", "")); + searchForLabel = new JLabel(AppStrings.translate("search.info").replace("%text%", "")); searchPanel.add(searchForLabel); searchPanel.add(prevSearchButton); searchPanel.add(new JLabel("Script ")); @@ -406,22 +434,22 @@ public class ActionPanel extends JPanel implements ActionListener { JButton graphButton = new JButton(View.getIcon("graph16")); graphButton.setActionCommand("GRAPH"); graphButton.addActionListener(this); - graphButton.setToolTipText(translate("button.viewgraph")); + graphButton.setToolTipText(AppStrings.translate("button.viewgraph")); graphButton.setMargin(new Insets(3, 3, 3, 3)); hexButton = new JToggleButton(View.getIcon("hex16")); hexButton.setActionCommand("HEX"); hexButton.addActionListener(this); - hexButton.setToolTipText(translate("button.viewhex")); + hexButton.setToolTipText(AppStrings.translate("button.viewhex")); hexButton.setMargin(new Insets(3, 3, 3, 3)); // todo: find icon, and set visible hexOnlyButton = new JToggleButton(View.getIcon("hex16")); hexOnlyButton.setActionCommand("HEXONLY"); hexOnlyButton.addActionListener(this); - hexOnlyButton.setToolTipText(translate("button.viewhex")); + hexOnlyButton.setToolTipText(AppStrings.translate("button.viewhex")); hexOnlyButton.setMargin(new Insets(3, 3, 3, 3)); - hexOnlyButton.setVisible(false); + //hexOnlyButton.setVisible(false); topButtonsPan = new JPanel(); topButtonsPan.setLayout(new BoxLayout(topButtonsPan, BoxLayout.X_AXIS)); @@ -681,7 +709,7 @@ public class ActionPanel extends JPanel implements ActionListener { } } else if (e.getActionCommand().equals("EDITACTION")) { setEditMode(true); - } else if (e.getActionCommand().equals("HEX")) { + } else if (e.getActionCommand().equals("HEX") || e.getActionCommand().equals("HEXONLY")) { setHex(getExportMode()); } else if (e.getActionCommand().equals("CANCELACTION")) { setEditMode(false); @@ -695,7 +723,7 @@ public class ActionPanel extends JPanel implements ActionListener { src.setActions(ASMParser.parse(0, src.getPos(), true, text, SWF.DEFAULT_VERSION, false), SWF.DEFAULT_VERSION); } setSource(this.src, false); - View.showMessageDialog(this, translate("message.action.saved")); + View.showMessageDialog(this, AppStrings.translate("message.action.saved")); saveButton.setVisible(false); cancelButton.setVisible(false); editButton.setVisible(true); @@ -703,7 +731,7 @@ public class ActionPanel extends JPanel implements ActionListener { editMode = false; } catch (IOException ex) { } catch (ParseException ex) { - View.showMessageDialog(this, translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), translate("error"), JOptionPane.ERROR_MESSAGE); + View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); } } else if (e.getActionCommand().equals("EDITDECOMPILED")) { setDecompiledEditMode(true); @@ -714,12 +742,12 @@ public class ActionPanel extends JPanel implements ActionListener { ActionScriptParser par = new ActionScriptParser(); src.setActions(par.actionsFromString(decompiledEditor.getText()), SWF.DEFAULT_VERSION); setSource(this.src, false); - View.showMessageDialog(this, translate("message.action.saved")); + View.showMessageDialog(this, AppStrings.translate("message.action.saved")); setDecompiledEditMode(false); } catch (IOException ex) { Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, "IOException during action compiling", ex); } catch (ParseException ex) { - View.showMessageDialog(this, translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), translate("error"), JOptionPane.ERROR_MESSAGE); + View.showMessageDialog(this, AppStrings.translate("error.action.save").replace("%error%", ex.text).replace("%line%", "" + ex.line), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index f848b7b53..6a5c3bec7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -366,3 +366,5 @@ message.font.add.exists = Character %char% already exists in the font tag.\nDo y filter.gfx = ScaleForm GFx files (*.gfx) filter.supported = All supported filetypes (*.swf, *.gfx) +work.canceled = Canceled +work.restoringControlFlow = Restoring control flow diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties index 508a3b95b..038bd6cab 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_hu.properties @@ -369,4 +369,6 @@ button.no.all = Egyik sem message.font.add.exists = %char% karakter m\u00e1r l\u00e9tezik a bet\u0171t\u00edpus tagben.\nSzeretn\u00e9 lecser\u00e9lni? filter.gfx = ScaleForm GFx f\u00e1jlok (*.gfx) -filter.supported = Minden t\u00e1mogatott f\u00e1jlt\u00edpus (*.swf, *.gfx) \ No newline at end of file +filter.supported = Minden t\u00e1mogatott f\u00e1jlt\u00edpus (*.swf, *.gfx) +work.canceled = Megszak\u00edtva +work.restoringControlFlow = Vez\u00e9rl\u00e9si-folyam helyre\u00e1ll\u00edt\u00e1s diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/FileTextWriter.java b/trunk/src/com/jpexs/decompiler/flash/helpers/FileTextWriter.java new file mode 100644 index 000000000..d208a1a83 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/FileTextWriter.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2010-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 . + */ +package com.jpexs.decompiler.flash.helpers; + +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Provides methods for highlighting positions of instructions in the text. + * + * @author JPEXS + */ +public class FileTextWriter extends GraphTextWriter implements AutoCloseable { + + private Writer writer; + private boolean newLine = true; + private int indent; + private int writtenBytes; + + public FileTextWriter(FileOutputStream fos) throws UnsupportedEncodingException { + this.writer = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8")); + } + + @Override + public FileTextWriter hilightSpecial(String text, String type) { + writeToFile(text); + return this; + } + + @Override + public FileTextWriter hilightSpecial(String text, String type, int index) { + writeToFile(text); + return this; + } + + @Override + public FileTextWriter append(String str) { + writeToFile(str); + return this; + } + + @Override + public FileTextWriter append(String str, long offset) { + writeToFile(str); + return this; + } + + @Override + public FileTextWriter appendNoHilight(int i) { + writeToFile(Integer.toString(i)); + return this; + } + + @Override + public FileTextWriter appendNoHilight(String str) { + writeToFile(str); + return this; + } + + @Override + public FileTextWriter indent() { + indent++; + return this; + } + + @Override + public FileTextWriter unindent() { + indent--; + return this; + } + + @Override + public FileTextWriter newLine() { + writeToFile(NEW_LINE); + newLine = true; + return this; + } + + @Override + public int getLength() { + return writtenBytes; + } + + @Override + public int getIndent() { + return indent; + } + + private void writeToFile(String str) { + if (newLine) { + newLine = false; + appendIndent(); + } + try { + writer.write(str); + writtenBytes += str.length(); + } catch (IOException ex) { + Logger.getLogger(FileTextWriter.class.getName()).log(Level.SEVERE, null, ex); + } + } + + private void appendIndent() { + for (int i = 0; i < indent; i++) { + writeToFile(INDENT_STRING); + } + } + + @Override + public void close() throws IOException { + writer.close(); + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java b/trunk/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java index 44747fc2f..d99491c4f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/GraphTextWriter.java @@ -25,7 +25,13 @@ import com.jpexs.decompiler.graph.GraphSourceItem; */ public class GraphTextWriter { + public static final String INDENT_STRING = " "; + public static final String NEW_LINE = "\r\n"; + protected long startTime; + protected long suspendTime; + public GraphTextWriter() { + startTime = System.currentTimeMillis(); } public boolean getIsHighlighted() { @@ -132,9 +138,6 @@ public class GraphTextWriter { return this; } - public void setLength(int length) { - } - public int getLength() { return 0; } @@ -143,15 +146,17 @@ public class GraphTextWriter { return 0; } + public void suspendMeasure() { + suspendTime = System.currentTimeMillis(); + } + + public void continueMeasure() { + long time = System.currentTimeMillis(); + startTime += time - suspendTime; + } + @Override public String toString() { return ""; } - - public void mark() { - } - - public boolean getMark() { - return false; - } } diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java b/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java index 5a3db523f..65592bbf2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/HilightedTextWriter.java @@ -17,8 +17,6 @@ package com.jpexs.decompiler.flash.helpers; import com.jpexs.decompiler.flash.Configuration; -import static com.jpexs.decompiler.flash.helpers.HilightType.CLASS; -import static com.jpexs.decompiler.flash.helpers.HilightType.SPECIAL; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.helpers.Helper; @@ -35,16 +33,11 @@ import java.util.Stack; */ public class HilightedTextWriter extends GraphTextWriter { - public static final String INDENT_STRING = " "; - public static final String NEW_LINE = "\r\n"; private StringBuilder sb = new StringBuilder(); private boolean hilight; private boolean newLine = true; private int indent = 0; private Stack offsets = new Stack<>(); - private Stack stringAddedStack = new Stack<>(); - private boolean stringAdded = false; - private long startTime; private boolean toStringCalled = false; private int newLineCount = 0; @@ -56,12 +49,10 @@ public class HilightedTextWriter extends GraphTextWriter { public List specialHilights = new ArrayList<>(); public HilightedTextWriter(boolean hilight) { - startTime = System.currentTimeMillis(); this.hilight = hilight; } public HilightedTextWriter(boolean hilight, int indent) { - startTime = System.currentTimeMillis(); this.hilight = hilight; this.indent = indent; } @@ -232,29 +223,13 @@ public class HilightedTextWriter extends GraphTextWriter { public HilightedTextWriter stripSemicolon() { // hack if (sb.charAt(sb.length() - 1) == ';') { - sb.setLength(sb.length() - 1); + // todo: remove later + // probably this code branch is not executed anymore + sb.append("TODO_REMOVE_SEMICOLON"); } return this; } - @Override - public void setLength(int length) { - if (length >= sb.length()) { - return; - } - - String remove = sb.substring(length); - int removedNewLines = 0; - for (int i = 0; i < remove.length(); i++) { - if (remove.charAt(i) == '\n') { - removedNewLines++; - } - } - newLineCount -= removedNewLines; - - sb.setLength(length); - } - @Override public int getLength() { return sb.length(); @@ -281,19 +256,6 @@ public class HilightedTextWriter extends GraphTextWriter { return sb.toString(); } - @Override - public void mark() { - stringAddedStack.add(stringAdded); - stringAdded = false; - } - - @Override - public boolean getMark() { - boolean result = stringAdded; - stringAdded = stringAddedStack.pop() || result; - return result; - } - private HilightedTextWriter start(Map data, HilightType type) { if (hilight) { Highlighting h = new Highlighting(sb.length() - newLineCount, data, type, null); @@ -338,7 +300,6 @@ public class HilightedTextWriter extends GraphTextWriter { appendIndent(); } sb.append(str); - stringAdded = true; } private void appendIndent() { diff --git a/trunk/src/com/jpexs/decompiler/flash/helpers/NulWriter.java b/trunk/src/com/jpexs/decompiler/flash/helpers/NulWriter.java index fbe7f9d1d..89090ccc4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/helpers/NulWriter.java +++ b/trunk/src/com/jpexs/decompiler/flash/helpers/NulWriter.java @@ -26,6 +26,8 @@ import java.util.Stack; public class NulWriter extends GraphTextWriter { private Stack loopStack = new Stack<>(); + private Stack stringAddedStack = new Stack<>(); + private boolean stringAdded = false; public NulWriter() { } @@ -87,4 +89,51 @@ public class NulWriter extends GraphTextWriter { loop.used = true; } } + + @Override + public NulWriter hilightSpecial(String text, String type) { + stringAdded = true; + return this; + } + + @Override + public NulWriter hilightSpecial(String text, String type, int index) { + stringAdded = true; + return this; + } + + @Override + public NulWriter append(String str) { + stringAdded = true; + return this; + } + + @Override + public NulWriter append(String str, long offset) { + stringAdded = true; + return this; + } + + @Override + public NulWriter appendNoHilight(int i) { + stringAdded = true; + return this; + } + + @Override + public NulWriter appendNoHilight(String str) { + stringAdded = true; + return this; + } + + public void mark() { + stringAddedStack.add(stringAdded); + stringAdded = false; + } + + public boolean getMark() { + boolean result = stringAdded; + stringAdded = stringAddedStack.pop() || result; + return result; + } } diff --git a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 9a90cbc8d..8c2e3e2e6 100644 --- a/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/trunk/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1113,9 +1113,7 @@ public class XFLConverter { private static String convertActionScript(ASMSource as) { HilightedTextWriter writer = new HilightedTextWriter(false); - as.getActionSourcePrefix(writer); - Action.actionsToSource(as.getActions(SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION, as.toString(), writer); - as.getActionSourceSuffix(writer); + Action.actionsToSource(as, as.getActions(SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION, as.toString(), writer); return writer.toString(); } diff --git a/trunk/src/com/jpexs/helpers/AsyncResult.java b/trunk/src/com/jpexs/helpers/AsyncResult.java new file mode 100644 index 000000000..baee87ae8 --- /dev/null +++ b/trunk/src/com/jpexs/helpers/AsyncResult.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010-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 . + */ +package com.jpexs.helpers; + +/** + * Class with helper method + * + * @author JPEXS + */ +public class AsyncResult { + + public T result; + + public Throwable error; + + public AsyncResult(T result, Throwable error) { + this.result = result; + this.error = error; + } +} diff --git a/trunk/src/com/jpexs/helpers/Callback.java b/trunk/src/com/jpexs/helpers/Callback.java new file mode 100644 index 000000000..07118190f --- /dev/null +++ b/trunk/src/com/jpexs/helpers/Callback.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2010-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 . + */ +package com.jpexs.helpers; + +/** + * Class with helper method + * + * @author JPEXS + */ +public abstract class Callback { + + public abstract void call(T arg1); +} diff --git a/trunk/src/com/jpexs/helpers/Helper.java b/trunk/src/com/jpexs/helpers/Helper.java index 86e098f33..5db7df549 100644 --- a/trunk/src/com/jpexs/helpers/Helper.java +++ b/trunk/src/com/jpexs/helpers/Helper.java @@ -607,7 +607,38 @@ public class Helper { public static T timedCall(Callable c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException { FutureTask task = new FutureTask<>(c); THREAD_POOL.execute(task); - return task.get(timeout, timeUnit); + try { + return task.get(timeout, timeUnit); + } finally { + task.cancel(true); + } + } + + public static FutureTask callAsync(final Callable c) { + return callAsync(c, null); + } + + public static FutureTask callAsync(final Callable c, final Callback> callback) { + FutureTask task = new FutureTask<>(new Callable() { + + @Override + public T call() throws Exception { + try { + T t = c.call(); + if (callback != null) { + callback.call(new AsyncResult<>(t, null)); + } + return t; + } catch (Throwable ex) { + if (callback != null) { + callback.call(new AsyncResult(null, ex)); + } + throw ex; + } + } + }); + THREAD_POOL.execute(task); + return task; } public static boolean contains(int[] array, int value) { @@ -629,4 +660,8 @@ public class Helper { } } } + + public static List timedCall(Callable> callable, int DECOMPILATION_TIMEOUT) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } } diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java index 4e75d8b36..b39d9d037 100644 --- a/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java @@ -41,7 +41,7 @@ public class ActionScript2AssemblerTest extends ActionStript2TestBase { DoActionTag doa = getFirstActionTag(); doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HilightedTextWriter writer = new HilightedTextWriter(false); - Action.actionsToSource(doa.getActions(swf.version), swf.version, "", writer); + Action.actionsToSource(doa, doa.getActions(swf.version), swf.version, "", writer); String actualResult = writer.toString(); writer = new HilightedTextWriter(false); doa.getASMSource(swf.version, ExportMode.PCODE, writer, null); diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java index 5cd40d429..3134f3cd2 100644 --- a/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java @@ -75,7 +75,7 @@ public class ActionScript2DeobfuscatorTest extends ActionStript2TestBase { DoActionTag doa = getFirstActionTag(); doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HilightedTextWriter writer = new HilightedTextWriter(false); - Action.actionsToSource(doa.getActions(swf.version), swf.version, "", writer); + Action.actionsToSource(doa, doa.getActions(swf.version), swf.version, "", writer); String actualResult = writer.toString(); assertTrue(actualResult.contains("case \"c\":")); diff --git a/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java index 12e88ca35..ffcde234a 100644 --- a/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/trunk/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -43,7 +43,7 @@ public class ActionScript2Test extends ActionStript2TestBase { DoActionTag doa = getFrameSource(frame); assertNotNull(doa); HilightedTextWriter writer = new HilightedTextWriter(false); - Action.actionsToSource(doa.getActions(swf.version), swf.version, "", writer); + Action.actionsToSource(doa, doa.getActions(swf.version), swf.version, "", writer); String actualResult = writer.toString().replaceAll("[ \r\n]", ""); expectedResult = expectedResult.replaceAll("[ \r\n]", ""); assertEquals(actualResult, expectedResult); diff --git a/trunk/test/com/jpexs/decompiler/flash/generators/AS2Generator.java b/trunk/test/com/jpexs/decompiler/flash/generators/AS2Generator.java index 74dc1eda0..1f714991a 100644 --- a/trunk/test/com/jpexs/decompiler/flash/generators/AS2Generator.java +++ b/trunk/test/com/jpexs/decompiler/flash/generators/AS2Generator.java @@ -36,7 +36,7 @@ public class AS2Generator { continue; } HilightedTextWriter writer = new HilightedTextWriter(false); - Action.actionsToSource(doa.getActions(swf.version), swf.version, "", writer); + Action.actionsToSource(doa, doa.getActions(swf.version), swf.version, "", writer); String src = writer.toString(); if (src.trim().equals("")) { doa = null;