diff --git a/lib/jsyntaxpane-0.9.5.jar b/lib/jsyntaxpane-0.9.5.jar index d1549edd4..fecf0721a 100644 Binary files a/lib/jsyntaxpane-0.9.5.jar and b/lib/jsyntaxpane-0.9.5.jar differ diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java index 9e561f9c8..9fc0a2f74 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java @@ -17,12 +17,22 @@ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.abc.RenameType; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation; +import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptLexer; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.ParsedSymbol; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.SymbolType; +import com.jpexs.decompiler.flash.asdoc.ActionScriptDocParser; +import com.jpexs.decompiler.flash.asdoc.AsDocComment; +import com.jpexs.decompiler.flash.asdoc.AsDocTag; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.tags.DefineSpriteTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.model.DocCommentItem; +import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.helpers.Cache; import com.jpexs.helpers.Helper; import java.util.ArrayList; @@ -34,6 +44,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.regex.Pattern; +import natorder.NaturalOrderComparator; /** * Identifiers deobfuscation. @@ -42,6 +53,11 @@ import java.util.regex.Pattern; */ public class IdentifiersDeobfuscation { + /** + * Prefix to be put instead of obfuscated name. It will by suffixed with a number. + */ + public static final String SAFE_STR_PREFIX = "_SafeStr_"; + /** * Random number generator. */ @@ -528,11 +544,27 @@ public class IdentifiersDeobfuscation { /** * Appends obfuscated identifier. * - * @param s String + * @param swf SWF + * @param used Used deobfuscations + * @param s String * @param writer Writer * @return Writer */ - public static GraphTextWriter appendObfuscatedIdentifier(String s, GraphTextWriter writer) { + public static GraphTextWriter appendObfuscatedIdentifier(SWF swf, Set used, String s, GraphTextWriter writer) { + Map map = new LinkedHashMap<>(); + if (Configuration.useSafeStr.get() && swf != null) { + map = swf.getObfuscatedIdentifiersMap(); + used.add(s); + if (map.containsKey(s)) { + writer.append(map.get(s)); + } else { + String ret = IdentifiersDeobfuscation.SAFE_STR_PREFIX + map.size(); + map.put(s, ret); + writer.append(ret); + } + return writer; + } + writer.append("\u00A7"); escapeOIdentifier(s, writer); return writer.append("\u00A7"); @@ -554,15 +586,22 @@ public class IdentifiersDeobfuscation { return ""; } - if (Configuration.useSafeStr.get() && as3) { + Map map = new LinkedHashMap<>(); + if (Configuration.useSafeStr.get()) { + + if (swf != null) { + map = swf.getObfuscatedIdentifiersMap(); + } - Map map = swf == null ? new LinkedHashMap<>() : swf.getAs3ObfuscatedIdentifiers(); if (map.containsKey(s)) { used.add(s); return map.get(s); } } - + + + + if (s.startsWith("\u00A7") && s.endsWith("\u00A7")) { // Assuming already printed - TODO:detect better return s; } @@ -584,6 +623,13 @@ public class IdentifiersDeobfuscation { return s; } + if (Configuration.useSafeStr.get()) { + String ret = IdentifiersDeobfuscation.SAFE_STR_PREFIX + map.size(); + map.put(s, ret); + used.add(s); + return ret; + } + String ret = "\u00A7" + escapeOIdentifier(s) + "\u00A7"; nameCache.put(s, ret); return ret; @@ -744,4 +790,55 @@ public class IdentifiersDeobfuscation { as2NameCache.clear(); as3NameCache.clear(); } + + @SuppressWarnings("unchecked") + public static GraphTextWriter writeCurrentScriptReplacements(GraphTextWriter writer, Set usedDeobfuscations, SWF swf) { + if (!usedDeobfuscations.isEmpty()) { + writer.newLine(); + List commentLines = new ArrayList<>(); + Map fullMap = swf.getObfuscatedIdentifiersMap(); + int i = 0; + for (String obfuscated : usedDeobfuscations) { + String deobfuscated = fullMap.get(obfuscated); + commentLines.add("@identifier " + deobfuscated + " = \"" + Helper.escapePCodeString(obfuscated) + "\""); + i++; + } + commentLines.sort(new NaturalOrderComparator()); + commentLines.add(0, AppResources.translate("decompilationWarning.obfuscatedIdentifiers")); + commentLines.add(1, AppResources.translate("decompilationWarning.replacementsFollow")); + String[] commentLinesArr = commentLines.toArray(new String[commentLines.size()]); + new DocCommentItem(commentLinesArr).appendTo(writer, LocalData.empty); + } + return writer; + } + + public static Map getReplacementsFromDoc(String s) throws Exception { + ActionScriptDocParser asd = new ActionScriptDocParser(); + List comments = asd.parse(s); + Map replacements = new LinkedHashMap<>(); + for (AsDocComment comment:comments) { + for (AsDocTag tag : comment.tags) { + if ("identifier".equals(tag.tagName)) { + String tagText = tag.tagText; + if (tagText != null && !tagText.isEmpty()) { + ActionScriptLexer lexer = new ActionScriptLexer(tagText); + ParsedSymbol symb = lexer.yylex(); + if (symb.type != SymbolType.IDENTIFIER) { + throw new Exception("Invalid @identifier AsDoc tag value. Identifier expected."); + } + ParsedSymbol symb2 = lexer.yylex(); + if (symb2.type != SymbolType.ASSIGN) { + throw new Exception("Invalid @identifier AsDoc tag value. Assign expected."); + } + ParsedSymbol symb3 = lexer.yylex(); + if (symb3.type != SymbolType.STRING) { + throw new Exception("Invalid @identifier AsDoc tag value. String expected."); + } + replacements.put(symb.value.toString(), symb3.value.toString()); + } + } + } + } + return replacements; + } } 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 2b3cf64e9..7607e6856 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -672,7 +672,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { /** * AS3 obfuscated identifiers map */ - private transient Map as3ObfuscatedIdentifiersMap = null; + private transient Map obfuscatedIdentifiersMap = null; /** * Lock for characters synchronization @@ -4002,21 +4002,23 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { } /** - * Gets all AS3 obfuscated identifiers in this SWF and their suggested SafeStr replacement + * Gets obfuscated identifiers map in this SWF and their suggested SafeStr replacement. + * For AS3 it calculates all replacements on first call. + * For AS1/2 it adds new items as they are opened in FFDec * @return Map source identifier to SafeStr replacement */ - public synchronized Map getAs3ObfuscatedIdentifiers() { - if (as3ObfuscatedIdentifiersMap != null) { - return as3ObfuscatedIdentifiersMap; + public synchronized Map getObfuscatedIdentifiersMap() { + if (obfuscatedIdentifiersMap != null) { + return obfuscatedIdentifiersMap; } - Map ret = new LinkedHashMap<>(); + Map ret = Collections.synchronizedMap(new LinkedHashMap<>()); for (Tag tag : getTags()) { if (tag instanceof ABCContainerTag) { ABCContainerTag abcTag = (ABCContainerTag) tag; abcTag.getABC().getObfuscatedIdentifiers(ret); } } - return as3ObfuscatedIdentifiersMap = ret; + return obfuscatedIdentifiersMap = ret; } /** @@ -4535,7 +4537,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { asmsCache = null; asmsCacheExportFilenames = null; synchronized (this) { - as3ObfuscatedIdentifiersMap = null; + obfuscatedIdentifiersMap = null; } IdentifiersDeobfuscation.clearCache(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index d22f2c480..5992374fa 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.AppResources; import com.jpexs.decompiler.flash.DeobfuscationListener; import com.jpexs.decompiler.flash.EndOfStreamException; import com.jpexs.decompiler.flash.EventListener; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; @@ -658,7 +659,7 @@ public class ABC implements Openable { return; } - ret.put(s, AVM2Deobfuscation.SAFE_STR_PREFIX + ret.size()); + ret.put(s, IdentifiersDeobfuscation.SAFE_STR_PREFIX + ret.size()); } private void getObfuscatedPackageIdentifier(int strIndex, Map ret) { @@ -680,8 +681,8 @@ public class ABC implements Openable { List deobfuscatedList = new ArrayList<>(); for (String part : parts) { if (!deobfuscation.isValidNSPart(part)) { - deobfuscatedList.add(AVM2Deobfuscation.SAFE_STR_PREFIX + ret.size()); - ret.put(part, AVM2Deobfuscation.SAFE_STR_PREFIX + ret.size()); + deobfuscatedList.add(IdentifiersDeobfuscation.SAFE_STR_PREFIX + ret.size()); + ret.put(part, IdentifiersDeobfuscation.SAFE_STR_PREFIX + ret.size()); } else { deobfuscatedList.add(part); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index 163bfda53..9c2615fb3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.abc; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.avm2.ConvertException; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; @@ -466,21 +467,7 @@ public class ScriptPack extends AS3ClassTreeItem { } } } - if (!usedDeobfuscations.isEmpty()) { - writer.newLine(); - List commentLines = new ArrayList<>(); - Map fullMap = abc.getSwf().getAs3ObfuscatedIdentifiers(); - int i = 0; - for (String obfuscated : usedDeobfuscations) { - String deobfuscated = fullMap.get(obfuscated); - commentLines.add("@identifier " + deobfuscated + " = \"" + Helper.escapePCodeString(obfuscated) + "\""); - i++; - } - commentLines.sort(new NaturalOrderComparator()); - commentLines.add(0, "The original code has obfuscated identifiers. List of replacements follows:"); - String[] commentLinesArr = commentLines.toArray(new String[commentLines.size()]); - new DocCommentItem(commentLinesArr).appendTo(writer, LocalData.empty); - } + IdentifiersDeobfuscation.writeCurrentScriptReplacements(writer, usedDeobfuscations, abc.getSwf()); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java index 9263b95f2..27b56823d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java @@ -33,9 +33,7 @@ import java.util.regex.Pattern; * * @author JPEXS */ -public class AVM2Deobfuscation { - - public static final String SAFE_STR_PREFIX = "_SafeStr_"; +public class AVM2Deobfuscation { /** * Default size of random word. 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 64b97bf22..92f8134e3 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 @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.abc.ABC; @@ -3023,33 +3024,11 @@ public class ActionScript3Parser { * @throws CompilationException On compilation error * @throws InterruptedException On interrupt */ - public void addScript(String s, String fileName, int classPos, int scriptIndex, String documentClass, ABC abc) throws AVM2ParseException, IOException, CompilationException, InterruptedException { - - replacements.clear(); - ActionScriptDocParser asd = new ActionScriptDocParser(); - List comments = asd.parse(s); - for (AsDocComment comment:comments) { - for (AsDocTag tag : comment.tags) { - if ("identifier".equals(tag.tagName)) { - String tagText = tag.tagText; - if (tagText != null && !tagText.isEmpty()) { - ActionScriptLexer lexer = new ActionScriptLexer(tagText); - ParsedSymbol symb = lexer.yylex(); - if (symb.type != SymbolType.IDENTIFIER) { - throw new AVM2ParseException("Invalid @identifier AsDoc tag value. Identifier expected.", 0); - } - ParsedSymbol symb2 = lexer.yylex(); - if (symb2.type != SymbolType.ASSIGN) { - throw new AVM2ParseException("Invalid @identifier AsDoc tag value. Assign expected.", 0); - } - ParsedSymbol symb3 = lexer.yylex(); - if (symb3.type != SymbolType.STRING) { - throw new AVM2ParseException("Invalid @identifier AsDoc tag value. String expected.", 0); - } - replacements.put(symb.value.toString(), symb3.value.toString()); - } - } - } + public void addScript(String s, String fileName, int classPos, int scriptIndex, String documentClass, ABC abc) throws AVM2ParseException, IOException, CompilationException, InterruptedException { + try { + replacements = IdentifiersDeobfuscation.getReplacementsFromDoc(s); + } catch (Exception ex) { + throw new AVM2ParseException(ex.getMessage(), -1); } List> allOpenedNamespaces = new ArrayList<>(); Reference numberContextRef = new Reference<>(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java index 9212db367..419a4ccb8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.action; import com.jpexs.decompiler.flash.AppResources; import com.jpexs.decompiler.flash.BaseLocalData; import com.jpexs.decompiler.flash.DisassemblyListener; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SWFOutputStream; import com.jpexs.decompiler.flash.ValueTooLargeException; @@ -1002,7 +1003,7 @@ public abstract class Action implements GraphSourceItem { new ActionDeobfuscator().actionTreeCreated(tree, swf); } - Graph.graphToString(tree, new NulWriter(), new LocalData()); + Graph.graphToString(tree, new NulWriter(), LocalData.create(new ConstantPool(), swf, usedDeobfuscations)); return tree; } }, timeout, TimeUnit.SECONDS); @@ -1031,7 +1032,7 @@ public abstract class Action implements GraphSourceItem { asm.getActionSourcePrefix(writer); } if (convertException == null) { - Graph.graphToString(tree, writer, new LocalData()); + Graph.graphToString(tree, writer, LocalData.create(new ConstantPool(), swf, usedDeobfuscations)); } else if (convertException instanceof TimeoutException) { Helper.appendTimeoutCommentAs2(writer, timeout, actions.size()); } else { @@ -1041,7 +1042,7 @@ public abstract class Action implements GraphSourceItem { asm.getActionSourceSuffix(writer); } - //TODO: write the actual used deobfuscations !!! + IdentifiersDeobfuscation.writeCurrentScriptReplacements(writer, usedDeobfuscations, swf); return writer; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java index 18a17608d..012d915d7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/DefineLocalActionItem.java @@ -101,7 +101,7 @@ public class DefineLocalActionItem extends ActionItem implements SetTypeActionIt srcData.declaration = true; if (((name instanceof DirectValueActionItem)) && (((DirectValueActionItem) name).isString()) && (!IdentifiersDeobfuscation.isValidName(false, ((DirectValueActionItem) name).toStringNoQuotes(localData), "this", "super", "true", "false", "NaN", "null", "newline", "Infinity", "undefined", "get", "set", "each"))) { - IdentifiersDeobfuscation.appendObfuscatedIdentifier(((DirectValueActionItem) name).toStringNoQuotes(localData), writer); + IdentifiersDeobfuscation.appendObfuscatedIdentifier(localData.swf, localData.usedDeobfuscations, ((DirectValueActionItem) name).toStringNoQuotes(localData), writer); } else { stripQuotes(name, localData, writer); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java index f673c350b..19af3495e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/FunctionActionItem.java @@ -248,7 +248,7 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista } if (!IdentifiersDeobfuscation.isValidName(false, fname)) { - IdentifiersDeobfuscation.appendObfuscatedIdentifier(fname, writer); + IdentifiersDeobfuscation.appendObfuscatedIdentifier(localData.swf, localData.usedDeobfuscations, fname, writer); } else { writer.append(fname); //calculatedFunctionName.appendToNoQuotes(writer, localData); @@ -265,7 +265,7 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista } writer.append(" "); if (!IdentifiersDeobfuscation.isValidName(false, fname)) { - IdentifiersDeobfuscation.appendObfuscatedIdentifier(fname, writer); + IdentifiersDeobfuscation.appendObfuscatedIdentifier(localData.swf, localData.usedDeobfuscations, fname, writer); } else { writer.append(fname); } @@ -298,7 +298,7 @@ public class FunctionActionItem extends ActionItem implements BranchStackResista d.declaration = true; if (!IdentifiersDeobfuscation.isValidName(false, pname)) { - IdentifiersDeobfuscation.appendObfuscatedIdentifier(pname, writer); + IdentifiersDeobfuscation.appendObfuscatedIdentifier(localData.swf, localData.usedDeobfuscations, pname, writer); } else { writer.append(pname); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index 5775efae9..a7531610d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -16,6 +16,7 @@ */ package com.jpexs.decompiler.flash.action.parser.script; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; import com.jpexs.decompiler.flash.action.Action; @@ -173,6 +174,7 @@ import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -259,6 +261,11 @@ public class ActionScript2Parser { * SWF */ private SWF swf; + + /** + * Obfuscation identifiers replacements + */ + private Map replacements = new LinkedHashMap<>(); /** * Constructor @@ -381,6 +388,11 @@ public class ActionScript2Parser { throw new InterruptedException(); } ParsedSymbol ret = lexer.lex(); + if (ret.type == SymbolType.IDENTIFIER) { + if (replacements.containsKey(ret.value.toString())) { + ret.value = replacements.get(ret.value.toString()); + } + } if (debugMode) { System.out.println(ret); } @@ -1129,7 +1141,7 @@ public class ActionScript2Parser { expectedType(SymbolType.CURLY_CLOSE); break; case FUNCTION: - s = lexer.lex(); + s = lex(); expectedIdentifier(s, lexer.yyline()); ret = (function(true, s.value.toString(), false, variables, functions, inTellTarget, hasEval)); break; @@ -1799,7 +1811,7 @@ public class ActionScript2Parser { //AS 1/2: //AS2: case "constant": - s = lexer.lex(); + s = lex(); expected(s, lexer.yyline(), SymbolType.INTEGER); ret = new UnresolvedConstantActionItem((int) (long) (Long) s.value); break; @@ -1819,7 +1831,7 @@ public class ActionScript2Parser { allowMemberOrCall = true; break; case "strict": - s = lexer.lex(); + s = lex(); expected(s, lexer.yyline(), SymbolType.INTEGER); ret = new StrictModeActionItem(null, null, (int) (long) (Long) s.value); break; @@ -2198,6 +2210,13 @@ public class ActionScript2Parser { * @throws InterruptedException On interrupt */ public List treeFromString(String str, List constantPool) throws ActionParseException, IOException, InterruptedException { + + try { + replacements = IdentifiersDeobfuscation.getReplacementsFromDoc(str); + } catch (Exception ex) { + throw new ActionParseException(ex.getMessage(), -1); + } + List retTree = new ArrayList<>(); this.constantPool = constantPool; lexer = new ActionScriptLexer(new StringReader(str)); @@ -2208,12 +2227,12 @@ public class ActionScript2Parser { BUTTONCONDACTION newButtonCond = new BUTTONCONDACTION(); if (targetSource instanceof BUTTONCONDACTION) { - ParsedSymbol symb = lexer.lex(); + ParsedSymbol symb = lex(); if (symb.type != SymbolType.IDENTIFIER || !"on".equals(symb.value)) { throw new ActionParseException("on keyword expected but " + symb + " found", lexer.yyline()); } expectedType(SymbolType.PARENT_OPEN); - symb = lexer.lex(); + symb = lex(); boolean condEmpty = true; while (symb.type == SymbolType.IDENTIFIER) { condEmpty = false; @@ -2240,7 +2259,7 @@ public class ActionScript2Parser { newButtonCond.condOutDownToOverDown = true; break; case "keyPress": - symb = lexer.lex(); + symb = lex(); expected(symb, lexer.yyline(), SymbolType.STRING); Integer key = CLIPACTIONRECORD.stringToKey((String) symb.value); if (key == null) { @@ -2251,12 +2270,12 @@ public class ActionScript2Parser { default: throw new ActionParseException("Unrecognized event type", lexer.yyline()); } - symb = lexer.lex(); + symb = lex(); if (symb.type == SymbolType.PARENT_CLOSE) { break; } expected(symb, lexer.yyline(), SymbolType.COMMA); - symb = lexer.lex(); + symb = lex(); } expected(symb, lexer.yyline(), SymbolType.PARENT_CLOSE); if (condEmpty) { @@ -2268,13 +2287,13 @@ public class ActionScript2Parser { CLIPEVENTFLAGS newClipEventFlags = new CLIPEVENTFLAGS(); int newClipActionRecordKey = 0; if (targetSource instanceof CLIPACTIONRECORD) { - ParsedSymbol symb = lexer.lex(); + ParsedSymbol symb = lex(); if (symb.type != SymbolType.IDENTIFIER || (!"on".equals(symb.value) && !"onClipEvent".equals(symb.value))) { throw new ActionParseException("on or onClipEvent keyword expected but " + symb + " found", lexer.yyline()); } expectedType(SymbolType.PARENT_OPEN); if ("on".equals(symb.value)) { - symb = lexer.lex(); + symb = lex(); boolean condEmpty = true; while (symb.type == SymbolType.IDENTIFIER) { condEmpty = false; @@ -2308,7 +2327,7 @@ public class ActionScript2Parser { break; case "keyPress": - symb = lexer.lex(); + symb = lex(); expected(symb, lexer.yyline(), SymbolType.STRING); Integer key = CLIPACTIONRECORD.stringToKey((String) symb.value); if (key == null) { @@ -2320,19 +2339,19 @@ public class ActionScript2Parser { default: throw new ActionParseException("Unrecognized event type", lexer.yyline()); } - symb = lexer.lex(); + symb = lex(); if (symb.type == SymbolType.PARENT_CLOSE) { break; } expected(symb, lexer.yyline(), SymbolType.COMMA); - symb = lexer.lex(); + symb = lex(); } expected(symb, lexer.yyline(), SymbolType.PARENT_CLOSE); if (condEmpty) { throw new ActionParseException("condition must be non empty", lexer.yyline()); } } else if ("onClipEvent".equals(symb.value)) { - symb = lexer.lex(); + symb = lex(); expected(symb, lexer.yyline(), SymbolType.IDENTIFIER); switch ((String) symb.value) { @@ -2404,7 +2423,7 @@ public class ActionScript2Parser { expectedType(SymbolType.CURLY_CLOSE); } - if (lexer.lex().type != SymbolType.EOF) { + if (lex().type != SymbolType.EOF) { throw new ActionParseException("Parsing finished before end of the file", lexer.yyline()); } if (targetSource instanceof BUTTONCONDACTION) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties index daa5fb3bb..76ed4688a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources.properties @@ -64,3 +64,5 @@ configuration.removed = WARNING: This configuration was REMOVED. It is unused. #after 24.0.1 decompilationWarning.as2.noUninitializedClassFieldsDetection = WARNING: This class was decompiled without detecting uninitialized class fields. +decompilationWarning.obfuscatedIdentifiers = WARNING: The original code has obfuscated identifiers. +decompilationWarning.replacementsFollow = List of replacements follows: \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources_cs.properties b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources_cs.properties index 1fdc7d12b..185c22a64 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources_cs.properties +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/locales/AppResources_cs.properties @@ -65,3 +65,5 @@ configuration.removed = VAROV\u00c1N\u00cd: Tato konfigurace byla ODSTRAN\u011aN #after 24.0.1 decompilationWarning.as2.noUninitializedClassFieldsDetection = VAROV\u00c1N\u00cd: Tato t\u0159\u00edda byla dekompilov\u00e1na bez detekce neinicializovan\u00fdch pol\u00ed t\u0159\u00edd. +decompilationWarning.obfuscatedIdentifiers = VAROV\u00c1N\u00cd: P\u016fvodn\u00ed k\u00f3d m\u00e1 obfuskovan\u00e9 identifik\u00e1tory. +decompilationWarning.replacementsFollow = N\u00e1sleduje seznam n\u00e1hrad: \ No newline at end of file diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java index 8de00f0d7..2cb4a5a7b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/LocalData.java @@ -101,6 +101,11 @@ public class LocalData { * SWF version */ public int swfVersion; + + private LocalData() { + } + + /** * Creates a new local data diff --git a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex index a32ce1b42..e6b0e42ef 100644 --- a/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex +++ b/libsrc/jsyntaxpane/jsyntaxpane/src/main/jflex/jsyntaxpane/lexers/actionscript.flex @@ -64,7 +64,7 @@ import java.util.List; this.offset = ofst; prevToken = null; Token t = yylex(); - if (t.type != TokenType.COMMENT) { + if (t != null && t.type != TokenType.COMMENT) { prevToken = t; } for (; t != null; t = yylex()) {