diff --git a/CHANGELOG.md b/CHANGELOG.md index fe73f8d79..539a808ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - AS3 - Show `Embed` tag over asset classes (readonly) - AS3 - Checkbox for exporting assets embedded using `Embed` (-exportembed in commandline) - FLA export - AS3 - Using `Embed` tag for DefineBinaryData, images not extending BitmapData +- [#2066] AS3 Support for api-versioned SWFs ### Fixed - [#2043] StartSound2 tag handling @@ -3098,6 +3099,7 @@ Major version of SWF to XML export changed to 2. [#2070]: https://www.free-decompiler.com/flash/issues/2070 [#2073]: https://www.free-decompiler.com/flash/issues/2073 [#2057]: https://www.free-decompiler.com/flash/issues/2057 +[#2066]: https://www.free-decompiler.com/flash/issues/2066 [#2043]: https://www.free-decompiler.com/flash/issues/2043 [#2017]: https://www.free-decompiler.com/flash/issues/2017 [#2052]: https://www.free-decompiler.com/flash/issues/2052 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java index c8be6a411..bb854071a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ScriptPack.java @@ -128,8 +128,9 @@ public class ScriptPack extends AS3ClassTreeItem { public Trait getPublicTrait() { for (int t : traitIndices) { Multiname name = abc.script_info.get(scriptIndex).traits.traits.get(t).getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + //Namespace ns = name.getNamespace(abc.constants); + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { return abc.script_info.get(scriptIndex).traits.traits.get(t); } } @@ -205,8 +206,8 @@ public class ScriptPack extends AS3ClassTreeItem { for (int t : traitIndices) { Trait trait = traits.get(t); Multiname name = trait.getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { trait.convertPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); } else { trait.convert(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, scopeStack); @@ -256,8 +257,8 @@ public class ScriptPack extends AS3ClassTreeItem { writer.startTrait(t); //} Multiname name = trait.getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { trait.toStringPackaged(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); } else { trait.toString(abcIndex, null, convertData, "", abc, false, exportMode, scriptIndex, -1, writer, new ArrayList<>(), parallel, false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java index bf015ba32..d633c0a61 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java @@ -335,9 +335,10 @@ public final class AbcIndexing { this.type = type; if (scriptIndex != null) { for (Trait t : abc.script_info.get(scriptIndex).traits.traits) { - Namespace ns = t.getName(abc).getNamespace(abc.constants); - if (ns.kind == Namespace.KIND_PACKAGE) { - pkg = ns.getName(abc.constants); + Multiname m = t.getName(abc); + int nskind = m.getSimpleNamespaceKind(abc.constants); + if (nskind == Namespace.KIND_PACKAGE) { + pkg = m.getSimpleNamespaceName(abc.constants); } } } @@ -818,7 +819,7 @@ public final class AbcIndexing { continue; } ClassInfo ci = abc.class_info.get(tc.class_info); - int nsKind = abc.constants.getMultiname(tc.name_index).getNamespace(abc.constants).kind; + int nsKind = abc.constants.getMultiname(tc.name_index).getSimpleNamespaceKind(abc.constants); Integer classScriptIndex = nsKind == Namespace.KIND_PACKAGE ? null : i; ClassIndex cindex = new ClassIndex(tc.class_info, abc, null, classScriptIndex); addedClasses.add(cindex); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index 76d782abf..4233c1161 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -187,7 +187,7 @@ public class InstanceInfo { String modifiers; Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - modifiers = ns.getPrefix(abc); + modifiers = ns.getPrefix(); if (!allowPrivate && modifiers.equals("private")) { modifiers = ""; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index ee3faed41..b5abe6580 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -24,8 +24,11 @@ import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Objects; +import java.util.Set; /** * @@ -410,19 +413,26 @@ public class Multiname { if (cached != null) { return cached; } - Namespace ns = getNamespace(constants); - if (ns == null) { - NamespaceSet nss = getNamespaceSet(constants); - if (nss != null) { - if (nss.namespaces.length == 1) { - ns = constants.getNamespace(nss.namespaces[0]); + + DottedChain nsName = getSimpleNamespaceName(constants); + if (nsName == null) { + Namespace ns = getNamespace(constants); + if (ns == null) { + NamespaceSet nss = getNamespaceSet(constants); + if (nss != null) { + if (nss.namespaces.length == 1) { + ns = constants.getNamespace(nss.namespaces[0]); + } } } + if (ns != null) { + nsName = ns.getName(constants); + } } String name = getName(constants, null, true, false); DottedChain ret; - if (ns != null) { - ret = ns.getName(constants).add(name, withSuffix ? getNamespaceSuffix() : ""); + if (nsName != null) { + ret = nsName.add(name, withSuffix ? getNamespaceSuffix() : ""); } else { ret = new DottedChain(new String[]{name}, new String[]{withSuffix ? getNamespaceSuffix() : ""}); } @@ -437,6 +447,60 @@ public class Multiname { return constants.getNamespace(namespace_index); } } + + /** + * Gets simple namespace name as dottedchain. Ignores swf api versioning. + * @param constants + * @return + */ + public DottedChain getSimpleNamespaceName(AVM2ConstantPool constants) { + if (hasOwnNamespace()) { + if (namespace_index == 0 || namespace_index == -1) { + return DottedChain.EMPTY; + } + return getNamespace(constants).getName(constants); + } + if (hasOwnNamespaceSet()) { + NamespaceSet nss = getNamespaceSet(constants); + if (nss == null) { + return null; + } + return nss.getNonversionedName(constants); + } + return null; + } + + /** + * Gets simplpe namespace kind. Ignores swf api versioning. + * @param constants + * @return + */ + public int getSimpleNamespaceKind(AVM2ConstantPool constants) { + if (hasOwnNamespace()) { + if (namespace_index == 0 || namespace_index == -1) { + return 0; + } + return getNamespace(constants).kind; + } + if (hasOwnNamespaceSet()) { + NamespaceSet nss = getNamespaceSet(constants); + if (nss == null) { + return 0; + } + return nss.getNonversionedKind(constants); + } + return 0; + } + + public List getApiVersions(AVM2ConstantPool constants) { + if (hasOwnNamespace()) { + return new ArrayList<>(); + } + if (hasOwnNamespaceSet()) { + return getNamespaceSet(constants).getApiVersions(constants); + } + return new ArrayList<>(); + } public NamespaceSet getNamespaceSet(AVM2ConstantPool constants) { if (namespace_set_index == 0) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Namespace.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Namespace.java index 376e74d18..1f86ed4f8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Namespace.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Namespace.java @@ -26,6 +26,10 @@ import com.jpexs.decompiler.graph.DottedChain; * @author JPEXS */ public class Namespace { + + public static final int MIN_API_MARK = 0xE000; + + public static final int MAX_API_MARK = 0xF8FF; public static final int KIND_NAMESPACE = 8; @@ -107,7 +111,18 @@ public class Namespace { return kindStr + (nameStr == null || nameStr.isEmpty() ? "" : " " + nameStr); } - public String getPrefix(ABC abc) { + public String getPrefix() { + String kindStr = "?"; + for (int k = 0; k < nameSpaceKinds.length; k++) { + if (nameSpaceKinds[k] == kind) { + kindStr = namePrefixes[k]; + break; + } + } + return kindStr; + } + + public static String getPrefix(int kind) { String kindStr = "?"; for (int k = 0; k < nameSpaceKinds.length; k++) { if (nameSpaceKinds[k] == kind) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java index 93297b4c3..3eb893c72 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java @@ -18,6 +18,11 @@ package com.jpexs.decompiler.flash.abc.types; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.types.annotations.Internal; +import com.jpexs.decompiler.graph.DottedChain; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * @@ -47,4 +52,78 @@ public class NamespaceSet { } return sb.toString(); } + + public List getApiVersions(AVM2ConstantPool constants) { + Set namespaceNames = new HashSet<>(); + Set namespaceKinds = new HashSet<>(); + List apiVersions = new ArrayList<>(); + for (int n:namespaces) { + Namespace ns = constants.getNamespace(n); + String nsName = ns.getRawName(constants); + if (nsName != null && nsName.length() > 0) { + int lastChar = nsName.codePointAt(nsName.length() - 1); + if (lastChar >= Namespace.MIN_API_MARK && lastChar <= Namespace.MAX_API_MARK) { + namespaceNames.add(nsName.substring(0, nsName.length() - 1)); + namespaceKinds.add(ns.kind); + int apiVersion = lastChar - Namespace.MIN_API_MARK; + if (apiVersion != 0) { + apiVersions.add(apiVersion); + } + } else { + return new ArrayList<>(); + } + } + } + if (namespaceNames.size() != 1) { + return new ArrayList<>(); + } + if (namespaceKinds.size() != 1) { + return new ArrayList<>(); + } + return apiVersions; + } + + public int getNonversionedKind(AVM2ConstantPool constants) { + Set namespaceNames = new HashSet<>(); + Set namespaceKinds = new HashSet<>(); + for (int n:namespaces) { + Namespace ns = constants.getNamespace(n); + String nsName = ns.getRawName(constants); + if (nsName != null && nsName.length() > 0) { + int lastChar = nsName.codePointAt(nsName.length() - 1); + if (lastChar >= Namespace.MIN_API_MARK && lastChar <= Namespace.MAX_API_MARK) { + namespaceNames.add(nsName.substring(0, nsName.length() - 1)); + namespaceKinds.add(ns.kind); + } else { + return 0; + } + } + } + if (namespaceNames.size() != 1) { + return 0; + } + if (namespaceKinds.size() != 1) { + return 0; + } + return namespaceKinds.iterator().next(); + } + + public DottedChain getNonversionedName(AVM2ConstantPool constants) { + Set namespaceNames = new HashSet<>(); + for (int n:namespaces) { + String nsName = constants.getNamespace(n).getRawName(constants); + if (nsName != null && nsName.length() > 0) { + int lastChar = nsName.codePointAt(nsName.length() - 1); + if (lastChar >= Namespace.MIN_API_MARK && lastChar <= Namespace.MAX_API_MARK) { + namespaceNames.add(nsName.substring(0, nsName.length() - 1)); + } else { + return null; + } + } + } + if (namespaceNames.size() != 1) { + return null; + } + return DottedChain.parseNoSuffix(namespaceNames.iterator().next()); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index c208bae78..e707341ea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -97,19 +97,19 @@ public class ScriptInfo { for (int j = 0; j < traits.traits.size(); j++) { Trait t = traits.traits.get(j); Multiname name = t.getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if (!((ns.kind == Namespace.KIND_PACKAGE_INTERNAL) - || (ns.kind == Namespace.KIND_PACKAGE))) { + int nskind = name.getSimpleNamespaceKind(abc.constants); + if (!((nskind == Namespace.KIND_PACKAGE_INTERNAL) + || (nskind == Namespace.KIND_PACKAGE))) { otherTraits.add(j); } } for (int j = 0; j < traits.traits.size(); j++) { Trait t = traits.traits.get(j); Multiname name = t.getName(abc); - Namespace ns = name.getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE_INTERNAL) - || (ns.kind == Namespace.KIND_PACKAGE)) { - DottedChain packageName = ns.getName(abc.constants); // assume not null package + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE_INTERNAL) + || (nskind == Namespace.KIND_PACKAGE)) { + DottedChain packageName = name.getSimpleNamespaceName(abc.constants); // assume not null package String objectName = name.getName(abc.constants, null, true, false); String namespaceSuffix = name.getNamespaceSuffix(); List traitIndices = new ArrayList<>(); @@ -134,9 +134,8 @@ public class ScriptInfo { for (int traitIndex : otherTraits) { Trait t = traits.traits.get(traitIndex); Multiname name = t.getName(abc); - Namespace ns = name.getNamespace(abc.constants); - - DottedChain packageName = ns.getName(abc.constants); + + DottedChain packageName = name.getSimpleNamespaceName(abc.constants); String objectName = name.getName(abc.constants, null, true, false); String namespaceSuffix = name.getNamespaceSuffix(); 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 9a6d993db..5f9ab3ab6 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 @@ -170,14 +170,15 @@ public abstract class Trait implements Cloneable, Serializable { } protected DottedChain getPackage(ABC abc) { - return getName(abc).getNamespace(abc.constants).getName(abc.constants); + return getName(abc).getSimpleNamespaceName(abc.constants); } 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(); + Multiname m = getName(abc); + int nskind = m.getSimpleNamespaceKind(abc.constants); + if (nskind == Namespace.KIND_NAMESPACE) { + ignoredCustom = m.getSimpleNamespaceName(abc.constants).toRawString(); } } DependencyParser.parseDependenciesFromMultiname(abcIndex, ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE); @@ -199,8 +200,8 @@ public abstract class Trait implements Cloneable, Serializable { boolean publicProtectedOnly = isParent; for (Trait it : abc.instance_info.get(classIndex).instance_traits.traits) { if (publicProtectedOnly) { - Namespace ns = it.getName(abc).getNamespace(abc.constants); - if (ns.kind != Namespace.KIND_PACKAGE && ns.kind != Namespace.KIND_PROTECTED) { + int nskind = it.getName(abc).getSimpleNamespaceKind(abc.constants); + if (nskind != Namespace.KIND_PACKAGE && nskind != Namespace.KIND_PROTECTED) { continue; } } @@ -208,8 +209,8 @@ public abstract class Trait implements Cloneable, Serializable { } for (Trait ct : abc.class_info.get(classIndex).static_traits.traits) { if (publicProtectedOnly) { - Namespace ns = ct.getName(abc).getNamespace(abc.constants); - if (ns.kind != Namespace.KIND_PACKAGE && ns.kind != Namespace.KIND_STATIC_PROTECTED) { + int nskind = ct.getName(abc).getSimpleNamespaceKind(abc.constants); + if (nskind != Namespace.KIND_PACKAGE && nskind != Namespace.KIND_STATIC_PROTECTED) { continue; } } @@ -249,9 +250,10 @@ public abstract class Trait implements Cloneable, Serializable { //imports List dependencies = new ArrayList<>(); String customNs = null; - Namespace ns = getName(abc).getNamespace(abc.constants); - if (ns.kind == Namespace.KIND_NAMESPACE) { - customNs = ns.getName(abc.constants).toRawString(); + Multiname multiname = getName(abc); + int nskind = multiname.getSimpleNamespaceKind(abc.constants); + if (nskind == Namespace.KIND_NAMESPACE) { + customNs = multiname.getSimpleNamespaceName(abc.constants).toRawString(); } getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, new ArrayList<>()); @@ -367,6 +369,15 @@ public abstract class Trait implements Cloneable, Serializable { writer.append("]"); writer.newLine(); } + getApiVersions(abc, writer); + return writer; + } + + public final GraphTextWriter getApiVersions(ABC abc, GraphTextWriter writer) { + List apiVersions = abc.constants.getMultiname(name_index).getApiVersions(abc.constants); + for(int version:apiVersions) { + writer.appendNoHilight("[API(\"" + version + "\")]").newLine(); + } return writer; } @@ -384,21 +395,21 @@ public abstract class Trait implements Cloneable, Serializable { DottedChain dc = abc.findCustomNs(m.namespace_index); String nsname = dc != null ? dc.getLast() : null; - Namespace ns = m.getNamespace(abc.constants); + int nskind = m.getSimpleNamespaceKind(abc.constants); if (insideInterface) { //no namespace identifier - } else if (ns.kind == Namespace.KIND_NAMESPACE && nsname == null) { + } else if (nskind == Namespace.KIND_NAMESPACE && nsname == null) { writer.append("§§namespace(\""); - writer.append(Helper.escapeActionScriptString(ns.getRawName(abc.constants))); + writer.append(Helper.escapeActionScriptString(m.getSimpleNamespaceName(abc.constants).toRawString())); writer.append("\") "); } else if (nsname != null) { String identifier = IdentifiersDeobfuscation.printIdentifier(true, nsname); if (identifier != null && !identifier.isEmpty()) { writer.appendNoHilight(identifier).appendNoHilight(" "); } - } else if (ns != null) { - String nsPrefix = ns.getPrefix(abc); + } else if (nskind != 0) { + String nsPrefix = Namespace.getPrefix(nskind); if (nsPrefix != null && !nsPrefix.isEmpty()) { writer.appendNoHilight(nsPrefix).appendNoHilight(" "); } @@ -508,9 +519,10 @@ public abstract class Trait implements Cloneable, Serializable { } public GraphTextWriter toStringPackaged(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List fullyQualifiedNames, boolean parallel, boolean insideInterface) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants).toPrintableString(true); + Multiname name = abc.constants.getMultiname(name_index); + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = name.getSimpleNamespaceName(abc.constants).toPrintableString(true); writer.appendNoHilight("package"); if (!nsname.isEmpty()) { writer.appendNoHilight(" " + nsname); //assume not null name @@ -524,9 +536,10 @@ public abstract class Trait implements Cloneable, Serializable { } public void convertPackaged(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List fullyQualifiedNames, boolean parallel, ScopeStack scopeStack) throws InterruptedException { - Namespace ns = abc.constants.getMultiname(name_index).getNamespace(abc.constants); - if ((ns.kind == Namespace.KIND_PACKAGE) || (ns.kind == Namespace.KIND_PACKAGE_INTERNAL)) { - String nsname = ns.getName(abc.constants).toPrintableString(true); + Multiname name = abc.constants.getMultiname(name_index); + int nskind = name.getSimpleNamespaceKind(abc.constants); + if ((nskind == Namespace.KIND_PACKAGE) || (nskind == Namespace.KIND_PACKAGE_INTERNAL)) { + String nsname = name.getSimpleNamespaceName(abc.constants).toPrintableString(true); convert(abcIndex, parent, convertData, path + nsname, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel, scopeStack); } } 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 2a8200f6b..1a7d0f3bd 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 @@ -139,7 +139,7 @@ public class TraitClass extends Trait implements TraitWithSlot { String instanceInfoName = instanceInfoMultiname.getName(abc.constants, fullyQualifiedNames, false, true); getMetaData(parent, convertData, abc, writer); - + boolean allowEmbed = true; if (convertData.exportEmbedFlaMode) { 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 70a2b5a5a..62cb7bf8e 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 @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.ConvertData; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; @@ -70,9 +71,10 @@ public class TraitMethodGetterSetter extends Trait { super.getDependencies(abcIndex, scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames); if (customNs == null) { - Namespace n = getName(abc).getNamespace(abc.constants); - if (n.kind == Namespace.KIND_NAMESPACE) { - customNs = n.getName(abc.constants).toRawString(); + Multiname m = getName(abc); + int nskind = m.getSimpleNamespaceKind(abc.constants); + if (nskind == Namespace.KIND_NAMESPACE) { + customNs = m.getSimpleNamespaceName(abc.constants).toRawString(); } } //if (method_info != 0) diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.abc b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.abc new file mode 100644 index 000000000..a0172c1be Binary files /dev/null and b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.abc differ diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.cpp b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.cpp new file mode 100644 index 000000000..f26c97271 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.cpp @@ -0,0 +1,50 @@ +const int as3_versioned_abc_length = 718; +const int as3_versioned_abc_method_count = 0; +const int as3_versioned_abc_class_count = 3; +const int as3_versioned_abc_script_count = 2; +const unsigned char as3_versioned_abc_data[718] = { +0x10, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x18, 0x00, 0x04, 0x76, 0x6f, 0x69, 0x64, 0x06, 0x4f, +0x62, 0x6a, 0x65, 0x63, 0x74, 0x06, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x05, 0x6d, 0x79, 0x70, +0x6b, 0x67, 0x07, 0x4d, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x0d, 0x6d, 0x79, 0x70, 0x6b, 0x67, +0x3a, 0x4d, 0x79, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x04, 0x74, 0x65, 0x73, 0x74, 0x03, 0xee, 0x80, +0x80, 0x08, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x36, 0x36, 0x32, 0x03, 0xee, 0x8a, 0x96, 0x08, 0x74, +0x65, 0x73, 0x74, 0x5f, 0x36, 0x37, 0x34, 0x03, 0xee, 0x8a, 0xa2, 0x0c, 0x74, 0x65, 0x73, 0x74, +0x5f, 0x36, 0x36, 0x32, 0x5f, 0x36, 0x37, 0x34, 0x03, 0x41, 0x53, 0x33, 0x21, 0x68, 0x74, 0x74, +0x70, 0x3a, 0x2f, 0x2f, 0x61, 0x64, 0x6f, 0x62, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x41, 0x53, +0x33, 0x2f, 0x32, 0x30, 0x30, 0x36, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x69, 0x6e, 0x03, 0x4e, +0x61, 0x4e, 0x08, 0x49, 0x6e, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x79, 0x09, 0x75, 0x6e, 0x64, 0x65, +0x66, 0x69, 0x6e, 0x65, 0x64, 0x08, 0x6d, 0x79, 0x70, 0x6b, 0x67, 0xee, 0x8a, 0x95, 0x08, 0x6d, +0x79, 0x70, 0x6b, 0x67, 0xee, 0x8a, 0x96, 0x05, 0x74, 0x72, 0x61, 0x63, 0x65, 0x0b, 0x48, 0x65, +0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x11, 0x16, 0x01, 0x18, 0x03, 0x18, 0x04, +0x16, 0x05, 0x18, 0x07, 0x16, 0x09, 0x16, 0x0b, 0x16, 0x0d, 0x08, 0x10, 0x16, 0x14, 0x16, 0x15, +0x05, 0x00, 0x05, 0x00, 0x17, 0x05, 0x1a, 0x07, 0x17, 0x01, 0x0b, 0x01, 0x06, 0x01, 0x07, 0x01, +0x08, 0x02, 0x07, 0x08, 0x02, 0x0a, 0x0b, 0x07, 0x01, 0x0c, 0x0d, 0x04, 0x0e, 0x05, 0x0f, 0x01, +0x01, 0x03, 0x01, 0x0d, 0x10, 0x01, 0x04, 0x04, 0x01, 0x0d, 0x04, 0x0e, 0x1a, 0x07, 0x01, 0x02, +0x07, 0x01, 0x03, 0x07, 0x01, 0x04, 0x07, 0x04, 0x06, 0x09, 0x08, 0x01, 0x09, 0x0a, 0x02, 0x09, +0x0c, 0x03, 0x09, 0x0e, 0x04, 0x09, 0x0f, 0x01, 0x09, 0x11, 0x01, 0x09, 0x12, 0x01, 0x09, 0x13, +0x01, 0x09, 0x03, 0x01, 0x09, 0x04, 0x01, 0x09, 0x06, 0x05, 0x09, 0x16, 0x06, 0x09, 0x0c, 0x06, +0x09, 0x03, 0x07, 0x09, 0x04, 0x07, 0x09, 0x03, 0x08, 0x09, 0x06, 0x09, 0x09, 0x03, 0x0a, 0x07, +0x01, 0x11, 0x07, 0x01, 0x12, 0x07, 0x01, 0x13, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x09, 0x02, 0x00, +0x01, 0x00, 0x03, 0x02, 0x09, 0x03, 0x00, 0x03, 0x00, 0x04, 0x02, 0x09, 0x05, 0x00, 0x09, 0x04, +0x05, 0x01, 0x02, 0x05, 0x06, 0x01, 0x03, 0x06, 0x07, 0x01, 0x04, 0x07, 0x08, 0x01, 0x05, 0x08, +0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x02, 0x0b, 0x04, 0x09, 0x06, 0x01, 0x00, 0x09, 0x08, 0x0a, +0x06, 0x02, 0x03, 0x01, 0x06, 0x0b, 0x06, 0x03, 0x03, 0x02, 0x06, 0x0c, 0x06, 0x04, 0x00, 0x00, +0x0a, 0x03, 0x0d, 0x04, 0x00, 0x00, 0x0e, 0x04, 0x00, 0x01, 0x0f, 0x04, 0x00, 0x02, 0x0c, 0x00, +0x01, 0x01, 0x02, 0x03, 0x03, 0xd0, 0x30, 0x47, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x04, 0x03, +0xd0, 0x30, 0x47, 0x00, 0x00, 0x02, 0x01, 0x01, 0x03, 0x04, 0x03, 0xd0, 0x30, 0x47, 0x00, 0x00, +0x03, 0x01, 0x01, 0x04, 0x05, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00, 0x47, 0x00, 0x00, 0x04, 0x01, +0x01, 0x03, 0x04, 0x03, 0xd0, 0x30, 0x47, 0x00, 0x00, 0x05, 0x02, 0x01, 0x04, 0x05, 0x0a, 0xd0, +0x30, 0x5d, 0x10, 0x2c, 0x17, 0x4f, 0x10, 0x01, 0x47, 0x00, 0x00, 0x06, 0x02, 0x01, 0x04, 0x05, +0x0a, 0xd0, 0x30, 0x5d, 0x10, 0x2c, 0x17, 0x4f, 0x10, 0x01, 0x47, 0x00, 0x00, 0x07, 0x02, 0x01, +0x04, 0x05, 0x0a, 0xd0, 0x30, 0x5d, 0x10, 0x2c, 0x17, 0x4f, 0x10, 0x01, 0x47, 0x00, 0x00, 0x08, +0x02, 0x01, 0x04, 0x05, 0x0e, 0xd0, 0x30, 0xd0, 0x4f, 0x11, 0x00, 0x5d, 0x10, 0x2c, 0x17, 0x4f, +0x10, 0x01, 0x47, 0x00, 0x00, 0x09, 0x01, 0x01, 0x04, 0x05, 0x06, 0xd0, 0x30, 0xd0, 0x49, 0x00, +0x47, 0x00, 0x00, 0x0a, 0x02, 0x01, 0x01, 0x03, 0x22, 0xd0, 0x30, 0x5d, 0x12, 0x20, 0x58, 0x00, +0x68, 0x02, 0x5d, 0x13, 0x60, 0x02, 0x30, 0x60, 0x14, 0x58, 0x01, 0x1d, 0x68, 0x03, 0x5d, 0x15, +0x60, 0x02, 0x30, 0x60, 0x16, 0x58, 0x02, 0x1d, 0x68, 0x04, 0x47, 0x00, 0x00, 0x0b, 0x03, 0x01, +0x01, 0x02, 0x19, 0xd0, 0x30, 0x65, 0x00, 0x24, 0x00, 0x2a, 0xa3, 0x68, 0x17, 0x65, 0x00, 0x24, +0x01, 0x24, 0x00, 0xa3, 0x68, 0x18, 0x65, 0x00, 0x21, 0x68, 0x19, 0x47, 0x00, 0x00 }; diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.h b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.h new file mode 100644 index 000000000..c5bb298a1 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/bin/as3_versioned.h @@ -0,0 +1,10 @@ +const int abcclass_Object = 0; +const int abcclass_Number = 1; +const int abcclass_mypkg_MyClass = 2; +const int abcpackage_Toplevel_as = 0; +const int abcpackage_stubs_as = 1; +extern const int as3_versioned_abc_length; +extern const int as3_versioned_abc_method_count; +extern const int as3_versioned_abc_class_count; +extern const int as3_versioned_abc_script_count; +extern const unsigned char as3_versioned_abc_data[]; diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/build_air_debug.bat b/libsrc/ffdec_lib/testdata/as3_versioned/build_air_debug.bat new file mode 100644 index 000000000..2afd751b2 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/build_air_debug.bat @@ -0,0 +1,7 @@ +@echo off +set COMPILERKIND=flex +set SWFNAME=as3_versioned +rem call c:\air\bin\mxmlc.bat -debug=true -builtin -apiversioning -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 +java -classpath c:\flex\lib\asc.jar macromedia.asc.embedding.ScriptCompiler -optimize -builtin -apiversioning -outdir bin/ -out as3_versioned src/stubs.as src/Toplevel.as +pause +rem -warnings=false diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/src/Number.as b/libsrc/ffdec_lib/testdata/as3_versioned/src/Number.as new file mode 100644 index 000000000..2982227d1 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/src/Number.as @@ -0,0 +1,4 @@ +package { + public class Number { + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/src/Object.as b/libsrc/ffdec_lib/testdata/as3_versioned/src/Object.as new file mode 100644 index 000000000..66e32ec59 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/src/Object.as @@ -0,0 +1,6 @@ +package +{ + public class Object + { + } +} diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/src/Toplevel.as b/libsrc/ffdec_lib/testdata/as3_versioned/src/Toplevel.as new file mode 100644 index 000000000..379bc0240 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/src/Toplevel.as @@ -0,0 +1,9 @@ +package { + public namespace AS3 = "http://adobe.com/AS3/2006/builtin"; + + public const NaN: Number = 0 / 0; + + public const Infinity: Number = 1 / 0; + + public const undefined = void 0; +} diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/src/mypkg/MyClass.as b/libsrc/ffdec_lib/testdata/as3_versioned/src/mypkg/MyClass.as new file mode 100644 index 000000000..3310f9bf0 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/src/mypkg/MyClass.as @@ -0,0 +1,33 @@ +package mypkg +{ + [API("661")] + [API("662")] + public class MyClass + { + public function test(): void + { + trace("Hello world"); + } + + [API("662")] + public function test_662(): void + { + trace("Hello world"); + } + + [API("674")] + public function test_674(): void + { + trace("Hello world"); + } + + [API("662")] + [API("674")] + public function test_662_674(): void + { + this.test_674(); + trace("Hello world"); + } + } + +} diff --git a/libsrc/ffdec_lib/testdata/as3_versioned/src/stubs.as b/libsrc/ffdec_lib/testdata/as3_versioned/src/stubs.as new file mode 100644 index 000000000..fe040d4e4 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_versioned/src/stubs.as @@ -0,0 +1,3 @@ +include "Object.as" +include "Number.as" +include "mypkg/MyClass.as"