diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e0ddd0c8..6bc0dccfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - Folder preview resizing (scrollbar too long) - [#1872] Removing PlaceObject/RemoveObject with no characterid with Remove character action - [#1692] Resolving use namespace +- [#1692] Properly distinguish obfuscated names vs namespace suffixes and attributes ## [16.3.1] - 2022-11-14 ### Fixed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java index 1900eaf0c..db6cede3b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Deobfuscation.java @@ -48,9 +48,9 @@ public class AVM2Deobfuscation { private final Map usageTypesCount = new HashMap<>(); - public static final DottedChain FLASH_PROXY = new DottedChain(new String[]{"flash", "utils", "flash_proxy"}, ""); + public static final DottedChain FLASH_PROXY = new DottedChain(new String[]{"flash", "utils", "flash_proxy"}); - public static final DottedChain BUILTIN = new DottedChain(new String[]{"-"}, ""); + public static final DottedChain BUILTIN = new DottedChain(new String[]{"-"}); public AVM2Deobfuscation(SWF swf, AVM2ConstantPool constants) { this.swf = swf; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java index 2abafdacd..f3f6520ea 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/alchemy/AlchemyTypeIns.java @@ -24,5 +24,5 @@ import com.jpexs.decompiler.graph.DottedChain; */ public interface AlchemyTypeIns { - public static final DottedChain ALCHEMY_PACKAGE = new DottedChain(new String[]{"avm2", "intrinsics", "memory"}, DottedChain.NO_SUFFIX); + public static final DottedChain ALCHEMY_PACKAGE = new DottedChain(new String[]{"avm2", "intrinsics", "memory"}); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitVectorAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitVectorAVM2Item.java index 7c8bb139e..930eb039a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitVectorAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/InitVectorAVM2Item.java @@ -44,17 +44,17 @@ import java.util.Objects; */ public class InitVectorAVM2Item extends AVM2Item { - public static final DottedChain VECTOR_PACKAGE = new DottedChain(new String[]{"__AS3__", "vec"}, ""); + public static final DottedChain VECTOR_PACKAGE = new DottedChain(new String[]{"__AS3__", "vec"}); - public static final DottedChain VECTOR_FQN = new DottedChain(new String[]{"__AS3__", "vec", "Vector"}, ""); + public static final DottedChain VECTOR_FQN = new DottedChain(new String[]{"__AS3__", "vec", "Vector"}); - public static final DottedChain VECTOR_INT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$int"}, ""); + public static final DottedChain VECTOR_INT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$int"}); - public static final DottedChain VECTOR_DOUBLE = new DottedChain(new String[]{"__AS3__", "vec", "Vector$double"}, ""); + public static final DottedChain VECTOR_DOUBLE = new DottedChain(new String[]{"__AS3__", "vec", "Vector$double"}); - public static final DottedChain VECTOR_UINT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$uint"}, ""); + public static final DottedChain VECTOR_UINT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$uint"}); - public static final DottedChain VECTOR_OBJECT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$object"}, ""); + public static final DottedChain VECTOR_OBJECT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$object"}); public GraphTargetItem subtype; 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 f2e6e09be..eb5474986 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 @@ -746,7 +746,7 @@ public class AVM2SourceGenerator implements SourceGenerator { ret.add(ins(AVM2Instructions.NewObject, 0)); ret.add(ins(AVM2Instructions.PushWith)); scope = localData.scopeStack.size(); - localData.scopeStack.add(new PropertyAVM2Item(null, item.functionName, abcIndex, new ArrayList<>(), localData.callStack)); + localData.scopeStack.add(new PropertyAVM2Item(null, false, item.functionName, abcIndex, new ArrayList<>(), localData.callStack)); } AVM2ConstantPool constants = abcIndex.getSelectedAbc().constants; ret.add(ins(AVM2Instructions.NewFunction, method(false, constants.getStringId(item.functionName, true), true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType))); @@ -1349,7 +1349,7 @@ public class AVM2SourceGenerator implements SourceGenerator { } */ List getterBody = new ArrayList<>(); - UnresolvedAVM2Item sp = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, TypeItem.UNBOUNDED, 0, new DottedChain(new String[]{"_skinParts"}, ""), + UnresolvedAVM2Item sp = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, TypeItem.UNBOUNDED, 0, new DottedChain(new String[]{"_skinParts"}), null, openedNamespaces, abcIndex); getterBody.add(new ReturnValueAVM2Item(null, null, sp)); List subvars = new ArrayList<>(); @@ -1850,7 +1850,7 @@ public class AVM2SourceGenerator implements SourceGenerator { continue; } - NameAVM2Item d = new NameAVM2Item(n.type, n.line, n.getVariableName(), NameAVM2Item.getDefaultValue("" + n.type), true, n.openedNamespaces, abcIndex); + NameAVM2Item d = new NameAVM2Item(n.type, n.line, n.isAttribute(), n.getVariableName(), NameAVM2Item.getDefaultValue("" + n.type), true, n.openedNamespaces, abcIndex); //no index if (needsActivation) { if (d.getSlotNumber() <= 0) { @@ -1909,9 +1909,9 @@ public class AVM2SourceGenerator implements SourceGenerator { mbody.traits.traits.add(tsc); } for (int i = 1; i < paramRegCount; i++) { - NameAVM2Item param = new NameAVM2Item(registerTypes.get(i), 0, registerNames.get(i), null, false, new ArrayList<>(), abcIndex); + NameAVM2Item param = new NameAVM2Item(registerTypes.get(i), 0, false, registerNames.get(i), null, false, new ArrayList<>(), abcIndex); param.setRegNumber(i); - NameAVM2Item d = new NameAVM2Item(registerTypes.get(i), 0, registerNames.get(i), param, true, new ArrayList<>(), abcIndex); + NameAVM2Item d = new NameAVM2Item(registerTypes.get(i), 0, false, registerNames.get(i), param, true, new ArrayList<>(), abcIndex); d.setSlotScope(slotScope); d.setSlotNumber(slotNames.indexOf(registerNames.get(i))); declarations.add(d); 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 8ad9c2c4c..45fea332d 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 @@ -308,7 +308,7 @@ public class ActionScript3Parser { s = lex(); GraphTargetItem ns = null; if (s.type == SymbolType.NAMESPACE_OP) { - ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, null, lexer.yyline(), new DottedChain(new String[]{propName}, "" /*FIXME ???*/), null, openedNamespaces, abcIndex); + ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, null, lexer.yyline(), new DottedChain(new String[]{propName}, new String[]{""} /*FIXME ???*/), null, openedNamespaces, abcIndex); variables.add((UnresolvedAVM2Item) ns); s = lex(); if (s.type == SymbolType.BRACKET_OPEN) { @@ -326,7 +326,7 @@ public class ActionScript3Parser { if (ns != null) { ret = new NamespacedAVM2Item(ns, propName, propItem, ret, attr, openedNamespaces, null); } else { - ret = new PropertyAVM2Item(ret, (attr ? "@" : "") + propName, abcIndex, openedNamespaces, new ArrayList<>()); + ret = new PropertyAVM2Item(ret, attr, propName, abcIndex, openedNamespaces, new ArrayList<>()); } s = lex(); } @@ -341,24 +341,31 @@ public class ActionScript3Parser { private GraphTargetItem name(List> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference needsActivation, boolean typeOnly, List openedNamespaces, HashMap registerVars, boolean inFunction, boolean inMethod, List variables, List importedClasses) throws IOException, AVM2ParseException, InterruptedException { ParsedSymbol s = lex(); - DottedChain name = new DottedChain(new String[]{}, ""); + DottedChain name = new DottedChain(new String[]{}, new String[]{""}); + boolean attribute = false; String name2 = ""; if (s.type == SymbolType.ATTRIBUTE) { - name2 += "@"; + attribute = true; s = lex(); } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP); name2 += s.value.toString(); s = lex(); boolean attrBracket = false; + String nsSuffix = ""; + if (s.type == SymbolType.NAMESPACESUFFIX) { + s = lex(); + nsSuffix = "#" + s.value; + } - name = name.addWithSuffix(name2); + name = name.add(attribute, name2, nsSuffix); while (s.isType(SymbolType.DOT)) { //name += s.value.toString(); //. or :: s = lex(); name2 = ""; + attribute = false; if (s.type == SymbolType.ATTRIBUTE) { - name2 += "@"; + attribute = true; s = lex(); if (s.type == SymbolType.MULTIPLY) { name2 += s.value.toString(); @@ -370,19 +377,26 @@ public class ActionScript3Parser { } attrBracket = true; continue; - } + } } else { expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, SymbolType.MULTIPLY); name2 += s.value.toString(); } - name = name.addWithSuffix(name2); s = lex(); + nsSuffix = ""; + if (s.type == SymbolType.NAMESPACESUFFIX) { + nsSuffix = "#" + s.value; + s = lex(); + } + name = name.add(attribute, name2, nsSuffix); } String nsname = null; String nsprop = null; + boolean nsAtribute = false; GraphTargetItem nspropItem = null; if (s.type == SymbolType.NAMESPACE_OP) { nsname = name.getLast(); + nsAtribute = name.isLastAttribute(); s = lex(); if (s.group == SymbolGroup.IDENTIFIER) { nsprop = s.value.toString(); @@ -401,14 +415,10 @@ public class ActionScript3Parser { variables.add(unr); ret = unr; } - if (nsname != null) { - boolean attr = nsname.startsWith("@"); - if (attr) { - nsname = nsname.substring(1); - } - UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(new String[]{nsname}, ""), null, openedNamespaces, abcIndex); + if (nsname != null) { + UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(new String[]{nsname}), null, openedNamespaces, abcIndex); variables.add(ns); - ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, attr, openedNamespaces, null); + ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, nsAtribute, openedNamespaces, null); } if (s.type == SymbolType.BRACKET_OPEN) { lexer.pushback(s); @@ -543,14 +553,14 @@ public class ActionScript3Parser { } List body = null; List subvariables = new ArrayList<>(); - subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), "this", null, true, openedNamespaces, abcIndex)); + subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), false, "this", null, true, openedNamespaces, abcIndex)); for (int i = 0; i < paramNames.size() - (hasRest ? 1 : 0); i++) { - subvariables.add(new NameAVM2Item(paramTypes.get(i), lexer.yyline(), paramNames.get(i), null, true, openedNamespaces, abcIndex)); + subvariables.add(new NameAVM2Item(paramTypes.get(i), lexer.yyline(), false, paramNames.get(i), null, true, openedNamespaces, abcIndex)); } if (hasRest) { - subvariables.add(new NameAVM2Item(TypeItem.UNBOUNDED, lexer.yyline(), paramNames.get(paramNames.size() - 1), null, true, openedNamespaces, abcIndex)); + subvariables.add(new NameAVM2Item(TypeItem.UNBOUNDED, lexer.yyline(), false, paramNames.get(paramNames.size() - 1), null, true, openedNamespaces, abcIndex)); } - subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), "arguments", null, true, openedNamespaces, abcIndex)); + subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), false, "arguments", null, true, openedNamespaces, abcIndex)); int parCnt = subvariables.size(); Reference needsActivation2 = new Reference<>(false); if (!isInterface) { @@ -1467,10 +1477,10 @@ public class ActionScript3Parser { if (s.type == SymbolType.ASSIGN) { GraphTargetItem varval = (expression(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false)); - ret = new NameAVM2Item(type, lexer.yyline(), varIdentifier, varval, true, openedNamespaces, abcIndex); + ret = new NameAVM2Item(type, lexer.yyline(), false, varIdentifier, varval, true, openedNamespaces, abcIndex); variables.add((NameAVM2Item) ret); } else { - ret = new NameAVM2Item(type, lexer.yyline(), varIdentifier, null, true, openedNamespaces, abcIndex); + ret = new NameAVM2Item(type, lexer.yyline(), false, varIdentifier, null, true, openedNamespaces, abcIndex); variables.add((NameAVM2Item) ret); lexer.pushback(s); } @@ -1738,7 +1748,7 @@ public class ActionScript3Parser { String enamestr = s.value.toString(); expectedType(SymbolType.COLON); GraphTargetItem etype = type(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, variables); - NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), enamestr, new ExceptionAVM2Item(null)/*?*/, true/*?*/, openedNamespaces, abcIndex); + NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), false, enamestr, new ExceptionAVM2Item(null)/*?*/, true/*?*/, openedNamespaces, abcIndex); variables.add(e); catchExceptions.add(e); e.setSlotNumber(1); @@ -2491,8 +2501,8 @@ public class ActionScript3Parser { } s = lex(); expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - DottedChain fullName = new DottedChain(new String[]{}, ""); - fullName = fullName.addWithSuffix(s.value.toString()); + DottedChain fullName = new DottedChain(new String[]{}); + fullName = fullName.add(s.value.toString(), ""); s = lex(); boolean isStar = false; while (s.type == SymbolType.DOT) { @@ -2504,7 +2514,7 @@ public class ActionScript3Parser { break; } expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER); - fullName = fullName.addWithSuffix(s.value.toString()); + fullName = fullName.add(s.value.toString(), ""); s = lex(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java index c7f872a01..0d903bed4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScriptLexer.java @@ -1,26 +1,28 @@ +/* The following code was generated by JFlex 1.6.0 */ + /* - * Copyright (C) 2010-2022 JPEXS, All rights reserved. - * + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ package com.jpexs.decompiler.flash.abc.avm2.parser.script; import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException; import java.io.StringReader; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Stack; +import java.math.BigInteger; /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java index 8f5203aa6..466af4516 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/CallAVM2Item.java @@ -98,11 +98,11 @@ public class CallAVM2Item extends AVM2Item { } } if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueABC, isType)) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, "this", null, false, n.openedNamespaces, abcIndex); + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, false, "this", null, false, n.openedNamespaces, abcIndex); nobj.setRegNumber(0); obj = nobj; } - PropertyAVM2Item p = new PropertyAVM2Item(obj, n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>()); + PropertyAVM2Item p = new PropertyAVM2Item(obj, n.isAttribute(), n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>()); p.setAssignedValue(n.getAssignedValue()); callable = p; } @@ -143,7 +143,7 @@ public class CallAVM2Item extends AVM2Item { } if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, new ArrayList<>(), abcIndex); + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, false, "this", null, false, new ArrayList<>(), abcIndex); nobj.setRegNumber(0); obj = nobj; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java index 2e29a98c5..0e4965165 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/NameAVM2Item.java @@ -49,6 +49,8 @@ import java.util.Objects; */ public class NameAVM2Item extends AssignableAVM2Item { + private boolean attribute; + private String variableName; private boolean definition; @@ -77,7 +79,7 @@ public class NameAVM2Item extends AssignableAVM2Item { @Override public AssignableAVM2Item copy() { - NameAVM2Item c = new NameAVM2Item(type, line, variableName, assignedValue, definition, openedNamespaces, abcIndex); + NameAVM2Item c = new NameAVM2Item(type, line, attribute, variableName, assignedValue, definition, openedNamespaces, abcIndex); c.setNs(ns); c.regNumber = regNumber; c.unresolved = unresolved; @@ -85,6 +87,12 @@ public class NameAVM2Item extends AssignableAVM2Item { return c; } + public boolean isAttribute() { + return attribute; + } + + + public void setSlotScope(int slotScope) { this.slotScope = slotScope; } @@ -137,8 +145,9 @@ public class NameAVM2Item extends AssignableAVM2Item { return variableName; } - public NameAVM2Item(GraphTargetItem type, int line, String variableName, GraphTargetItem storeValue, boolean definition, List openedNamespaces, AbcIndexing abcIndex) { + public NameAVM2Item(GraphTargetItem type, int line, boolean attribute, String variableName, GraphTargetItem storeValue, boolean definition, List openedNamespaces, AbcIndexing abcIndex) { super(storeValue); + this.attribute = attribute; this.variableName = variableName; this.assignedValue = storeValue; this.definition = definition; 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 41f701289..72bab0b26 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 @@ -86,7 +86,7 @@ public class NamespaceItem { } if (kind == Namespace.KIND_NAMESPACE) { String custom = name.toRawString(); - PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abcIndex, openedNamespaces, new ArrayList<>()); + PropertyAVM2Item prop = new PropertyAVM2Item(null, false, custom, abcIndex, openedNamespaces, new ArrayList<>()); Reference value = new Reference<>(null); Reference outAbc = new Reference<>(null); Reference isType = new Reference<>(false); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java index f9d45ff80..e0ec46080 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/PropertyAVM2Item.java @@ -57,6 +57,8 @@ import java.util.logging.Logger; */ public class PropertyAVM2Item extends AssignableAVM2Item { + public boolean attribute; + public String propertyName; public GraphTargetItem object; @@ -71,11 +73,12 @@ public class PropertyAVM2Item extends AssignableAVM2Item { @Override public AssignableAVM2Item copy() { - PropertyAVM2Item p = new PropertyAVM2Item(object, propertyName, abcIndex, openedNamespaces, callStack); + PropertyAVM2Item p = new PropertyAVM2Item(object, attribute, propertyName, abcIndex, openedNamespaces, callStack); return p; } - public PropertyAVM2Item(GraphTargetItem object, String propertyName, AbcIndexing abcIndex, List openedNamespaces, List callStack) { + public PropertyAVM2Item(GraphTargetItem object, boolean attribute, String propertyName, AbcIndexing abcIndex, List openedNamespaces, List callStack) { + this.attribute = attribute; this.propertyName = propertyName; this.object = object; this.abcIndex = abcIndex; @@ -160,7 +163,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { int propIndex = 0; ABC abc = abcIndex.getSelectedAbc(); AVM2ConstantPool constants = abc.constants; - if (!propertyName.startsWith("@")) { + if (!attribute) { if (scopeStack.isEmpty()) { //Everything is multiname when with command if (objType == null) { @@ -417,17 +420,16 @@ public class PropertyAVM2Item extends AssignableAVM2Item { if (propIndex == 0 && !mustExist) { String pname = propertyName; - boolean attr = pname.startsWith("@"); - if (attr) { + if (attribute) { pname = pname.substring(1); } Multiname multiname; - if (attr && pname.isEmpty()) { + if (attribute && pname.isEmpty()) { multiname = Multiname.createMultinameL(true, constants.getNamespaceSetId(new int[]{constants.getNamespaceId(Namespace.KIND_PACKAGE_INTERNAL, localData.pkg, 0, true)}, true)); } else { int name_index = constants.getStringId("*".equals(pname) ? null : pname, true); //Note: name = * is for .@* attribute - multiname = Multiname.createMultiname(attr, name_index, allNsSet(abcIndex)); + multiname = Multiname.createMultiname(attribute, name_index, allNsSet(abcIndex)); } propIndex = constants.getMultinameId(multiname, true); propType = TypeItem.UNBOUNDED; @@ -557,7 +559,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item { } } if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, abcIndex, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) { - NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces, abcIndex); + NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, false, "this", null, false, openedNamespaces, abcIndex); nobj.setRegNumber(0); obj = nobj; } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java index 322f40f3f..2b72d7d60 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/UnresolvedAVM2Item.java @@ -295,13 +295,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { if (a instanceof NameAVM2Item) { NameAVM2Item n = (NameAVM2Item) a; if (n.isDefinition() && name.get(0).equals(n.getVariableName())) { - NameAVM2Item ret = new NameAVM2Item(n.type, n.line, name.get(0), null, false, openedNamespaces, abcIndex); + NameAVM2Item ret = new NameAVM2Item(n.type, n.line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex); ret.setSlotScope(n.getSlotScope()); ret.setSlotNumber(n.getSlotNumber()); ret.setRegNumber(n.getRegNumber()); resolved = ret; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -325,10 +325,10 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { t = paramTypes.get(ind); } //else rest parameter - GraphTargetItem ret = new NameAVM2Item(t, line, name.get(0), null, false, openedNamespaces, abcIndex); + GraphTargetItem ret = new NameAVM2Item(t, line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex); resolved = ret; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -341,7 +341,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { boolean isProperty = false; if (localData != null) { //resolve can be called without localData - PropertyAVM2Item resolvedx = new PropertyAVM2Item(null, name.get(0), abc, openedNamespaces, callStack); + PropertyAVM2Item resolvedx = new PropertyAVM2Item(null, name.isAttribute(0), name.get(0), abc, openedNamespaces, callStack); ((PropertyAVM2Item) resolvedx).scopeStack = scopeStack; ((PropertyAVM2Item) resolvedx).setAssignedValue(assignedValue); Reference objectType = new Reference<>(null); @@ -362,13 +362,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { DottedChain classChain = DottedChain.parseWithSuffix(currentClass); DottedChain pkg = classChain.getWithoutLast(); - TypeItem ti = new TypeItem(pkg.addWithSuffix(name.get(0))); + TypeItem ti = new TypeItem(pkg.addWithSuffix(name.get(0))); AbcIndexing.ClassIndex ci = abc.findClass(ti); if (ci != null) { resolved = ti; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -387,7 +387,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { TypeItem ret = new TypeItem(imp); resolved = ret; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -420,7 +420,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { TypeItem ret = new TypeItem(fname); resolved = ret; for (int j = i + 1; j < name.size(); j++) { - resolved = new PropertyAVM2Item(resolved, name.get(j), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(j), name.get(j), abc, openedNamespaces, new ArrayList<>()); if (j == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -449,7 +449,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { TypeItem ret = ti; resolved = ret; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -483,10 +483,10 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { } } - NameAVM2Item ret = new NameAVM2Item(ntype, line, name.get(0), null, false, openedNamespaces, abcIndex); + NameAVM2Item ret = new NameAVM2Item(ntype, line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex); resolved = ret; for (int i = 1; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>()); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>()); if (i == name.size() - 1) { ((PropertyAVM2Item) resolved).assignedValue = assignedValue; } @@ -509,7 +509,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item { resolved = null; GraphTargetItem ret = null; for (int i = 0; i < name.size(); i++) { - resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, callStack); + resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, callStack); if (ret == null) { ((PropertyAVM2Item) resolved).scopeStack = scopeStack; ret = resolved; 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 001d048b8..e66e4bb6c 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 @@ -418,7 +418,7 @@ public class Multiname { if (ns != null) { return ns.getName(constants).add(name, withSuffix ? getNamespaceSuffix() : ""); } - return new DottedChain(new String[]{name}, withSuffix ? getNamespaceSuffix() : ""); + return new DottedChain(new String[]{name}, new String[]{withSuffix ? getNamespaceSuffix() : ""}); } public Namespace getNamespace(AVM2ConstantPool constants) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java index a888d739a..f4bb3988c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScriptLexer.java @@ -1,16 +1,18 @@ +/* The following code was generated by JFlex 1.6.0 */ + /* - * Copyright (C) 2010-2022 JPEXS, All rights reserved. - * + * Copyright (C) 2010-2016 JPEXS, All rights reserved. + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. */ 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 e3bcb7cfd..04838939f 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 @@ -167,7 +167,7 @@ public class LinkReportExporter { sb.append(indent(3)).append("").append(newLineChar); //Automatic - tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, uses, new DottedChain(new String[]{"FAKE!PACKAGE"}, ""), new ArrayList<>()); + tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, uses, 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 0ee0177e7..f42eccdcf 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 @@ -144,12 +144,12 @@ public class SwfToSwcExporter { sb.append(" \n"); Set allDeps = new HashSet<>(); - allDeps.add(new DottedChain(new String[]{"AS3"}, "")); + allDeps.add(new DottedChain(new String[]{"AS3"}, new String[]{""})); sb.append(" \n"); if (!skipDependencies) { List dependencies = new ArrayList<>(); List uses = new ArrayList<>(); - pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, uses, new DottedChain(new String[]{"NO:PACKAGE"}, ""), new ArrayList<>()); + pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, uses, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>()); for (Dependency d : dependencies) { if ("*".equals(d.getId().getLast())) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java index eb86b8a15..d9c206711 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/DottedChain.java @@ -30,41 +30,41 @@ import java.util.List; */ public class DottedChain implements Serializable, Comparable { - public static final String NO_SUFFIX = ""; - public static final DottedChain EMPTY = new DottedChain(true); - public static final DottedChain TOPLEVEL = new DottedChain(new String[]{}, NO_SUFFIX); + public static final DottedChain TOPLEVEL = new DottedChain(new String[]{}); - public static final DottedChain BOOLEAN = new DottedChain(new String[]{"Boolean"}, NO_SUFFIX); + public static final DottedChain BOOLEAN = new DottedChain(new String[]{"Boolean"}); - public static final DottedChain STRING = new DottedChain(new String[]{"String"}, NO_SUFFIX); + public static final DottedChain STRING = new DottedChain(new String[]{"String"}); - public static final DottedChain ARRAY = new DottedChain(new String[]{"Array"}, NO_SUFFIX); + public static final DottedChain ARRAY = new DottedChain(new String[]{"Array"}); - public static final DottedChain NUMBER = new DottedChain(new String[]{"Number"}, NO_SUFFIX); + public static final DottedChain NUMBER = new DottedChain(new String[]{"Number"}); - public static final DottedChain OBJECT = new DottedChain(new String[]{"Object"}, NO_SUFFIX); + public static final DottedChain OBJECT = new DottedChain(new String[]{"Object"}); - public static final DottedChain INT = new DottedChain(new String[]{"int"}, NO_SUFFIX); + public static final DottedChain INT = new DottedChain(new String[]{"int"}); - public static final DottedChain UINT = new DottedChain(new String[]{"uint"}, NO_SUFFIX); + public static final DottedChain UINT = new DottedChain(new String[]{"uint"}); - public static final DottedChain UNDEFINED = new DottedChain(new String[]{"Undefined"}, NO_SUFFIX); + public static final DottedChain UNDEFINED = new DottedChain(new String[]{"Undefined"}); - public static final DottedChain XML = new DottedChain(new String[]{"XML"}, NO_SUFFIX); + public static final DottedChain XML = new DottedChain(new String[]{"XML"}); - public static final DottedChain NULL = new DottedChain(new String[]{"null"}, NO_SUFFIX); + public static final DottedChain NULL = new DottedChain(new String[]{"null"}); - public static final DottedChain FUNCTION = new DottedChain(new String[]{"Function"}, NO_SUFFIX); + public static final DottedChain FUNCTION = new DottedChain(new String[]{"Function"}); - public static final DottedChain VOID = new DottedChain(new String[]{"void"}, NO_SUFFIX); + public static final DottedChain VOID = new DottedChain(new String[]{"void"}); - public static final DottedChain NAMESPACE = new DottedChain(new String[]{"Namespace"}, NO_SUFFIX); + public static final DottedChain NAMESPACE = new DottedChain(new String[]{"Namespace"}); - public static final DottedChain ALL = new DottedChain(new String[]{"*"}, NO_SUFFIX); + public static final DottedChain ALL = new DottedChain(new String[]{"*"}); private final String[] parts; + + private final boolean[] attributes; private final int length; @@ -72,25 +72,42 @@ public class DottedChain implements Serializable, Comparable { private boolean isNull = false; - private String namespaceSuffix = ""; + private String[] namespaceSuffixes; - public String getNamespaceSuffix() { - return namespaceSuffix; + public String getNamespaceSuffix(int index) { + return namespaceSuffixes[index]; } + public String getLastNamespaceSuffix() { + if (length == 0) { + return ""; + } + return namespaceSuffixes[length - 1]; + } + + public static final DottedChain parseWithSuffix(String name) { if (name == null) { return DottedChain.EMPTY; } else if (name.isEmpty()) { return DottedChain.TOPLEVEL; } else { - String nameNoSuffix = name; - String namespaceSuffix = ""; - if (name.matches(".*#[0-9]+$")) { - nameNoSuffix = name.substring(0, name.lastIndexOf("#")); - namespaceSuffix = name.substring(name.lastIndexOf("#")); + String parts[] = name.split("\\."); + String nsSuffixes[] = new String[parts.length]; + int i = 0; + for (String part : parts) { + String nameNoSuffix = part; + String namespaceSuffix = ""; + if (part.matches(".*#[0-9]+$")) { + nameNoSuffix = part.substring(0, part.lastIndexOf("#")); + namespaceSuffix = part.substring(part.lastIndexOf("#")); + } + parts[i] = nameNoSuffix; + nsSuffixes[i] = namespaceSuffix; + i++; } - return new DottedChain(nameNoSuffix.split("\\."), namespaceSuffix); + + return new DottedChain(parts, nsSuffixes); } } @@ -99,37 +116,58 @@ public class DottedChain implements Serializable, Comparable { this.parts = new String[0]; this.length = 0; this.hash = 0; + this.attributes = new boolean[0]; + this.namespaceSuffixes = new String[0]; } public DottedChain(DottedChain src) { - this(src.parts, src.namespaceSuffix); + this(src.parts, src.namespaceSuffixes); this.isNull = src.isNull; } + public DottedChain(String[] parts) { + this(Arrays.asList(parts)); + } + public DottedChain(List parts) { length = parts.size(); this.parts = parts.toArray(new String[length]); + attributes = new boolean[length]; hash = calcHash(); + this.namespaceSuffixes = new String[length]; + for(int i = 0; i < length; i++) { + namespaceSuffixes[i] = ""; + } } /*public DottedChain(String onePart, String namespaceSuffix) { this(new String[]{onePart}, namespaceSuffix); }*/ - public DottedChain(String[] parts, String namespaceSuffix) { + public DottedChain(String[] parts, String[] namespaceSuffixes) { + this(new boolean[parts.length], parts, namespaceSuffixes); + } + + public DottedChain(boolean attributes[], String[] parts, String[] namespaceSuffixes) { if (parts.length == 1 && parts[0].isEmpty()) { length = 0; - this.parts = new String[0]; + this.parts = new String[0]; } else { length = parts.length; - this.parts = parts; + this.parts = parts; } + this.attributes = attributes; hash = calcHash(); - this.namespaceSuffix = namespaceSuffix; + this.namespaceSuffixes = namespaceSuffixes; } private DottedChain(String[] parts, int length) { this.length = length; this.parts = parts; + attributes = new boolean[length]; + this.namespaceSuffixes = new String[length]; + for(int i = 0; i < length; i++) { + namespaceSuffixes[i] = ""; + } hash = calcHash(); } @@ -152,6 +190,13 @@ public class DottedChain implements Serializable, Comparable { return parts[index]; } + + public boolean isAttribute(int index) { + if (index >= length) { + throw new ArrayIndexOutOfBoundsException(); + } + return attributes[index]; + } public DottedChain subChain(int count) { if (count > length) { @@ -171,6 +216,17 @@ public class DottedChain implements Serializable, Comparable { return parts[length - 1]; } } + + public boolean isLastAttribute() { + if (isNull) { + return false; + } + if (length == 0) { + return false; + } else { + return attributes[length - 1]; + } + } public DottedChain getWithoutLast() { if (isNull) { @@ -194,16 +250,25 @@ public class DottedChain implements Serializable, Comparable { } public DottedChain add(String name, String namespaceSuffix) { + return add(false, name, namespaceSuffix); + } + public DottedChain add(boolean attribute, String name, String namespaceSuffix) { if (name == null) { return new DottedChain(this); } String[] nparts = new String[length + 1]; + boolean[] nattributes = new boolean[length + 1]; + String[] nnamespaceSuffixes = new String[length + 1]; if (length > 0) { System.arraycopy(parts, 0, nparts, 0, length); + System.arraycopy(attributes, 0, nattributes, 0, length); + System.arraycopy(namespaceSuffixes, 0, nnamespaceSuffixes, 0, length); } - + + nattributes[nattributes.length - 1] = attribute; nparts[nparts.length - 1] = name; - return new DottedChain(nparts, namespaceSuffix); + nnamespaceSuffixes[nparts.length - 1] = namespaceSuffix; + return new DottedChain(nparts, nnamespaceSuffixes); } protected String toString(boolean as3, boolean raw, boolean withSuffix) { @@ -223,10 +288,11 @@ public class DottedChain implements Serializable, Comparable { String part = parts[i]; boolean lastStar = i == length - 1 && "*".equals(part); ret.append((raw || lastStar) ? part : IdentifiersDeobfuscation.printIdentifier(as3, part)); + if (withSuffix) { + ret.append(namespaceSuffixes[i]); + } } - if (withSuffix) { - ret.append(namespaceSuffix); - } + return ret.toString(); } @@ -305,6 +371,12 @@ public class DottedChain implements Serializable, Comparable { if (!s1.equals(s2)) { return false; } + if (attributes[i] != other.attributes[i]) { + return false; + } + if (!namespaceSuffixes[i].equals(other.namespaceSuffixes[i])) { + return false; + } } return true; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java index 78819aa8c..8b6d44833 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -43,7 +43,7 @@ public class TypeItem extends GraphTargetItem { public final DottedChain fullTypeName; public TypeItem(String s) { - this(s == null ? new DottedChain(new String[]{}, "") : DottedChain.parseWithSuffix(s)); + this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s)); } public TypeItem(DottedChain fullTypeName) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java index d29b2fd78..ddcec8478 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3DecompileTestBase.java @@ -93,7 +93,7 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas abc = scriptPack.abc; scriptIndex = scriptPack.scriptIndex; - clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); + clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className})); assertTrue(clsIndex > -1); assertTrue(scriptIndex > -1); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java index 8acfa04bc..bc25b00eb 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3OptinalParametersTest.java @@ -52,7 +52,7 @@ public class ActionScript3OptinalParametersTest extends ActionScript3DecompileTe if (t instanceof DoABC2Tag) { tag = (DoABC2Tag) t; abc = tag.getABC(); - clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className}, "")); + clsIndex = abc.findClassByName(new DottedChain(new String[]{"tests", className})); if (clsIndex > -1) { break; } diff --git a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java index 3a51a1474..31cdc34be 100644 --- a/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java +++ b/src/com/jpexs/decompiler/flash/gui/tagtree/TagTreeContextMenu.java @@ -1613,7 +1613,7 @@ public class TagTreeContextMenu extends JPopupMenu { try { ActionScript3Parser parser = new ActionScript3Parser(doAbc.getABC(), abcs); - DottedChain dc = new DottedChain(pkgParts, ""); + DottedChain dc = new DottedChain(pkgParts); String script = "package " + dc.toPrintableString(true) + " {" + "public class " + IdentifiersDeobfuscation.printIdentifier(true, classSimpleName) + " {" + " }" @@ -1937,7 +1937,7 @@ public class TagTreeContextMenu extends JPopupMenu { ActionScript2Parser parser = new ActionScript2Parser(swf, doInit); String[] parts = className.contains(".") ? className.split("\\.") : new String[]{className}; - DottedChain dc = new DottedChain(parts, ""); + DottedChain dc = new DottedChain(parts); try { List actions = parser.actionsFromString("class " + dc.toPrintableString(false) + "{}", swf.getCharset());