From dc2dc32feee625bb5873caab96e07090219b8edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 5 Mar 2023 15:31:46 +0100 Subject: [PATCH] =?UTF-8?q?Added=20AS3=20Display=20missing=20namespaces=20?= =?UTF-8?q?along=20traits=20as=20=C2=A7=C2=A7namespace("url")=20Added=20#1?= =?UTF-8?q?892=20AS3=20option=20to=20select=20SWF=20dependencies=20to=20pr?= =?UTF-8?q?operly=20resolve=20namespaces,=20types,=20etc.=20(currently=20i?= =?UTF-8?q?n=20GUI=20only)=20Fixed=20AS3=20P-code=20ValueKind=20namespaces?= =?UTF-8?q?=20handling=20Fixed=20AS3=20direct=20editation=20-=20namespace?= =?UTF-8?q?=20definition=20without=20explicit=20value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 +- .../src/com/jpexs/decompiler/flash/SWF.java | 23 +- .../com/jpexs/decompiler/flash/abc/ABC.java | 9 +- .../abc/avm2/parser/pcode/ASM3Parser.java | 3 +- .../parser/script/AVM2SourceGenerator.java | 10 +- .../parser/script/ActionScript3Parser.java | 33 ++- .../abc/avm2/parser/script/ConstAVM2Item.java | 5 +- .../abc/avm2/parser/script/NamespaceItem.java | 7 +- .../decompiler/flash/abc/types/ValueKind.java | 29 +- .../flash/abc/types/traits/Trait.java | 12 +- .../flash/abc/types/traits/TraitClass.java | 16 +- .../flash/abc/types/traits/TraitFunction.java | 6 +- .../types/traits/TraitMethodGetterSetter.java | 6 +- .../abc/types/traits/TraitSlotConst.java | 6 +- .../flash/abc/types/traits/Traits.java | 4 +- .../CustomConfigurationKeys.java | 1 + .../exporters/script/DependencyParser.java | 38 ++- .../exporters/script/LinkReportExporter.java | 2 +- .../flash/exporters/swf/SwfToSwcExporter.java | 2 +- src/com/jpexs/decompiler/flash/gui/Main.java | 74 ++++++ .../decompiler/flash/gui/abc/ABCPanel.java | 64 ++++- .../decompiler/flash/gui/abc/LinkDialog.java | 248 ++++++++++++++++++ .../decompiler/flash/gui/graphics/link16.png | Bin 0 -> 649 bytes .../decompiler/flash/gui/graphics/link32.png | Bin 0 -> 1282 bytes .../flash/gui/locales/MainFrame.properties | 6 +- 25 files changed, 533 insertions(+), 77 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/abc/LinkDialog.java create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/link16.png create mode 100644 src/com/jpexs/decompiler/flash/gui/graphics/link32.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 04180c113..8382c2173 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ### Added - AS3 support for logical AND/OR compound operator +- AS3 Display missing namespaces along traits as §§namespace("url") +- [#1892] AS3 option to select SWF dependencies to properly resolve namespaces, types, etc. (currently in GUI only) ### Fixed - [#1981] AS3 fully qualified (colliding) types in submethods @@ -17,6 +19,8 @@ All notable changes to this project will be documented in this file. - [#1981] AS3 star import collisions - [#1982] Slow calculation of large shape outlines - now use only rectangles for large shapes - [#1986] AS2 Class detection - NullPointerException on certain classes +- AS3 P-code ValueKind namespaces handling +- AS3 direct editation - namespace definition without explicit value ### Changed - AS1/2/3 P-code - format Number values with EcmaScript toString function @@ -2984,6 +2988,7 @@ All notable changes to this project will be documented in this file. [alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9 [alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8 [alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7 +[#1892]: https://www.free-decompiler.com/flash/issues/1892 [#1981]: https://www.free-decompiler.com/flash/issues/1981 [#1982]: https://www.free-decompiler.com/flash/issues/1982 [#1986]: https://www.free-decompiler.com/flash/issues/1986 @@ -3015,7 +3020,6 @@ All notable changes to this project will be documented in this file. [#1913]: https://www.free-decompiler.com/flash/issues/1913 [#1894]: https://www.free-decompiler.com/flash/issues/1894 [#1801]: https://www.free-decompiler.com/flash/issues/1801 -[#1892]: https://www.free-decompiler.com/flash/issues/1892 [#1936]: https://www.free-decompiler.com/flash/issues/1936 [#1937]: https://www.free-decompiler.com/flash/issues/1937 [#1458]: https://www.free-decompiler.com/flash/issues/1458 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 9ed958b88..726becd3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -398,7 +398,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { @Internal private AbcIndexing abcIndex; - + + private int numAbcIndexDependencies = 0; + + private static AbcIndexing playerGlobalAbcIndex; private static AbcIndexing airGlobalAbcIndex; @@ -460,6 +463,24 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { return abcIndex; } + public int getNumAbcIndexDependencies() { + return numAbcIndexDependencies; + } + + public void setAbcIndexDependencies(List swfs) { + abcIndex = null; + getAbcIndex(); + for (SWF swf:swfs) { + for (Tag tag:swf.tags) { + if (tag instanceof ABCContainerTag) { + abcIndex.addAbc(((ABCContainerTag)tag).getABC()); + } + } + } + abcIndex.rebuildPkgToObjectsNameMap(); + numAbcIndexDependencies = swfs.size(); + } + public static void initPlayer() throws IOException, InterruptedException { if (playerGlobalAbcIndex == null) { /*if (Configuration.getPlayerSWC() == null) { 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 b8411302a..7fe36a843 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 @@ -2222,7 +2222,10 @@ public class ABC implements Openable { String name = constants.getString(ns.name_index); if (name.equals("http://adobe.com/AS3/2006/builtin")) { //TODO: This should really be resolved using ABC indexing, not hardcoded constant return DottedChain.parseNoSuffix("AS3"); - } + } + + return getSwf().getAbcIndex().nsValueToName(name); + /* for (ABCContainerTag abcTag : getAbcTags()) { DottedChain dc = abcTag.getABC().nsValueToName(name); nsname = dc.getLast(); @@ -2233,8 +2236,8 @@ public class ABC implements Openable { if (!nsname.isEmpty()) { return dc; } - } - return null; + }*/ + //return null; } public void clearPacksCache() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java index ac36bd454..ab7fc58c7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/pcode/ASM3Parser.java @@ -633,8 +633,9 @@ public class ASM3Parser { value_kind = ValueKind.CONSTANT_PackageNamespace; break; } - lexer.pushback(type); + expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer); value_index = parseNamespace(constants, lexer); + expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); break; default: if (Configuration._debugMode.get()) { 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 d618e4ffc..8d0f1c740 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 @@ -1875,7 +1875,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } for (int i = 0; i < paramValues.size(); i++) { - optional[i] = getValueKind(Namespace.KIND_NAMESPACE/*FIXME*/, paramTypes.get(paramTypes.size() - paramValues.size() + i), paramValues.get(i)); + optional[i] = getValueKind(Namespace.KIND_NAMESPACE/*FIXME*/, paramTypes.get(paramTypes.size() - paramValues.size() + i), paramValues.get(i), false); if (optional[i] == null) { throw new CompilationException("Default value must be compiletime constant", line); } @@ -2059,7 +2059,7 @@ public class AVM2SourceGenerator implements SourceGenerator { return mindex; } - public ValueKind getValueKind(int ns, GraphTargetItem type, GraphTargetItem val) { + public ValueKind getValueKind(int ns, GraphTargetItem type, GraphTargetItem val, boolean generatedNs) { if (val instanceof BooleanAVM2Item) { BooleanAVM2Item bi = (BooleanAVM2Item) val; @@ -2084,7 +2084,7 @@ public class AVM2SourceGenerator implements SourceGenerator { if (val instanceof StringAVM2Item) { StringAVM2Item sval = (StringAVM2Item) val; if (isNs) { - return new ValueKind(namespace(Namespace.KIND_NAMESPACE, sval.getValue()), ValueKind.CONSTANT_Namespace); + return new ValueKind(namespace(generatedNs ? Namespace.KIND_PACKAGE_INTERNAL : Namespace.KIND_NAMESPACE, sval.getValue()), ValueKind.CONSTANT_Namespace); } else { return new ValueKind(str(sval.getValue()), ValueKind.CONSTANT_Utf8); } @@ -2394,8 +2394,10 @@ public class AVM2SourceGenerator implements SourceGenerator { namespace = sai.pkg == null ? 0 : sai.pkg.getCpoolIndex(abcIndex); metadata = generateMetadata(((SlotAVM2Item) item).metadata); } + boolean generatedNs = false; if (item instanceof ConstAVM2Item) { ConstAVM2Item cai = (ConstAVM2Item) item; + generatedNs = cai.generatedNs; if (cai.isStatic() != generateStatic) { continue; } @@ -2415,7 +2417,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } tsc.type_index = isNamespace ? 0 : (type == null ? 0 : typeName(localData, type)); - ValueKind vk = getValueKind(namespace, type, val); + ValueKind vk = getValueKind(namespace, type, val, generatedNs); if (vk == null) { tsc.value_index = ValueKind.CONSTANT_Undefined; tsc.value_kind = ValueKind.CONSTANT_Undefined; 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 8158b47e9..fa312eb29 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 @@ -83,6 +83,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.operations.SubtractAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.TypeOfAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.operations.URShiftAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; +import static com.jpexs.decompiler.flash.abc.avm2.parser.script.SymbolType.PREPROCESSOR; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.ScriptInfo; import com.jpexs.decompiler.flash.action.swf4.ActionIf; @@ -648,6 +649,7 @@ public class ActionScript3Parser { boolean isPrivate = false; String customNs = null; + String rawCustomNs = null; NamespaceItem namespace = null; ParsedSymbol s = lex(); //static class initializer @@ -660,7 +662,7 @@ public class ActionScript3Parser { List>> metadata = parseMetadata(); s = lex(); - while (s.isType(SymbolType.STATIC, SymbolType.PUBLIC, SymbolType.PRIVATE, SymbolType.PROTECTED, SymbolType.OVERRIDE, SymbolType.FINAL, SymbolType.DYNAMIC, SymbolGroup.IDENTIFIER, SymbolType.INTERNAL)) { + while (s.isType(SymbolType.STATIC, SymbolType.PUBLIC, SymbolType.PRIVATE, SymbolType.PROTECTED, SymbolType.OVERRIDE, SymbolType.FINAL, SymbolType.DYNAMIC, SymbolGroup.IDENTIFIER, SymbolType.INTERNAL, SymbolType.PREPROCESSOR)) { if (s.type == SymbolType.FINAL) { if (isFinal) { throw new AVM2ParseException("Only one final keyword allowed", lexer.yyline()); @@ -714,6 +716,19 @@ public class ActionScript3Parser { case INTERNAL: namespace = packageInternalNs; break; + + + case PREPROCESSOR: + if (((String)s.value).toLowerCase().equals("namespace")) { + expectedType(SymbolType.PARENT_OPEN); + s = lex(); + expected(s, lexer.yyline(), SymbolType.STRING); + namespace = new NamespaceItem((String)s.value, Namespace.KIND_NAMESPACE); + expectedType(SymbolType.PARENT_CLOSE); + } else { + lexer.pushback(s); + } + break; } s = lex(); } @@ -725,7 +740,7 @@ public class ActionScript3Parser { } if (namespace == null && customNs != null) { //Special: it will be resolved later: - namespace = new NamespaceItem(customNs, Namespace.KIND_NAMESPACE); + namespace = new NamespaceItem(customNs, NamespaceItem.KIND_NAMESPACE_CUSTOM); } switch (s.type) { @@ -833,6 +848,7 @@ public class ActionScript3Parser { String nval; s = lex(); + boolean generatedNs = false; if (s.type == SymbolType.ASSIGN) { s = lex(); expected(s, lexer.yyline(), SymbolType.STRING); @@ -840,12 +856,13 @@ public class ActionScript3Parser { s = lex(); } else { nval = (pkg.name.toRawString() + ":" + classNameStr) + "/" + nname; + generatedNs = true; } if (s.type != SymbolType.SEMICOLON) { lexer.pushback(s); } - ConstAVM2Item ns = new ConstAVM2Item(metadata, namespace, customNs, true, nname, new TypeItem(DottedChain.NAMESPACE), new StringAVM2Item(null, null, nval), lexer.yyline()); + ConstAVM2Item ns = new ConstAVM2Item(metadata, namespace, customNs, true, nname, new TypeItem(DottedChain.NAMESPACE), new StringAVM2Item(null, null, nval), lexer.yyline(), generatedNs); traits.add(ns); break; case CONST: @@ -887,7 +904,7 @@ public class ActionScript3Parser { } GraphTargetItem tar; if (isConst) { - tar = new ConstAVM2Item(metadata, namespace, customNs, isStatic, vcname, type, value, lexer.yyline()); + tar = new ConstAVM2Item(metadata, namespace, customNs, isStatic, vcname, type, value, lexer.yyline(), false); } else { tar = new SlotAVM2Item(metadata, namespace, customNs, isStatic, vcname, type, value, lexer.yyline()); } @@ -1111,7 +1128,7 @@ public class ActionScript3Parser { } GraphTargetItem tar; if (isConst) { - tar = new ConstAVM2Item(metadata, ns, null, false, vcname, type, value, lexer.yyline()); + tar = new ConstAVM2Item(metadata, ns, null, false, vcname, type, value, lexer.yyline(), false); } else { tar = new SlotAVM2Item(metadata, ns, null, false, vcname, type, value, lexer.yyline()); } @@ -1131,19 +1148,21 @@ public class ActionScript3Parser { String nval; s = lex(); + boolean generatedNs = false; if (s.type == SymbolType.ASSIGN) { s = lex(); expected(s, lexer.yyline(), SymbolType.STRING); nval = s.value.toString(); s = lex(); } else { - nval = ns + "/" + nname; + generatedNs = true; + nval = ns.name.toRawString() + ":" + nname; } if (s.type != SymbolType.SEMICOLON) { lexer.pushback(s); } - traits.add(new ConstAVM2Item(metadata, ns, null, true, nname, new TypeItem(DottedChain.NAMESPACE), new StringAVM2Item(null, null, nval), lexer.yyline())); + traits.add(new ConstAVM2Item(metadata, ns, null, true, nname, new TypeItem(DottedChain.NAMESPACE), new StringAVM2Item(null, null, nval), lexer.yyline(), generatedNs)); break; default: lexer.pushback(s); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstAVM2Item.java index d770172a9..94db5fcf3 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ConstAVM2Item.java @@ -42,12 +42,14 @@ public class ConstAVM2Item extends AVM2Item { public int line; public NamespaceItem pkg; + + public boolean generatedNs; public boolean isStatic() { return isStatic; } - public ConstAVM2Item(List>> metadata, NamespaceItem pkg, String customNamespace, boolean isStatic, String var, GraphTargetItem type, GraphTargetItem value, int line) { + public ConstAVM2Item(List>> metadata, NamespaceItem pkg, String customNamespace, boolean isStatic, String var, GraphTargetItem type, GraphTargetItem value, int line, boolean generatedNs) { super(null, null, NOPRECEDENCE, value); this.metadata = metadata; @@ -57,6 +59,7 @@ public class ConstAVM2Item extends AVM2Item { this.var = var; this.type = type; this.customNamespace = customNamespace; + this.generatedNs = generatedNs; } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java index 9ce427749..ee97241c4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NamespaceItem.java @@ -34,6 +34,8 @@ import java.util.Objects; */ public class NamespaceItem { + public static final int KIND_NAMESPACE_CUSTOM = -2; + public DottedChain name; public int kind; @@ -89,6 +91,9 @@ public class NamespaceItem { return; } if (kind == Namespace.KIND_NAMESPACE) { + nsIndex = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_NAMESPACE, name, 0, true); + } + if (kind == KIND_NAMESPACE_CUSTOM) { String custom = name.toRawString(); PropertyAVM2Item prop = new PropertyAVM2Item(null, false, custom, "", abcIndex, openedNamespaces, new ArrayList<>()); Reference value = new Reference<>(null); @@ -125,7 +130,7 @@ public class NamespaceItem { } } - throw new CompilationException("Namespace \"" + name + "\"+not defined", -1); + throw new CompilationException("Namespace \"" + name + "\" not defined", -1); } nsIndex = abcIndex.getSelectedAbc().constants.getNamespaceId(Namespace.KIND_NAMESPACE, outAbc.getVal().constants.getNamespace(value.getVal().value_index).getName(outAbc.getVal().constants), 0, true); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ValueKind.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ValueKind.java index e4a58d639..7e6da50d9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ValueKind.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ValueKind.java @@ -158,7 +158,7 @@ public class ValueKind { case CONSTANT_Undefined: ret = "undefined"; break; - case CONSTANT_Namespace: + case CONSTANT_Namespace: case CONSTANT_PackageInternalNs: case CONSTANT_ProtectedNamespace: case CONSTANT_ExplicitNamespace: @@ -200,13 +200,34 @@ public class ValueKind { case CONSTANT_Undefined: ret = "Undefined()"; //"Void()" is also synonym break; - case CONSTANT_Namespace: + case CONSTANT_Namespace: case CONSTANT_PackageInternalNs: case CONSTANT_ProtectedNamespace: case CONSTANT_ExplicitNamespace: case CONSTANT_StaticProtectedNs: - case CONSTANT_PrivateNs: - ret = constants.getNamespace(value_index).getKindStr() + "(\"" + constants.getNamespace(value_index).getName(constants).toRawString() + "\")"; //assume not null name + case CONSTANT_PrivateNs: + String nsVal = constants.getNamespace(value_index).getKindStr() + "(\"" + constants.getNamespace(value_index).getName(constants).toRawString() + "\")"; //assume not null name + + switch (value_kind) { + case CONSTANT_Namespace: + ret = "Namespace(" + nsVal + ")"; + break; + case CONSTANT_PackageInternalNs: + ret = "PackageInternalNs(" + nsVal + ")"; + break; + case CONSTANT_ProtectedNamespace: + ret = "ProtectedNamespace(" + nsVal + ")"; + break; + case CONSTANT_ExplicitNamespace: + ret = "ExplicitNamespace(" + nsVal + ")"; + break; + case CONSTANT_StaticProtectedNs: + ret = "StaticProtectedNs(" + nsVal + ")"; + break; + case CONSTANT_PrivateNs: + ret = "PrivateNamespace(" + nsVal + ")"; + break; + } break; } return ret; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index e24f685b7..5e609b3e1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -171,14 +171,14 @@ public abstract class Trait implements Cloneable, Serializable { return getName(abc).getNamespace(abc.constants).getName(abc.constants); } - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignoredCustom == null) { Namespace n = getName(abc).getNamespace(abc.constants); if (n.kind == Namespace.KIND_NAMESPACE) { ignoredCustom = n.getName(abc.constants).toRawString(); } } - DependencyParser.parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); + DependencyParser.parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); //DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); } @@ -214,7 +214,7 @@ public abstract class Trait implements Cloneable, Serializable { if (ns.kind == Namespace.KIND_NAMESPACE) { customNs = ns.getName(abc.constants).toRawString(); } - getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, new ArrayList<>()); + getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, new ArrayList<>()); List imports = new ArrayList<>(); for (Dependency d : dependencies) { @@ -349,7 +349,11 @@ public abstract class Trait implements Cloneable, Serializable { Namespace ns = m.getNamespace(abc.constants); - if (nsname != null) { + if (ns.kind == Namespace.KIND_NAMESPACE && nsname == null) { + writer.append("§§namespace(\""); + writer.append(Helper.escapeActionScriptString(ns.getRawName(abc.constants))); + writer.append("\") "); + } else if (nsname != null) { String identifier = IdentifiersDeobfuscation.printIdentifier(true, nsname); if (identifier != null && !identifier.isEmpty()) { writer.appendNoHilight(identifier).appendNoHilight(" "); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java index 56baffe26..f5c749261 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitClass.java @@ -78,31 +78,31 @@ public class TraitClass extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { - super.getDependencies(scriptIndex, -1, false, customNs, abc, dependencies, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames); + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + super.getDependencies(abcIndex, scriptIndex, -1, false, customNs, abc, dependencies, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames); ClassInfo classInfo = abc.class_info.get(class_info); InstanceInfo instanceInfo = abc.instance_info.get(class_info); DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name //DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames); if (instanceInfo.super_index > 0) { - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); + DependencyParser.parseDependenciesFromMultiname(abcIndex, customNs, abc, dependencies, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); } for (int i : instanceInfo.interfaces) { - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); + DependencyParser.parseDependenciesFromMultiname(abcIndex, customNs, abc, dependencies, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE); } //static - classInfo.static_traits.getDependencies(scriptIndex, class_info, true, customNs, abc, dependencies, packageName, fullyQualifiedNames); + classInfo.static_traits.getDependencies(abcIndex, scriptIndex, class_info, true, customNs, abc, dependencies, packageName, fullyQualifiedNames); //static initializer - DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(abcIndex, null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); //instance - instanceInfo.instance_traits.getDependencies(scriptIndex, class_info, false, customNs, abc, dependencies, packageName, fullyQualifiedNames); + instanceInfo.instance_traits.getDependencies(abcIndex, scriptIndex, class_info, false, customNs, abc, dependencies, packageName, fullyQualifiedNames); //instance initializer - DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(abcIndex, null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>()); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java index 4db356181..6d3ab7536 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitFunction.java @@ -133,14 +133,14 @@ public class TraitFunction extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, false, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); + super.getDependencies(abcIndex, scriptIndex, classIndex, false, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); //if (method_info != 0) { - DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(abcIndex, this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java index 3544d5949..880ec0bda 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitMethodGetterSetter.java @@ -63,11 +63,11 @@ public class TraitMethodGetterSetter extends Trait { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); + super.getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); if (customNs == null) { Namespace n = getName(abc).getNamespace(abc.constants); @@ -77,7 +77,7 @@ public class TraitMethodGetterSetter extends Trait { } //if (method_info != 0) { - DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); + DependencyParser.parseDependenciesFromMethodInfo(abcIndex, this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>()); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index bea04594a..7f2fb35e7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -221,12 +221,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } @Override - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { if (ignorePackage == null) { ignorePackage = getPackage(abc); } - super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); - DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE); + super.getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); + DependencyParser.parseDependenciesFromMultiname(abcIndex, customNs, abc, dependencies, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 343a6039a..e76c823e2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -298,9 +298,9 @@ public class Traits implements Cloneable, Serializable { } } - public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { + public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames) throws InterruptedException { for (Trait t : traits) { - t.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); + t.getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java index 78c40211a..c6c263ae5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/CustomConfigurationKeys.java @@ -10,4 +10,5 @@ public class CustomConfigurationKeys { public static final String KEY_CHARSET = "charset"; public static final String KEY_LIBRARY = "library"; public static final String KEY_LOADED_IMPORT_ASSETS = "loadedImportAssets"; + public static final String KEY_ABC_DEPENDENCIES = "abcDependencies"; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java index 5216b2b7c..8661bcc9e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/DependencyParser.java @@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns; import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; @@ -40,29 +41,26 @@ import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.abc.types.NamespaceSet; import com.jpexs.decompiler.flash.abc.types.traits.Trait; import com.jpexs.decompiler.flash.configuration.Configuration; -import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.graph.DottedChain; import java.util.List; public class DependencyParser { - public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List dependencies, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) { + public static void parseDependenciesFromNS(AbcIndexing abcIndex, String ignoredCustom, ABC abc, List dependencies, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) { Namespace ns = abc.constants.getNamespace(namespace_index); if (name.isEmpty()) { name = "*"; } DottedChain newimport = ns.getName(abc.constants); - if (ns.kind == Namespace.KIND_NAMESPACE || ns.kind == Namespace.KIND_PACKAGE_INTERNAL) { String nsVal = ns.getName(abc.constants).toRawString(); - for (ABCContainerTag abcTag : abc.getAbcTags()) { - DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal); + DottedChain nsimport = abcIndex.nsValueToName(nsVal); + if (nsimport != null) { if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) { return; //builtin, no dependency } if (!nsimport.isEmpty()) { - Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE); if ((ignorePackage == null || !nsimport.getWithoutLast().equals(ignorePackage)) && !dependencies.contains(depNs)) { dependencies.add(depNs); @@ -74,7 +72,7 @@ public class DependencyParser { } } } - + if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) { return; } @@ -93,15 +91,15 @@ public class DependencyParser { //} } - public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List dependencies, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) { + public static void parseDependenciesFromMultiname(AbcIndexing abcIndex, String ignoredCustom, ABC abc, List dependencies, Multiname m, DottedChain ignorePackage, List fullyQualifiedNames, DependencyType dependencyType) { if (m != null) { if (m.kind == Multiname.TYPENAME) { if (m.qname_index != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType); } for (Integer i : m.params) { if (i != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType); } } return; @@ -110,35 +108,35 @@ public class DependencyParser { String name = m.getName(abc.constants, fullyQualifiedNames, true, true); NamespaceSet nss = m.getNamespaceSet(abc.constants); if (ns != null) { - parseDependenciesFromNS(ignoredCustom, abc, dependencies, m.namespace_index, ignorePackage, name, dependencyType); + parseDependenciesFromNS(abcIndex, ignoredCustom, abc, dependencies, m.namespace_index, ignorePackage, name, dependencyType); } if (nss != null) { for (int n : nss.namespaces) { - parseDependenciesFromNS(ignoredCustom, abc, dependencies, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType); + parseDependenciesFromNS(abcIndex, ignoredCustom, abc, dependencies, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType); } } } } - public static void parseDependenciesFromMethodInfo(Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) throws InterruptedException { + public static void parseDependenciesFromMethodInfo(AbcIndexing abcIndex, Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List dependencies, DottedChain ignorePackage, List fullyQualifiedNames, List visitedMethods) throws InterruptedException { if ((method_index < 0) || (method_index >= abc.method_info.size())) { return; } visitedMethods.add(method_index); if (abc.method_info.get(method_index).ret_type != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); } for (int t : abc.method_info.get(method_index).param_types) { if (t != 0) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE); } } MethodBody body = abc.findBody(method_index); if (body != null && body.convertException == null) { body = body.convertMethodBodyCanUseLast(Configuration.autoDeobfuscate.get(), "", isStatic, scriptIndex, classIndex, abc, trait); - body.traits.getDependencies(scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, ignorePackage, fullyQualifiedNames); + body.traits.getDependencies(abcIndex, scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, ignorePackage, fullyQualifiedNames); for (ABCException ex : body.exceptions) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/); } for (AVM2Instruction ins : body.getCode().code) { if (ins.definition instanceof AlchemyTypeIns) { @@ -151,7 +149,7 @@ public class DependencyParser { if (ins.definition instanceof NewFunctionIns) { if (ins.operands[0] != method_index) { if (!visitedMethods.contains(ins.operands[0])) { - parseDependenciesFromMethodInfo(trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, ignorePackage, fullyQualifiedNames, visitedMethods); + parseDependenciesFromMethodInfo(abcIndex, trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, ignorePackage, fullyQualifiedNames, visitedMethods); } } } @@ -159,12 +157,12 @@ public class DependencyParser { if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) { int m = ins.operands[k]; if (m < abc.constants.getMultinameCount()) { - parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION); + parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION); } } } } } - } + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java index cbeb6b198..51a161b6f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/script/LinkReportExporter.java @@ -165,7 +165,7 @@ public class LinkReportExporter { List dependencies = new ArrayList<>(); sb.append(indent(3)).append("").append(newLineChar); //Automatic - tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>()); + tc.getDependencies(swf.getAbcIndex(), scriptIndex, -1, false, null, abc, dependencies, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>()); for (Dependency dependency : dependencies) { DottedChain dc = dependency.getId(); if (!"*".equals(dc.getLast())) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java index f4929e75c..cb26c9b68 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/swf/SwfToSwcExporter.java @@ -148,7 +148,7 @@ public class SwfToSwcExporter { sb.append(" \n"); if (!skipDependencies) { List dependencies = new ArrayList<>(); - pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>()); + pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(swf.getAbcIndex(), pack.scriptIndex, -1, false, null, pack.abc, dependencies, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>()); for (Dependency d : dependencies) { if ("*".equals(d.getId().getLast())) { diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 91360712e..dae843d1a 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -47,6 +47,7 @@ import com.jpexs.decompiler.flash.console.CommandLineArgumentParser; import com.jpexs.decompiler.flash.console.ContextMenuTools; import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode; import com.jpexs.decompiler.flash.gfx.GfxConvertor; +import com.jpexs.decompiler.flash.gui.abc.LinkDialog; import com.jpexs.decompiler.flash.gui.debugger.DebugListener; import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools; import com.jpexs.decompiler.flash.gui.pipes.FirstInstance; @@ -119,6 +120,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -1500,6 +1502,7 @@ public class Main { boolean first = true; SWF firstSWF = null; Openable firstOpenable = null; + List openableLists = new ArrayList<>(); for (int index = 0; index < sourceInfos.length; index++) { OpenableSourceInfo sourceInfo = sourceInfos[index]; OpenableList openables = null; @@ -1532,6 +1535,7 @@ public class Main { continue; } + openableLists.add(openables); final OpenableList openables1 = openables; final boolean first1 = first; first = false; @@ -1558,6 +1562,31 @@ public class Main { } } + + if (mainFrame != null) { + for (OpenableList openableList:openableLists) { + for (Openable openable:openableList) { + if (openable instanceof SWF) { + SWF swf = (SWF) openable; + SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + if (conf != null) { + String abcDependencies = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, ""); + if (!abcDependencies.isEmpty()) { + String[] parts = (abcDependencies + LinkDialog.ABC_DEPS_SEPARATOR).split(Pattern.quote(LinkDialog.ABC_DEPS_SEPARATOR)); + List preselectedNames = new ArrayList<>(); + for (String part : parts) { + if (!part.isEmpty()) { + preselectedNames.add(part); + } + } + swf.setAbcIndexDependencies(namesToSwfs(preselectedNames)); + } + } + } + } + } + } + loadingDialog.setVisible(false); shouldCloseWhenClosingLoadingDialog = false; @@ -2816,6 +2845,51 @@ public class Main { } } + public static List namesToSwfs(List names) { + List ret = new ArrayList<>(); + Map swfs = new LinkedHashMap<>(); + populateAllSWFs(swfs); + for (String name : names) { + if (swfs.containsKey(name)) { + ret.add(swfs.get(name)); + } + } + return ret; + } + + public static void populateAllSWFs(Map swfs) { + if (mainFrame == null) { + return; + } + List ols = mainFrame.getPanel().getSwfs(); + for (OpenableList ol : ols) { + for (Openable op : ol) { + if (op instanceof SWF) { + SWF swf = (SWF) op; + populateSwf(swfs, swf, swf.getShortPathTitle()); //swf.getShortFileName()); + } + } + } + } + + private static void populateSwf(Map ret, SWF swf, String name) { + int pos = 1; + String baseName = name; + while (ret.containsKey(name)) { + pos++; + name = baseName + "[" + pos + "]"; + } + ret.put(name, swf); + for (Tag t : swf.getTags()) { + if (t instanceof DefineBinaryDataTag) { + DefineBinaryDataTag binaryData = (DefineBinaryDataTag) t; + if (binaryData.innerSwf != null) { + populateSwf(ret, binaryData.innerSwf, binaryData.innerSwf.getShortPathTitle());//name + " / " + t.getTagName() + " (" + ((DefineBinaryDataTag) t).getCharacterId() + ")"); + } + } + } + } + public static void exit() { if (mainFrame != null && mainFrame.getPanel() != null) { mainFrame.getPanel().scrollPosStorage.saveScrollPos(mainFrame.getPanel().getCurrentTree().getCurrentTreeItem()); diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index cb879d8d9..86065133e 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -100,6 +100,7 @@ import java.awt.Cursor; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Insets; +import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; @@ -127,7 +128,6 @@ import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComboBox; import javax.swing.JLabel; -import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; @@ -211,6 +211,8 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener(); libraryComboBox.addItem("AIR (airglobal.swc)"); libraryComboBox.addItem("Flash (playerglobal.swc)"); @@ -1012,14 +1018,41 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener. + */ +package com.jpexs.decompiler.flash.gui.abc; + +import com.jpexs.decompiler.flash.SWF; +import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.configuration.CustomConfigurationKeys; +import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration; +import com.jpexs.decompiler.flash.gui.Main; +import com.jpexs.decompiler.flash.gui.MainPanel; +import com.jpexs.decompiler.flash.tags.DefineBinaryDataTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.treeitems.Openable; +import com.jpexs.decompiler.flash.treeitems.OpenableList; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Pattern; +import javax.swing.BorderFactory; +import javax.swing.DefaultListModel; +import javax.swing.JCheckBox; +import javax.swing.JDialog; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.ListCellRenderer; +import javax.swing.ListModel; +import javax.swing.SwingUtilities; +import javax.swing.border.BevelBorder; + +/** + * + * @author JPEXS + */ +public class LinkDialog extends JDialog { + + public static final String ABC_DEPS_SEPARATOR = "{*sep*}"; + + private MainPanel mainPanel; + + private JList linkList; + + private SWF swf; + + private List saveListeners = new ArrayList<>(); + + public void addSaveListener(ActionListener listener) { + saveListeners.add(listener); + } + + public void removeSaveListener(ActionListener listener) { + saveListeners.remove(listener); + } + + private void fireSave() { + for (ActionListener listener : saveListeners) { + listener.actionPerformed(new ActionEvent(this, 0, "SAVE")); + } + } + + public LinkDialog(MainPanel mainPanel) { + this.mainPanel = mainPanel; + setUndecorated(true); + setResizable(false); + getRootPane().setWindowDecorationStyle(JRootPane.NONE); + + setSize(400, 300); + addWindowListener(new WindowAdapter() { + @Override + public void windowDeactivated(WindowEvent e) { + save(swf, false); + swf = null; + dispose(); + } + }); + JPanel customLibraryPanel = new JPanel(new BorderLayout()); + linkList = new JList<>(); + linkList.setCellRenderer(new CustomLibraryListCellRenderer()); + linkList.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e)) { + int index = linkList.locationToIndex(e.getPoint()); + LinkItem item = linkList.getModel().getElementAt(index); + item.setSelected(!item.isSelected()); + linkList.repaint(linkList.getCellBounds(index, index)); + } + } + }); + customLibraryPanel.add(linkList, BorderLayout.CENTER); + + customLibraryPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED)); + + setContentPane(customLibraryPanel); + } + + public void load(SWF swf) { + this.swf = swf; + SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + List selectedSWFs = new ArrayList<>(); + + if (conf != null) { + String abcDependencies = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, ""); + if (!abcDependencies.isEmpty()) { + String[] parts = (abcDependencies + ABC_DEPS_SEPARATOR).split(Pattern.quote(ABC_DEPS_SEPARATOR)); + List preselectedNames = new ArrayList<>(); + for (String part : parts) { + if (!part.isEmpty()) { + preselectedNames.add(part); + } + } + selectedSWFs = Main.namesToSwfs(preselectedNames); + } + } + + populateSWFs(swf, selectedSWFs); + } + + public void show(SWF swf) { + load(swf); + setVisible(true); + } + + public void save(SWF swf, boolean force) { + Map map = getSelectedSwfs(); + SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle()); + String oldValue = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, ""); + String newValue = String.join(ABC_DEPS_SEPARATOR, map.keySet()); + conf.setCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, newValue); + List swfs = new ArrayList<>(map.values()); + if (!Objects.equals(oldValue, newValue) || force) { + swf.setAbcIndexDependencies(swfs); + fireSave(); + } + } + + private Map getSelectedSwfs() { + ListModel model = linkList.getModel(); + Map ret = new LinkedHashMap<>(); + for (int i = 0; i < model.getSize(); i++) { + LinkItem item = model.getElementAt(i); + if (!item.isSelected()) { + continue; + } + ret.put(item.getName(), item.getSwf()); + } + return ret; + } + + + + private void populateSWFs(SWF ignoreSWF, List selectedSWFs) { + Map swfs = new LinkedHashMap<>(); + Main.populateAllSWFs(swfs); + DefaultListModel listModel = new DefaultListModel<>(); + + for (String key : swfs.keySet()) { + SWF swf = swfs.get(key); + if (swf == ignoreSWF) { + continue; + } + boolean selected = false; + for (SWF s : selectedSWFs) { + if (s == swf) { + selected = true; + } + } + listModel.addElement(new LinkItem(key, swf, selected)); + } + linkList.setModel(listModel); + pack(); + } + + +} + +class LinkItem { + + private String name; + private SWF swf; + private boolean selected; + + public LinkItem(String name, SWF swf, boolean selected) { + this.name = name; + this.swf = swf; + this.selected = selected; + } + + public void setSelected(boolean selected) { + this.selected = selected; + } + + public boolean isSelected() { + return selected; + } + + public String getName() { + return name; + } + + public SWF getSwf() { + return swf; + } + + @Override + public String toString() { + return name; + } +} + +class CustomLibraryListCellRenderer extends JCheckBox implements ListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, LinkItem value, int index, boolean isSelected, boolean cellHasFocus) { + setEnabled(list.isEnabled()); + setSelected(value.isSelected()); + setFont(list.getFont()); + setBackground(list.getBackground()); + setForeground(list.getForeground()); + setText(value.toString()); + return this; + } + +} diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/link16.png b/src/com/jpexs/decompiler/flash/gui/graphics/link16.png new file mode 100644 index 0000000000000000000000000000000000000000..c4f00cb2231006331f76e8fb34fe98ba3e6c4c5a GIT binary patch literal 649 zcmV;40(Sk0P)R-wVQ6jZWcdI0SI7HLUn+ckeHpfG*^&WNl8M*$>e_m+%~e1e$TbFH z(ca$P8S6G|`k$7O^&jK{CVU1k0`c?bFBpFR`o)l$lXnKleSPl2rS#vw|1$jj^9QU3 zuK|C7fi{2PLWYLgYKAv2UoylcB>fKv2xQp4Z3_cGzu;Pe0a#X1_5bVFum6KX!v1gG zy8ZvEHS7P!CnWywn=ol7P+AV;1xBO*o3?uOnoLGUMh1|?@87=}8tSSU5)xAxUcPwB zpslOV@ZSJml#C3+_wPS|_&dRXX88q- z<2Uc#FtD(3lrLGb_|3`F=ejkuv>3K*-o&7#twS)X7?&1GCf1H)a#g?Xt!HIMLl0ThjLv**n3J9+X%Fi7wZFolVUi|^~|Xai}!M<@(n=>QZp jqDXS@32BBI01#jRVaY0la%Xjb00000NkvXXu0mjfT~I+< literal 0 HcmV?d00001 diff --git a/src/com/jpexs/decompiler/flash/gui/graphics/link32.png b/src/com/jpexs/decompiler/flash/gui/graphics/link32.png new file mode 100644 index 0000000000000000000000000000000000000000..b0c35b59a32a35922e235ce13cfaea86fb337aa3 GIT binary patch literal 1282 zcmV+d1^xPoP)20c}Tt0!?8C z=xDn*fBM6aEEdGD1Q?8M&Y9_)i5akqKa4SPh|I~&Y>66U;$^0z!)-+4-0+8)a_I%U zEl{ADC53V5Mi*U6ZE3c)r#Ij4^t1vi!Z=-alJ}&^cTS)8d%x#>pXcx*kqA7@D}~&6 zJYKT@m)F|XS&}XiT?~c8d7)qsBB3zQ0s3OgyG?s>Js5wGR3OO-@Y_329w;g(R99>( z2cOpuF1H)(4hKw6O~ahc25s*je-xjiA4CHD*7gq$$cl>8H8s^>7#;>{#tH%24?=+u zBvL8ZY&U?Sti2z9cxpGPL`pJuz8GAqGl1D_2Ghj&r{+JenN(%vZ}@266FE6KnAB`7 zJ}(Q+YtOLuHVAAbFlu>?>CD>Xxb$L#{SQhBQJ&=DPBID+pZ;MLWYpw%0&4X0q{ z`gF%1zyGGk^}ESPAT<;U!MyVyu>XA< z_x1fmj>aCF1Dr`1!U?C>YN4>G0Cv{Z!slO}2A|IdTedvevmCrX3Vw^-eIywi0GG?@ zk|^X^yXtm;`b-yGy*dJ~A3X|$aQ%bYMBsNY!pRuLsc#>9XLj>ujF8&{$uO ztrlk3&RI$mtJ;5(+H>LDIb6T_)#)#`&CT6x%Fo{j8Ch9iw>wA$=96Md?@={$GOU^C zW_vie|CLv_%jJp=GG6-!w5V#-5>?}x0HbPNpP$$zKnwNJBJh}`eionYQh%=AnbHH2hq1bORO`x*Qe6b9y2~yrUDVF8gVkKsoJ_d9XpCe_*>rGa>6K)xosNU38rrDURE=u_q!PIp#RnS>pWGl6ZY7)`u~t>%ngG*^7}*$k7@6$xtXb8P skwA