mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-15 04:31:55 +00:00
Added AS3 Display missing namespaces along traits as §§namespace("url")
Added #1892 AS3 option to select SWF dependencies to properly resolve namespaces, types, etc. (currently in GUI only) Fixed AS3 P-code ValueKind namespaces handling Fixed AS3 direct editation - namespace definition without explicit value
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<SWF> 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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Map.Entry<String, Map<String, String>>> 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);
|
||||
|
||||
@@ -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<Map.Entry<String, Map<String, String>>> metadata, NamespaceItem pkg, String customNamespace, boolean isStatic, String var, GraphTargetItem type, GraphTargetItem value, int line) {
|
||||
public ConstAVM2Item(List<Map.Entry<String, Map<String, String>>> 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
|
||||
|
||||
@@ -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<ValueKind> 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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
|
||||
public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<DottedChain> 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(" ");
|
||||
|
||||
@@ -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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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
|
||||
|
||||
@@ -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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
|
||||
public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,11 +63,11 @@ public class TraitMethodGetterSetter extends Trait {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
|
||||
public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
|
||||
public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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
|
||||
|
||||
@@ -298,9 +298,9 @@ public class Traits implements Cloneable, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
|
||||
public void getDependencies(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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<Dependency> dependencies, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) {
|
||||
public static void parseDependenciesFromNS(AbcIndexing abcIndex, String ignoredCustom, ABC abc, List<Dependency> 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<Dependency> dependencies, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
|
||||
public static void parseDependenciesFromMultiname(AbcIndexing abcIndex, String ignoredCustom, ABC abc, List<Dependency> dependencies, Multiname m, DottedChain ignorePackage, List<DottedChain> 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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> 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<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ public class LinkReportExporter {
|
||||
List<Dependency> dependencies = new ArrayList<>();
|
||||
sb.append(indent(3)).append("<dep id=\"AS3\" />").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())) {
|
||||
|
||||
@@ -148,7 +148,7 @@ public class SwfToSwcExporter {
|
||||
sb.append(" <dep id=\"AS3\" type=\"").append(DEPENDENCY_NAMESPACE).append("\" />\n");
|
||||
if (!skipDependencies) {
|
||||
List<Dependency> 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())) {
|
||||
|
||||
@@ -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<OpenableList> 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<String> 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<SWF> namesToSwfs(List<String> names) {
|
||||
List<SWF> ret = new ArrayList<>();
|
||||
Map<String, SWF> 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<String, SWF> swfs) {
|
||||
if (mainFrame == null) {
|
||||
return;
|
||||
}
|
||||
List<OpenableList> 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<String, SWF> 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());
|
||||
|
||||
@@ -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<Scr
|
||||
private final JButton cancelDecompiledButton = new JButton(AppStrings.translate("button.cancel"), View.getIcon("cancel16"));
|
||||
|
||||
private String lastDecompiled = null;
|
||||
|
||||
private JLabel linksLabel = new JLabel("");
|
||||
|
||||
public MainPanel getMainPanel() {
|
||||
View.checkAccess();
|
||||
@@ -260,6 +262,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
|
||||
setDecompiledEditMode(false);
|
||||
navigator.setAbc(abc);
|
||||
updateConstList();
|
||||
updateLinksLabel();
|
||||
}
|
||||
|
||||
public void updateConstList() {
|
||||
@@ -998,7 +1001,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
|
||||
toolbarPanel = new JPanel(new BorderLayout());
|
||||
toolbarPanel.add(iconsPanel, BorderLayout.WEST);
|
||||
|
||||
JPanel librarySelectPanel = new JPanel(new FlowLayout());
|
||||
JPanel libraryAndLinkPanel = new JPanel(new FlowLayout());
|
||||
|
||||
LinkDialog linkDialog = new LinkDialog(mainPanel);
|
||||
|
||||
libraryComboBox = new JComboBox<>();
|
||||
libraryComboBox.addItem("AIR (airglobal.swc)");
|
||||
libraryComboBox.addItem("Flash (playerglobal.swc)");
|
||||
@@ -1012,14 +1018,41 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
|
||||
}
|
||||
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle());
|
||||
conf.setCustomData(CustomConfigurationKeys.KEY_LIBRARY, "" + libraryComboBox.getSelectedIndex());
|
||||
swf.resetAbcIndex();
|
||||
reload();
|
||||
linkDialog.load(getSwf());
|
||||
linkDialog.save(getSwf(), true);
|
||||
}
|
||||
});
|
||||
|
||||
librarySelectPanel.add(new JLabel(AppStrings.translate("library")));
|
||||
librarySelectPanel.add(libraryComboBox);
|
||||
toolbarPanel.add(librarySelectPanel, BorderLayout.EAST);
|
||||
libraryAndLinkPanel.add(new JLabel(AppStrings.translate("library")));
|
||||
libraryAndLinkPanel.add(libraryComboBox);
|
||||
|
||||
|
||||
libraryAndLinkPanel.add(linksLabel);
|
||||
|
||||
JButton linkButton = new JButton(View.getIcon("link16"));
|
||||
linkButton.setToolTipText(AppStrings.translate("button.abc.linkedSwfs.hint"));
|
||||
|
||||
linkDialog.addSaveListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
reload();
|
||||
}
|
||||
});
|
||||
|
||||
linkButton.addActionListener(new ActionListener(){
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
linkDialog.setLocationRelativeTo(linkButton);
|
||||
Point loc = new Point(0, linkButton.getHeight());
|
||||
SwingUtilities.convertPointToScreen(loc, linkButton);
|
||||
linkDialog.setLocation(loc);
|
||||
|
||||
linkDialog.show(getSwf());
|
||||
}
|
||||
});
|
||||
libraryAndLinkPanel.add(linkButton);
|
||||
|
||||
toolbarPanel.add(libraryAndLinkPanel, BorderLayout.EAST);
|
||||
|
||||
topPanel.add(toolbarPanel, BorderLayout.CENTER);
|
||||
|
||||
@@ -1384,7 +1417,22 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
|
||||
}
|
||||
|
||||
decompiledTextArea.reloadClass();
|
||||
detailPanel.methodTraitPanel.methodCodePanel.clear();
|
||||
detailPanel.methodTraitPanel.methodCodePanel.clear();
|
||||
updateLinksLabel();
|
||||
}
|
||||
|
||||
private void updateLinksLabel() {
|
||||
SWF swf = getSwf();
|
||||
if (swf == null) {
|
||||
linksLabel.setText("");
|
||||
} else {
|
||||
int num = swf.getNumAbcIndexDependencies();
|
||||
if (num == 0) {
|
||||
linksLabel.setText("");
|
||||
} else {
|
||||
linksLabel.setText(AppStrings.translate(num == 1 ? "abc.linkedSwfs.one" : "abc.linkedSwfs.more").replace("%num%", "" + num));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
248
src/com/jpexs/decompiler/flash/gui/abc/LinkDialog.java
Normal file
248
src/com/jpexs/decompiler/flash/gui/abc/LinkDialog.java
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (C) 2023 JPEXS
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.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<LinkItem> linkList;
|
||||
|
||||
private SWF swf;
|
||||
|
||||
private List<ActionListener> 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<SWF> 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<String> 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<String, SWF> 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<SWF> swfs = new ArrayList<>(map.values());
|
||||
if (!Objects.equals(oldValue, newValue) || force) {
|
||||
swf.setAbcIndexDependencies(swfs);
|
||||
fireSave();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, SWF> getSelectedSwfs() {
|
||||
ListModel<LinkItem> model = linkList.getModel();
|
||||
Map<String, SWF> 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<SWF> selectedSWFs) {
|
||||
Map<String, SWF> swfs = new LinkedHashMap<>();
|
||||
Main.populateAllSWFs(swfs);
|
||||
DefaultListModel<LinkItem> 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<LinkItem> {
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends LinkItem> 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;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
src/com/jpexs/decompiler/flash/gui/graphics/link16.png
Normal file
BIN
src/com/jpexs/decompiler/flash/gui/graphics/link16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 649 B |
BIN
src/com/jpexs/decompiler/flash/gui/graphics/link32.png
Normal file
BIN
src/com/jpexs/decompiler/flash/gui/graphics/link32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1121,4 +1121,8 @@ button.morph.start = Start
|
||||
button.morph.end = End
|
||||
|
||||
header.displayrect.unit.pixels = pixels
|
||||
header.displayrect.unit.twips = twips
|
||||
header.displayrect.unit.twips = twips
|
||||
|
||||
button.abc.linkedSwfs.hint = Other SWF dependencies
|
||||
abc.linkedSwfs.one = +1 swf
|
||||
abc.linkedSwfs.more = +%num% swfs
|
||||
Reference in New Issue
Block a user