diff --git a/CHANGELOG.md b/CHANGELOG.md index 22e422b35..076bfe31b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,11 +30,17 @@ All notable changes to this project will be documented in this file. - SWF dependencies label was not updated on startup - [#2127] Wrong parameter order in AS1/2 P-code Action GetURL2 documentation - [#2025], [#2078], [#2053] Problems starting the app on Windows when the username has unicode characters +- Incorrect debugger line numbers when "Open loaded while playing" is enabled +- AS3 debugger - Slow injecting debug info - now faster +- AS3 debugger - obfuscated classes debugging +- Delayed open loaded SWFs while playing +- AS3 Direct editation - script initializer for main document class ### Changed - [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class - [#2127] AS1/2 P-code Action GetURL2 switched parameters back - correct order is (loadVariablesFlag, loadTargetFlag, sendVarsMethod), code from 19.1.x to 20.0.0 is still accepted +- Wrong unicode escape `{invalid_utf8:xxx}` changed to `{invalid_utf8=xxx}` for compatibility with file names ## [20.0.0] - 2023-11-05 ### Added diff --git a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as index 14c813e10..05c9ca248 100644 --- a/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as +++ b/libsrc/debugswf/com/jpexs/decompiler/flash/debugger/DebugConnection.as @@ -26,10 +26,10 @@ private static function sendQueue(){ var qo = q; - q = []; - for each(var m in qo){ - writeMsg(m.data,m.type); - } + q = []; + for each(var m in qo){ + writeMsg(m.data,m.type); + } } private static function writeStringNull(msg){ @@ -119,7 +119,7 @@ if(!inited){ initClient(""); } - if(s.connected){ + if(s.connected){ if(first){ //s.writeByte(0); writeStringNull("debug.version.major="+DEBUG_VERSION_MAJOR+";debug.version.minor="+DEBUG_VERSION_MINOR); @@ -138,12 +138,13 @@ writeBytes(msg); break; case MSG_LOADER_URL_GETBYTES: - writeString(msg); + writeString(msg); break; case MSG_LOADER_BYTES_GETBYTES: writeBytes(msg); break; - } + } + s.flush(); }else{ q.push({type:msgType,data:msg}); } diff --git a/libsrc/debugswf/debug/DOMDocument.xml b/libsrc/debugswf/debug/DOMDocument.xml index 607f86475..2a2022b3c 100644 --- a/libsrc/debugswf/debug/DOMDocument.xml +++ b/libsrc/debugswf/debug/DOMDocument.xml @@ -1,4 +1,4 @@ - + @@ -14,6 +14,15 @@ + + + + + + + + + @@ -25,10 +34,5 @@ - - - - - \ No newline at end of file diff --git a/libsrc/debugswf/debug/META-INF/metadata.xml b/libsrc/debugswf/debug/META-INF/metadata.xml index 1bd11073f..ed05677a5 100644 --- a/libsrc/debugswf/debug/META-INF/metadata.xml +++ b/libsrc/debugswf/debug/META-INF/metadata.xml @@ -5,8 +5,8 @@ xmlns:xmp="http://ns.adobe.com/xap/1.0/"> Adobe Flash Professional CS6 - build 537 2014-10-26T15:59:21+01:00 - 2014-10-27T08:16:09+01:00 - 2014-10-27T08:16:09+01:00 + 2023-11-18T12:05:50-08:00 + 2023-11-18T12:05:50-08:00 @@ -15,7 +15,7 @@ - xmp.iid:A3850720A95DE411873EA2B016962F64 + xmp.iid:CDA31DDF4D86EE11B43B9B2E6D6D7C97 xmp.did:1476A545885CE411B13FACEEFCD7D43C xmp.did:1476A545885CE411B13FACEEFCD7D43C @@ -44,6 +44,12 @@ 2014-10-26T15:59:21+01:00 Adobe Flash Professional CS6 - build 537 + + created + xmp.iid:CDA31DDF4D86EE11B43B9B2E6D6D7C97 + 2014-10-26T15:59:21+01:00 + Adobe Flash Professional CS6 - build 481 + diff --git a/libsrc/debugswf/debug/PublishSettings.xml b/libsrc/debugswf/debug/PublishSettings.xml index dce804882..e317964e7 100644 --- a/libsrc/debugswf/debug/PublishSettings.xml +++ b/libsrc/debugswf/debug/PublishSettings.xml @@ -35,11 +35,11 @@ 0 - 11,4,0,0;11,3,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1; + 11,3,0,0;11,4,0,0;12,0,0,0;11,2,0,0;11,1,0,0;10,3,0,0;10,2,153,0;10,1,52,0;9,0,124,0;8,0,24,0;7,0,14,0;6,0,79,0;5,0,58,0;4,0,32,0;3,0,8,0;2,0,1,12;1,0,0,1; 1 1 - debug_content.html - debug_alternate.html + debug.xfl_content.html + debug.xfl_alternate.html 0 550 @@ -56,7 +56,7 @@ 0 1 0 - C:\Users\Jindra\AppData\Local\Adobe\Flash CS6\en_US\Configuration\HTML\Default.html + C:\Users\MyUser\AppData\Local\Adobe\Flash CS6\en_US\Configuration\HTML\Default.html 1 @@ -72,8 +72,8 @@ 0 7 0 - 17 - FlashPlayer11.4 + 15 + FlashPlayer11.2 3 1 diff --git a/libsrc/debugswf/debug/bin/SymDepend.cache b/libsrc/debugswf/debug/bin/SymDepend.cache index fa0e29a10..ea8830d75 100644 Binary files a/libsrc/debugswf/debug/bin/SymDepend.cache and b/libsrc/debugswf/debug/bin/SymDepend.cache differ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java index cfbaf5f81..a32a41cff 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/DecompilerPool.java @@ -73,6 +73,8 @@ public class DecompilerPool { src.getActionScriptSource(writer, actions); writer.endFunction(); + writer.finishHilights(); + HighlightedText result = new HighlightedText(writer); SWF swf = src.getSwf(); if (swf != null) { @@ -107,6 +109,7 @@ public class DecompilerPool { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); pack.toSource(abcIndex, writer, script == null ? null : script.traits.traits, new ConvertData(), ScriptExportMode.AS, parallel, false); + writer.finishHilights(); HighlightedText result = new HighlightedText(writer); Openable openable = pack.getOpenable(); SWF swf = (openable instanceof SWF) ? (SWF) openable : ((ABC) openable).getSwf(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 1dc302227..195d2e5e4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -94,6 +94,7 @@ import com.jpexs.decompiler.flash.helpers.NulWriter; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.DebugIDTag; import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; @@ -3945,7 +3946,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { * * @param decompileDir Directory to set file information paths */ - public void injectAS3DebugInfo(File decompileDir) throws InterruptedException { + public void injectAS3DebugInfo(File decompileDir) throws InterruptedException { List packs = getAS3Packs(); int i = 0; for (ScriptPack s : packs) { @@ -3954,10 +3955,14 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } i++; informListeners("inject_debuginfo", "" + i + "/" + packs.size() + ": " + s.getPath()); - if (s.isSimple) { - s.injectDebugInfo(decompileDir); + if (s.isSimple) { + try { + s.injectDebugInfo(decompileDir); + } catch (Throwable t) { + Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, "Errorr injecting debug info", t); + } } - } + } } /** @@ -4121,7 +4126,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } catch (InterruptedException ex) { logger.log(Level.SEVERE, null, ex); } - List hls = writer.instructionHilights; + writer.finishHilights(); + HighlightingList hls = writer.instructionHilights; Map offsetToLine = new TreeMap<>(); String txt = writer.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java index d7b5ee0b7..f48426b4b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SourceGeneratorLocalData.java @@ -84,6 +84,8 @@ public class SourceGeneratorLocalData implements Serializable { public List> catchesOpenedLoops = new ArrayList<>(); public List catchesTempRegs = new ArrayList<>(); + + public String documentClass; public boolean secondRun = false; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 082201b93..da8332285 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1186,6 +1186,7 @@ public class AVM2Code implements Cloneable { public String toASMSource(ABC abc, AVM2ConstantPool constants) { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toASMSource(abc, constants, null, null, new ArrayList<>(), ScriptExportMode.PCODE, writer); + writer.finishHilights(); return writer.toString(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java index 7700b00e2..8c11ada3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/construction/NewClassIns.java @@ -45,6 +45,7 @@ public class NewClassIns extends InstructionDefinition { int clsIndex = ins.operands[0]; HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); stack.pop().toString(writer, LocalData.create(localData.callStack /*??*/, localData.abcIndex, localData.abc, localData.localRegNames, localData.fullyQualifiedNames, new HashSet<>())); + writer.finishHilights(); String baseType = writer.toString(); ABC abc = localData.abc; stack.push(new UnparsedAVM2Item(ins, localData.lineStartInstruction, "§§newclass(" + abc.constants.getMultiname(abc.instance_info.get(clsIndex).name_index).getName(localData.getConstants(), localData.fullyQualifiedNames, false, true) + "," + baseType + ")")); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index 9829791b0..01b76286b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -841,6 +841,7 @@ public class AVM2SourceGenerator implements SourceGenerator { newlocalData.traitUsages = localData.traitUsages; newlocalData.currentScript = localData.currentScript; newlocalData.scriptIndex = localData.scriptIndex; + newlocalData.documentClass = localData.documentClass; newlocalData.privateNs = localData.privateNs; newlocalData.protectedNs = localData.protectedNs; newlocalData.isStatic = isStatic; @@ -1815,6 +1816,12 @@ public class AVM2SourceGenerator implements SourceGenerator { mbCode.add(ins(AVM2Instructions.PushScope)); int traitScope = 1; + + String documentClassStr = localData.documentClass; + DottedChain documentClass = null; + if (documentClassStr != null && !documentClassStr.isEmpty()) { + documentClass = DottedChain.parseNoSuffix(documentClassStr); + } Map initScopes = new HashMap<>(); @@ -1823,9 +1830,15 @@ public class AVM2SourceGenerator implements SourceGenerator { TraitClass tc = (TraitClass) t; DottedChain className = tc.getName(abc).getNameWithNamespace(abc.constants, true); + + List parents = new ArrayList<>(); - int[] nsset = new int[]{constants.getMultiname(tc.name_index).namespace_index}; - mbCode.add(ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createMultiname(false, constants.getMultiname(tc.name_index).name_index, constants.getNamespaceSetId(nsset, true)), true))); + if (documentClass != null && documentClass.equals(className)) { + mbCode.add(ins(AVM2Instructions.GetScopeObject, 0)); + } else { + int[] nsset = new int[]{constants.getMultiname(tc.name_index).namespace_index}; + mbCode.add(ins(AVM2Instructions.FindPropertyStrict, constants.getMultinameId(Multiname.createMultiname(false, constants.getMultiname(tc.name_index).name_index, constants.getNamespaceSetId(nsset, true)), true))); + } traitScope++; if (abc.instance_info.get(tc.class_info).isInterface()) { mbCode.add(ins(AVM2Instructions.PushNull)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java index 5d8ba9a39..39b2eb2b0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3Parser.java @@ -2612,10 +2612,11 @@ public class ActionScript3Parser { return ret; } - public void addScriptFromTree(List> allOpenedNamespaces, List items, int classPos) throws AVM2ParseException, CompilationException { + public void addScriptFromTree(List> allOpenedNamespaces, List items, int classPos, String documentClass) throws AVM2ParseException, CompilationException { AVM2SourceGenerator gen = new AVM2SourceGenerator(abcIndex); SourceGeneratorLocalData localData = new SourceGeneratorLocalData( new HashMap<>(), 0, Boolean.FALSE, 0); + localData.documentClass = documentClass; ScriptInfo si = new ScriptInfo(); int scriptIndex = abcIndex.getSelectedAbc().script_info.size(); abcIndex.getSelectedAbc().script_info.add(si); @@ -2629,10 +2630,10 @@ public class ActionScript3Parser { abcIndex.getSelectedAbc().fireChanged(); } - public void addScript(String s, String fileName, int classPos, int scriptIndex) throws AVM2ParseException, IOException, CompilationException, InterruptedException { + public void addScript(String s, String fileName, int classPos, int scriptIndex, String documentClass) throws AVM2ParseException, IOException, CompilationException, InterruptedException { List> allOpenedNamespaces = new ArrayList<>(); List traits = scriptTraitsFromString(allOpenedNamespaces, s, fileName, scriptIndex); - addScriptFromTree(allOpenedNamespaces, traits, classPos); + addScriptFromTree(allOpenedNamespaces, traits, classPos, documentClass); } public ActionScript3Parser(AbcIndexing abcIndex) throws IOException, InterruptedException { @@ -2641,14 +2642,14 @@ public class ActionScript3Parser { this.abcIndex = abcIndex; } - public static void compile(String src, ABC abc, AbcIndexing abcIndex, String fileName, int classPos, int scriptIndex, boolean air) throws AVM2ParseException, IOException, InterruptedException, CompilationException { + public static void compile(String src, ABC abc, AbcIndexing abcIndex, String fileName, int classPos, int scriptIndex, boolean air, String documentClass) throws AVM2ParseException, IOException, InterruptedException, CompilationException { //List parABCs = new ArrayList<>(); SWF.initPlayer(); ActionScript3Parser parser = new ActionScript3Parser(abcIndex); boolean success = false; ABC originalAbc = ((ABCContainerTag) ((Tag) abc.parentTag).cloneTag()).getABC(); try { - parser.addScript(src, fileName, classPos, scriptIndex); + parser.addScript(src, fileName, classPos, scriptIndex, documentClass); success = true; } finally { if (!success) { @@ -2673,7 +2674,7 @@ public class ActionScript3Parser { AbcIndexing abcIndex = swf.getAbcIndex(); abcIndex.selectAbc(abc); ActionScript3Parser parser = new ActionScript3Parser(abcIndex); - parser.addScript(new String(Helper.readFile(src), Utf8Helper.charset), src, classPos, scriptIndex); + parser.addScript(new String(Helper.readFile(src), Utf8Helper.charset), src, classPos, scriptIndex, swf.getDocumentClass()); try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(new File(dst)))) { abc.saveToStream(fos); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index 4ee9b3722..54720651f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -434,6 +434,7 @@ public final class MethodBody implements Cloneable { writer.indent().indent().indent(); toString(callStack, abcIndex, "", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods); writer.unindent().unindent().unindent(); + writer.finishHilights(); return writer.toString(); } catch (InterruptedException ex) { logger.log(Level.SEVERE, null, ex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java index 5ed033066..e004847ee 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/ConstVarMultinameUsage.java @@ -73,6 +73,7 @@ public abstract class ConstVarMultinameUsage extends TraitMultinameUsage { } catch (InterruptedException ex) { // ignore } + writer.finishHilights(); return writer.toString().trim(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java index 34949cd12..e556b9f70 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/usages/MethodMultinameUsage.java @@ -90,6 +90,7 @@ public abstract class MethodMultinameUsage extends TraitMultinameUsage { } ((TraitMethodGetterSetter) traits.traits.get(traitIndex)).toStringHeader(null, convertData, "", abc, traitsType == TRAITS_TYPE_CLASS, ScriptExportMode.AS, -1/*FIXME*/, classIndex, writer, new ArrayList<>(), false, insideInterface); } + writer.finishHilights(); return writer.toString().trim(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java index a8c72834c..cb88c9147 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionList.java @@ -556,6 +556,7 @@ public class ActionList extends ArrayList { public String toString() { HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToString(new ArrayList<>(), 0, this, SWF.DEFAULT_VERSION, ScriptExportMode.PCODE, writer); + writer.finishHilights(); return writer.toString(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java index 04db785ee..172e4c651 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/swf4/ActionPush.java @@ -377,8 +377,9 @@ public class ActionPush extends Action { @Override public String toString() { - HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); + HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toString(writer); + writer.finishHilights(); return writer.toString(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedText.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedText.java index 7bdce45ff..2c44a0be5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedText.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedText.java @@ -17,6 +17,7 @@ package com.jpexs.decompiler.flash.helpers; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; import java.io.Serializable; import java.util.ArrayList; import java.util.List; @@ -32,33 +33,33 @@ public class HighlightedText implements Serializable { public String text; - private final List traitHighlights; + private final HighlightingList traitHighlights; - private final List classHighlights; + private final HighlightingList classHighlights; - private final List methodHighlights; + private final HighlightingList methodHighlights; - private final List instructionHighlights; + private final HighlightingList instructionHighlights; - private final List specialHighlights; + private final HighlightingList specialHighlights; - public List getTraitHighlights() { + public HighlightingList getTraitHighlights() { return traitHighlights; } - public List getMethodHighlights() { + public HighlightingList getMethodHighlights() { return methodHighlights; } - public List getClassHighlights() { + public HighlightingList getClassHighlights() { return classHighlights; } - public List getInstructionHighlights() { + public HighlightingList getInstructionHighlights() { return instructionHighlights; } - public List getSpecialHighlights() { + public HighlightingList getSpecialHighlights() { return specialHighlights; } @@ -77,10 +78,10 @@ public class HighlightedText implements Serializable { public HighlightedText(String text) { this.text = text; - this.traitHighlights = new ArrayList<>(); - this.classHighlights = new ArrayList<>(); - this.methodHighlights = new ArrayList<>(); - this.instructionHighlights = new ArrayList<>(); - this.specialHighlights = new ArrayList<>(); + this.traitHighlights = new HighlightingList(); + this.classHighlights = new HighlightingList(); + this.methodHighlights = new HighlightingList(); + this.instructionHighlights = new HighlightingList(); + this.specialHighlights = new HighlightingList(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java index 13972d3ae..e28cec35b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/HighlightedTextWriter.java @@ -21,10 +21,9 @@ import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; import com.jpexs.decompiler.flash.helpers.hilight.HighlightType; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.helpers.Helper; -import java.util.ArrayList; -import java.util.List; import java.util.Stack; /** @@ -50,16 +49,24 @@ public class HighlightedTextWriter extends GraphTextWriter { private final Stack hilightStack = new Stack<>(); - public List traitHilights = new ArrayList<>(); + public HighlightingList traitHilights = new HighlightingList(); - public List classHilights = new ArrayList<>(); + public HighlightingList classHilights = new HighlightingList(); - public List methodHilights = new ArrayList<>(); + public HighlightingList methodHilights = new HighlightingList(); - public List instructionHilights = new ArrayList<>(); + public HighlightingList instructionHilights = new HighlightingList(); - public List specialHilights = new ArrayList<>(); + public HighlightingList specialHilights = new HighlightingList(); + public void finishHilights() { + traitHilights.finish(); + classHilights.finish(); + methodHilights.finish(); + instructionHilights.finish(); + specialHilights.finish(); + } + public HighlightedTextWriter(CodeFormatting formatting, boolean hilight) { super(formatting); this.hilight = hilight; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/HighlightingList.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/HighlightingList.java new file mode 100644 index 000000000..d3dab5dfd --- /dev/null +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/helpers/hilight/HighlightingList.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2010-2023 JPEXS, All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. + */ +package com.jpexs.decompiler.flash.helpers.hilight; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +/** + * + * @author JPEXS + */ +public class HighlightingList extends ArrayList { + + private boolean finished = false; + + public void finish() { + this.finished = true; + } + + public boolean isFinished() { + return finished; + } + + + private void checkWriteAccess() { + if (finished) { + throw new RuntimeException("Cannot add to readonly list"); + } + } + + @Override + public boolean add(Highlighting e) { + checkWriteAccess(); + return super.add(e); + } + + @Override + public void add(int index, Highlighting element) { + checkWriteAccess(); + super.add(index, element); + } + + @Override + public boolean addAll(Collection c) { + checkWriteAccess(); + return super.addAll(c); + } + + @Override + public boolean addAll(int index, Collection c) { + checkWriteAccess(); + return super.addAll(index, c); + } + + @Override + public boolean remove(Object o) { + checkWriteAccess(); + return super.remove(o); + } + + @Override + public Highlighting remove(int index) { + checkWriteAccess(); + return super.remove(index); + } + + @Override + public boolean removeAll(Collection c) { + checkWriteAccess(); + return super.removeAll(c); + } + + @Override + public boolean removeIf(Predicate filter) { + checkWriteAccess(); + return super.removeIf(filter); + } + + @Override + public void replaceAll(UnaryOperator operator) { + checkWriteAccess(); + super.replaceAll(operator); + } + + @Override + protected void removeRange(int fromIndex, int toIndex) { + checkWriteAccess(); + super.removeRange(fromIndex, toIndex); + } + + @Override + public boolean retainAll(Collection c) { + checkWriteAccess(); + return super.retainAll(c); + } + + @Override + public void clear() { + checkWriteAccess(); + super.clear(); + } + + @Override + public int hashCode() { + return System.identityHashCode(this); + } + + @Override + public boolean equals(Object o) { + return o == this; + } +} diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java index 060889390..dd763084d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/As3ScriptReplaceException.java @@ -29,6 +29,7 @@ public class As3ScriptReplaceException extends Exception { public As3ScriptReplaceException(String message) { super(message); + this.exceptionItems = new ArrayList<>(); } public As3ScriptReplaceException(List exceptionItems) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java index 468a9922f..7bfbe7e00 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/FFDecAs3ScriptReplacer.java @@ -72,7 +72,7 @@ public class FFDecAs3ScriptReplacer implements As3ScriptReplacerInterface { AbcIndexing abcIndex = swf.getAbcIndex(); abcIndex.selectAbc(abc); - ActionScript3Parser.compile(text, abc, abcIndex, scriptName, newClassIndex, oldIndex, air); + ActionScript3Parser.compile(text, abc, abcIndex, scriptName, newClassIndex, oldIndex, air, swf.getDocumentClass()); if (pack.isSimple) { // Move newly added script to its position abc.script_info.set(oldIndex, abc.script_info.get(newIndex)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java index 898b358bb..6b3d12459 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/search/ActionScriptSearch.java @@ -72,6 +72,7 @@ public class ActionScriptSearch { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); asm.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String text = writer.toString(); if (pat.matcher(text).find()) { found.add(new ActionSearchResult(asm, pcode, item.getKey())); @@ -187,6 +188,7 @@ public class ActionScriptSearch { MethodBody body = abc.bodies.get(bodyIndex); HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), true); abc.bodies.get(bodyIndex).getCode().toASMSource(abc, abc.constants, abc.method_info.get(body.method_info), body, ScriptExportMode.PCODE, writer); + writer.finishHilights(); String text = writer.toString(); if (pat.matcher(text).find()) { ABCSearchResult searchResult = new ABCSearchResult(pack, methodInfo.getClassIndex(), methodInfo.getTraitId()); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index 1daaad54a..ce138c388 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -636,6 +636,7 @@ public class DefineEditTextTag extends TextTag { String text = initialText.replace("\\", "\\\\").replace("[", "\\[").replace("]", "\\]"); writer.hilightSpecial(text, HighlightSpecialType.TEXT); } + writer.finishHilights(); return new HighlightedText(writer); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java index 93952c0ff..489edf03f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/StaticTextTag.java @@ -309,6 +309,7 @@ public abstract class StaticTextTag extends TextTag { } } } + writer.finishHilights(); return new HighlightedText(writer); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index 7c875d051..874311db4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1654,6 +1654,7 @@ public class XFLConverter { } catch (InterruptedException ex) { logger.log(Level.SEVERE, null, ex); } + writer.finishHilights(); return writer.toString(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 3117a9916..3c3197f8c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -328,6 +328,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { public String toString(LocalData localData) throws InterruptedException { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toString(writer, localData); + writer.finishHilights(); return writer.toString(); } @@ -422,6 +423,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { try { HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false); toStringNoQuotes(writer, localData); + writer.finishHilights(); return writer.toString(); } catch (InterruptedException ex) { //ignore diff --git a/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/Utf8Helper.java b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/Utf8Helper.java index d0cf8d6cb..affef52c6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/Utf8Helper.java +++ b/libsrc/ffdec_lib/src/com/jpexs/helpers/utf8/Utf8Helper.java @@ -104,19 +104,30 @@ public class Utf8Helper { } } + public static String stripEscapes(String string) { + return string.replaceAll("\\{invalid_utf8=[0-9]+\\}", "") + .replaceAll("\\{\\+(\\+*invalid_utf8=[0-9]+)\\}", "{$1}"); + } + public static byte[] getBytes(String string) { - if (!string.contains("{invalid_utf8:")) { + if (!string.contains("invalid_utf8")) { return string.getBytes(charset); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { - Pattern invPattern = Pattern.compile("^(\\{invalid_utf8:([0-9]+)\\}).*", Pattern.DOTALL); + Pattern invPattern = Pattern.compile("^(\\{invalid_utf8[=:]([0-9]+)\\}).*", Pattern.DOTALL); for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); + char c = string.charAt(i); if (c == '{') { String subStr = string.substring(i); + if (!subStr.isEmpty() && subStr.charAt(0) == '+') { + baos.write(("" + c).getBytes(charset)); + i++; + continue; + } + Matcher m = invPattern.matcher(subStr); if (m.matches()) { int v = Integer.parseInt(m.group(2)); @@ -125,6 +136,7 @@ public class Utf8Helper { i--; continue; } + } baos.write(("" + c).getBytes(charset)); } @@ -141,7 +153,8 @@ public class Utf8Helper { } private static String escapeInvalidUtf8Char(int v) { - return "{invalid_utf8:" + v + "}"; + //Note: for writing the string "{invalid_utf8=xxx}" itself, you can escape it with "{+invalid_utf8=xxx}" + return "{invalid_utf8=" + v + "}"; } public static String decode(byte[] data) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionDefineFunctionPushRegisterCleanerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionDefineFunctionPushRegisterCleanerTest.java index 7c6a667fa..8199c808a 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionDefineFunctionPushRegisterCleanerTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionDefineFunctionPushRegisterCleanerTest.java @@ -58,6 +58,7 @@ public class ActionDefineFunctionPushRegisterCleanerTest extends ActionScript2Te } catch (InterruptedException ex) { fail(); } + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); String expectedResult = cleanPCode("class " + testClassName + "\r\n" + "{\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java index 7dc214681..d16b2f15c 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java @@ -57,6 +57,7 @@ public class ActionScript2AssemblerTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); return writer.toString(); } catch (IOException | ActionParseException | InterruptedException ex) { fail(); @@ -78,7 +79,7 @@ public class ActionScript2AssemblerTest extends ActionScript2TestBase { } catch (InterruptedException ex) { fail(); } - + writer.finishHilights(); return writer.toString(); } catch (IOException | ActionParseException ex) { fail(); @@ -100,7 +101,7 @@ public class ActionScript2AssemblerTest extends ActionScript2TestBase { } catch (InterruptedException ex) { fail(); } - + writer.finishHilights(); return writer.toString(); } catch (IOException | ActionParseException ex) { fail(); @@ -126,9 +127,11 @@ public class ActionScript2AssemblerTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(new HashMap<>(),doa, doa.getActions(), "", writer, swf.getCharset()); + writer.finishHilights(); String actualResult = writer.toString(); writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String decompiled = writer.toString(); assertEquals(actualResult.trim(), "ok = false;"); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ClassesTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ClassesTest.java index e40b2db5c..72c3bc2a8 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ClassesTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ClassesTest.java @@ -59,6 +59,7 @@ public class ActionScript2ClassesTest extends ActionScript2TestBase { } catch (InterruptedException ex) { fail(); } + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); String expectedResult = cleanPCode("class " + BASE_TEST_PACKAGE + "." + testClassName + "\r\n" + "{\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java index eb6049b2c..c633f10d6 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java @@ -69,6 +69,7 @@ public class ActionScript2CompilerTest extends ActionScript2TestBase { asm.setActionBytes(Action.actionsToBytes(asm.getActions(), true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String actualResult = normalizeLabels(writer.toString()); actualResult = cleanPCode(actualResult); String expectedResult = cleanPCode(expectedPCode); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java index 3f3f07f1f..a6693c2dc 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java @@ -63,6 +63,7 @@ public class ActionScript2DeobfuscatorTest extends ActionScript2TestBase { byte[] hex = Action.actionsToBytes(actions, true, SWF.DEFAULT_VERSION); ActionList list = ActionListReader.readActionListTimeout(new ArrayList<>(), new SWFInputStream(swf, hex), SWF.DEFAULT_VERSION, 0, hex.length, "", 1); Action.actionsToSource(new HashMap<>(), null, list, "", writer, Utf8Helper.charsetName); + writer.finishHilights(); return writer.toString(); } @@ -257,6 +258,7 @@ public class ActionScript2DeobfuscatorTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(new HashMap<>(), doa, doa.getActions(), "", writer, swf.getCharset()); + writer.finishHilights(); String actualResult = writer.toString(); assertTrue(actualResult.contains("case \"c\":")); @@ -282,6 +284,7 @@ public class ActionScript2DeobfuscatorTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(new HashMap<>(), doa, doa.getActions(), "", writer, swf.getCharset()); + writer.finishHilights(); String actualResult = writer.toString(); assertTrue(!actualResult.contains("FAIL")); @@ -309,6 +312,7 @@ public class ActionScript2DeobfuscatorTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(new HashMap<>(), doa, doa.getActions(), "", writer, swf.getCharset()); + writer.finishHilights(); String actualResult = writer.toString(); assertTrue(!actualResult.contains("FAIL")); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java index bc731c55e..ba1e29561 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java @@ -81,6 +81,7 @@ public class ActionScript2ModificationTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String actualResult = normalizeLabels(writer.toString()); actualResult = cleanPCode(actualResult); @@ -107,6 +108,7 @@ public class ActionScript2ModificationTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String actualResult = normalizeLabels(writer.toString()); actualResult = cleanPCode(actualResult); @@ -133,6 +135,7 @@ public class ActionScript2ModificationTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String actualResult = normalizeLabels(writer.toString()); actualResult = cleanPCode(actualResult); @@ -156,6 +159,7 @@ public class ActionScript2ModificationTest extends ActionScript2TestBase { doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); doa.getASMSource(ScriptExportMode.PCODE, writer, null); + writer.finishHilights(); String actualResult = normalizeLabels(writer.toString()); actualResult = cleanPCode(actualResult); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java index c7a63c4c5..0b1916049 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2Test.java @@ -60,6 +60,7 @@ public class ActionScript2Test extends ActionScript2TestBase { } catch (InterruptedException ex) { fail(); } + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); expectedResult = cleanPCode(expectedResult); assertEquals(actualResult, expectedResult); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2UninitializedFieldsTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2UninitializedFieldsTest.java index f3fbb76b8..f3e9922b7 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2UninitializedFieldsTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2UninitializedFieldsTest.java @@ -59,6 +59,7 @@ public class ActionScript2UninitializedFieldsTest extends ActionScript2TestBase } catch (InterruptedException ex) { fail(); } + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); String expectedResult = cleanPCode("class " + BASE_TEST_PACKAGE + "." + testClassName + "\r\n" + "{\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index 2f170ba27..56f78c490 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -115,6 +115,7 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas return; } Configuration.autoDeobfuscate.set(false); + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); expectedResult = cleanPCode(expectedResult); assertEquals(actualResult, expectedResult); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java index fe69ac390..9a79fc629 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DeobfuscatorTest.java @@ -100,6 +100,7 @@ public class ActionScript3DeobfuscatorTest extends ActionScriptTestBase { deobfuscator.avm2CodeRemoveTraps("test", 0, true, 0, abc, null, 0, b); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); code.toASMSource(abc, abc.constants, new MethodInfo(), new MethodBody(abc, new Traits(), new byte[0], new ABCException[0]), ScriptExportMode.PCODE, writer); + writer.finishHilights(); String ret = writer.toString(); ret = ret.replaceAll("\r\n +", "\r\n"); String prefix = "\r\ncode\r\n"; @@ -134,9 +135,10 @@ public class ActionScript3DeobfuscatorTest extends ActionScriptTestBase { index.rebuildPkgToObjectsNameMap(); ActionScript3Parser par = new ActionScript3Parser(index); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); - par.addScript(str, "Test.as", 0, 0); + par.addScript(str, "Test.as", 0, 0, swf.getDocumentClass()); abc.script_info.get(0).getPacks(abc, 0, "", new ArrayList<>()).get(0).toSource(swf.getAbcIndex(), writer, abc.script_info.get(0).traits.traits, new ConvertData(), ScriptExportMode.AS, false, false); + writer.finishHilights(); return writer.toString(); } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java index 37219666b..0d72ebe83 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java @@ -66,6 +66,7 @@ public class ActionScript3OptinalParametersTest extends ActionScript3DecompileTe assertTrue(bodyIndex > -1); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); abc.method_info.get(methodInfo).getParamStr(writer, abc.constants, abc.bodies.get(bodyIndex), abc, new ArrayList<>()); + writer.finishHilights(); String actualResult = writer.toString().replaceAll("[ \r\n]", ""); String expectedResult = "p1:Event=null,p2:Number=1,p3:Number=-1,p4:Number=-1.1,p5:Number=-1.1,p6:String=\"a\""; expectedResult = expectedResult.replaceAll("[ \r\n]", ""); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java index 7a5f3192a..dbec37687 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java @@ -92,6 +92,7 @@ public class DirectEditingTest extends FileTestBase { System.out.println("Recompiling:" + classPathString + "..."); try { en.toSource(swf.getAbcIndex(), htw, abc.script_info.get(s).traits.traits, new ConvertData(), ScriptExportMode.AS, false, false); + htw.finishHilights(); String original = htw.toString(); abc.replaceScriptPack(As3ScriptReplacerFactory.createFFDec() /*TODO: test the otherone*/, en, original, new ArrayList<>()); } catch (As3ScriptReplaceException ex) { @@ -109,6 +110,7 @@ public class DirectEditingTest extends FileTestBase { try { HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); + writer.finishHilights(); String as = writer.toString(); //as = asm.removePrefixAndSuffix(as); @@ -120,6 +122,7 @@ public class DirectEditingTest extends FileTestBase { } writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); + writer.finishHilights(); String as2 = writer.toString(); //as2 = asm.removePrefixAndSuffix(as2); try { @@ -129,6 +132,7 @@ public class DirectEditingTest extends FileTestBase { } writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); + writer.finishHilights(); String as3 = writer.toString(); //as3 = asm.removePrefixAndSuffix(as3); if (!as3.equals(as2)) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java index c885553fe..664b18ec6 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassTest.java @@ -72,6 +72,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase { } catch (InterruptedException ex) { fail(); } + writer.finishHilights(); String actualResult = cleanPCode(writer.toString()); expectedResult = cleanPCode(expectedResult); assertEquals(actualResult, expectedResult); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS2Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS2Generator.java index b41b6764d..1a0a37b6d 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS2Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS2Generator.java @@ -57,6 +57,7 @@ public class AS2Generator { } HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(new HashMap<>() /*FIXME*/,doa, doa.getActions(), "", writer, Utf8Helper.charsetName); + writer.finishHilights(); String src = writer.toString(); if (src.trim().isEmpty()) { doa = null; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java index fad8a1fe3..cec380846 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/generators/AS3Generator.java @@ -161,6 +161,7 @@ public class AS3Generator { callStack.add(b); b.convert(callStack, swf.getAbcIndex(), new ConvertData(), "", ScriptExportMode.AS, false, ((TraitMethodGetterSetter) t).method_info, pack.scriptIndex, classId, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), abc.instance_info.get(classId).instance_traits, true, new HashSet<>()); b.toString(callStack, swf.getAbcIndex(), "", ScriptExportMode.AS, abc, null, src, new ArrayList<>(), new HashSet<>()); + src.finishHilights(); String[] srcs = src.toString().split("[\r\n]+"); for (int i = 0; i < srcs.length; i++) { String ss = srcs[i]; diff --git a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java index 57db4ef5a..cb21f08c5 100644 --- a/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java +++ b/src/com/jpexs/decompiler/flash/gui/DebuggerHandler.java @@ -577,8 +577,7 @@ public class DebuggerHandler implements DebugConnectionListener { } Main.getMainFrame().getPanel().updateMenu(); - boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3()); - + //enlog(DebuggerConnection.class); //enlog(DebuggerCommands.class); //enlog(DebuggerHandler.class); @@ -608,6 +607,7 @@ public class DebuggerHandler implements DebugConnectionListener { final Pattern patAS3 = Pattern.compile("^(.*);(.*);(.*)\\.as$"); final Pattern patAS3PCode = Pattern.compile("^#PCODE abc:([0-9]+),script:([0-9]+),class:(-?[0-9]+),trait:(-?[0-9]+),method:([0-9]+),body:([0-9]+);(.*)$"); + boolean isAS3 = (Main.getMainFrame().getPanel().getCurrentSwf().isAS3()); try { con.addMessageListener(new DebugMessageListener() { @@ -627,14 +627,15 @@ public class DebuggerHandler implements DebugConnectionListener { moduleToSwfIndex.put(sc.module, sc.swfIndex); int file = sc.module; String name = sc.name; - String[] parts = name.split(";"); - + + + name = name.replaceAll("\\[(invalid_utf8=[0-9]+)\\]", "{$1}"); + Matcher m; if ((m = patAS3.matcher(name)).matches()) { - String clsNameWithSuffix = m.group(3); - String pkg = m.group(2).replace("\\", "."); + String clsNameWithSuffix = m.group(3).replace("{{semicolon}}", ";"); + String pkg = m.group(2).replace("{{semicolon}}", ";").replace("\\", "."); m = patAS3PCode.matcher(name); - if (m.matches()) { moduleToClassIndex.put(file, Integer.parseInt(m.group(3))); moduleToTraitIndex.put(file, Integer.parseInt(m.group(4))); @@ -642,7 +643,7 @@ public class DebuggerHandler implements DebugConnectionListener { name = DottedChain.parseWithSuffix(pkg).addWithSuffix(clsNameWithSuffix).toString(); name = "#PCODE abc:" + m.group(1) + ",body:" + m.group(6) + ";" + name; } else { - name = DottedChain.parseWithSuffix(pkg).addWithSuffix(clsNameWithSuffix).toString(); + name = DottedChain.parseWithSuffix(pkg).addWithSuffix(clsNameWithSuffix).toPrintableString(con.isAS3); } } Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "Script added - index {0} name: {1}", new Object[]{file, name}); @@ -762,7 +763,7 @@ public class DebuggerHandler implements DebugConnectionListener { } else if (reasonInt != InBreakReason.REASON_SCRIPT_LOADED) { Logger.getLogger(DebuggerCommands.class.getName()).log(Level.SEVERE, "Invalid file: {0}", message.file); - return; + //return; } final String[] reasonNames = new String[]{"unknown", "breakpoint", "watch", "fault", "stopRequest", "step", "halt", "scriptLoaded"}; diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index bad77df4c..5d2c0b5fd 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -456,8 +456,6 @@ public class Main { @Override public SWF prepare(SWF instrSWF) throws InterruptedException { - instrSWF = super.prepare(instrSWF); - EventListener prepEventListner = new EventListener() { @Override public void handleExportingEvent(String type, int index, int count, Object data) { @@ -525,6 +523,9 @@ public class Main { //ignore, return instrSWF } instrSWF.removeEventListener(prepEventListner); + + instrSWF = super.prepare(instrSWF); + return instrSWF; } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java index e3259755a..c957edaf1 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ASMSourceEditorPane.java @@ -152,6 +152,7 @@ public class ASMSourceEditorPane extends DebuggableEditorPane implements CaretLi } writer.appendNoHilight("end ; trait").newLine(); } + writer.finishHilights(); return new HighlightedText(writer); } @@ -180,6 +181,7 @@ public class ASMSourceEditorPane extends DebuggableEditorPane implements CaretLi if (bodyIndex > -1) { Helper.byteArrayToHexWithHeader(writer, abc.bodies.get(bodyIndex).getCodeBytes()); } + writer.finishHilights(); textHexOnly = new HighlightedText(writer); } setText(textHexOnly); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ClassTraitDetailPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ClassTraitDetailPanel.java index 6cbe8d8d9..6734bb096 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ClassTraitDetailPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ClassTraitDetailPanel.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.gui.ViewMessages; import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; import com.jpexs.decompiler.flash.tags.Tag; import java.awt.BorderLayout; import java.io.IOException; @@ -51,7 +52,7 @@ public class ClassTraitDetailPanel extends JPanel implements TraitDetail { private TraitClass trait; - private List specialHilights; + private HighlightingList specialHilights; private boolean ignoreCaret = false; @@ -103,6 +104,7 @@ public class ClassTraitDetailPanel extends JPanel implements TraitDetail { writer.unindent(); } writer.appendNoHilight("end ; trait"); + writer.finishHilights(); String s = writer.toString(); specialHilights = writer.specialHilights; classEditor.setText(s); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java index 0f8d26e65..064789d0e 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/SlotConstTraitDetailPanel.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.gui.ViewMessages; import com.jpexs.decompiler.flash.gui.editor.LineMarkedEditorPane; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; +import com.jpexs.decompiler.flash.helpers.hilight.HighlightingList; import com.jpexs.decompiler.flash.tags.Tag; import java.awt.BorderLayout; import java.io.IOException; @@ -53,7 +54,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { private boolean showWarning = false; - private List specialHilights; + private HighlightingList specialHilights; private boolean ignoreCaret = false; @@ -105,6 +106,7 @@ public class SlotConstTraitDetailPanel extends JPanel implements TraitDetail { writer.unindent(); } writer.appendNoHilight("end ; trait"); + writer.finishHilights(); String s = writer.toString(); specialHilights = writer.specialHilights; showWarning = trait.isConst() || isStatic; diff --git a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java index 4aaaa2b5c..fd15112ad 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java @@ -112,6 +112,7 @@ public class TraitsListItem { insideInterface = abc.instance_info.get(classIndex).isInterface(); } trait.toStringHeader(null, convertData, "", abc, true, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); + writer.finishHilights(); s = writer.toString(); } else { ConvertData convertData = new ConvertData(); @@ -127,6 +128,7 @@ public class TraitsListItem { insideInterface = abc.instance_info.get(classIndex).isInterface(); } trait.toStringHeader(null, convertData, "", abc, false, ScriptExportMode.AS, scriptIndex, classIndex, writer, new ArrayList<>(), false, insideInterface); + writer.finishHilights(); s = writer.toString(); } } catch (InterruptedException ex) { diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index 6947fc944..5d45a788a 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -398,6 +398,7 @@ public class ActionPanel extends JPanel implements SearchListener