diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java index 4e11ddc50..3f71ebe9c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2ConstantPool.java @@ -311,6 +311,30 @@ public class AVM2ConstantPool implements Cloneable { return null; } + /** + * Converts kind MULTINAME with one namespace to QNAME with that namespace + * (must exist in the abc). Ignores others. + * + * @param cpool + * @param index MULTINAME index + * @return + */ + public int convertToQname(AVM2ConstantPool cpool, int index) { + Multiname mx = cpool.getMultiname(index); + if (mx.isMULTINAMEwithOneNs(cpool)) { + Multiname mx2 = new Multiname(); + mx2.kind = Multiname.QNAME; + mx2.name_index = mx.name_index; + mx2.namespace_index = mx.getSingleNamespaceIndex(cpool); + //and same QNAME exists within this ABC + int newMultinameIndex = cpool.getMultinameId(mx2, false); + if (newMultinameIndex > 0) { + index = newMultinameIndex; //use that QNAME + } + } + return index; + } + public Multiname getMultiname(int index) { try { return constant_multiname.get(index); @@ -514,6 +538,23 @@ public class AVM2ConstantPool implements Cloneable { return id; } + /** + * Finds multiname index based on multiname in other constant pool + * + * @param val + * @param origConst + * @return + */ + public int getMultinameId(Multiname val, AVM2ConstantPool origConst) { + + for (int i = 1; i < getMultinameCount(); i++) { + if (getMultiname(i).qnameEquals(this, val, origConst)) { + return i; + } + } + return -1; + } + public int getStringId(String val, boolean add) { if (val == null) { return 0; 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 31099ce36..4a637b1a5 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 @@ -106,7 +106,7 @@ public class InstanceInfo { writer.hilightSpecial(abc.constants.getMultiname(name_index).getName(abc.constants, null/* No full names here*/, false), HighlightSpecialType.CLASS_NAME); if (super_index > 0) { - String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toPrintableString(true); + String typeName = abc.constants.getMultiname(super_index).getNameWithNamespace(abc.constants).toRawString(); String parentName = abc.constants.getMultiname(super_index).getName(abc.constants, fullyQualifiedNames, false); if (!parentName.equals("Object")) { writer.appendNoHilight(" extends "); @@ -123,7 +123,7 @@ public class InstanceInfo { if (i > 0) { writer.append(", "); } - String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toPrintableString(true); + String typeName = abc.constants.getMultiname(interfaces[i]).getNameWithNamespace(abc.constants).toRawString(); writer.hilightSpecial(abc.constants.getMultiname(interfaces[i]).getName(abc.constants, fullyQualifiedNames, false), HighlightSpecialType.TYPE_NAME, typeName); } } 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 a29b864d6..b1f4c7efc 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 @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.Helper; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -418,4 +419,72 @@ public class Multiname { } return true; } + + /** + * Is this MULTINAME kind with only one namespace. Hint: it is sometimes + * used for interfaces + * + * @param pool + * @return + */ + public boolean isMULTINAMEwithOneNs(AVM2ConstantPool pool) { + return kind == MULTINAME && pool.getNamespaceSet(namespace_set_index).namespaces.length == 1; + } + + /** + * Gets single namespace index. It can be the namespace index of QNAME or + * namespace index in namespace set of MULTINAME, if it has only one + * namespace in the set. + * + * @param pool + * @return + */ + public int getSingleNamespaceIndex(AVM2ConstantPool pool) { + if (isMULTINAMEwithOneNs(pool)) { + return pool.getNamespaceSet(namespace_set_index).namespaces[0]; + } + return namespace_index; + } + + /** + * Gets single namespace. It can be the namespace of QNAME or namespace in + * namespace set of MULTINAME, if it has only one namespace in the set. + * + * @param pool + * @return + */ + public Namespace getSingleNamespace(AVM2ConstantPool pool) { + int index = getSingleNamespaceIndex(pool); + if (index < 0) { + return null; + } + return pool.getNamespace(index); + } + + private boolean isEfectivelyQname(AVM2ConstantPool thisCpool) { + return kind == QNAME || kind == QNAMEA || isMULTINAMEwithOneNs(thisCpool); + } + + public boolean qnameEquals(AVM2ConstantPool thisCpool, Multiname other, AVM2ConstantPool otherCpool) { + if (!isEfectivelyQname(thisCpool) || !other.isEfectivelyQname(otherCpool)) { + return false; + } + Namespace otherNs = other.getSingleNamespace(otherCpool); + Namespace thisNs = getSingleNamespace(thisCpool); + if (otherNs.kind != thisNs.kind) { + return false; + } + if (otherNs.kind == Namespace.KIND_PRIVATE) { + return false; + } + if (!Objects.equals(otherNs.getName(otherCpool).toRawString(), thisNs.getName(thisCpool).toRawString())) { + return false; + } + + if (!Objects.equals(other.getName(otherCpool, new ArrayList<>(), true), getName(thisCpool, new ArrayList<>(), true))) { + 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 fbe84c125..ed6a06085 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TypeItem.java @@ -79,9 +79,9 @@ public class TypeItem extends GraphTargetItem { boolean as3 = localData.constantsAvm2 != null; if (localData.fullyQualifiedNames.contains(new DottedChain(fullTypeName.getLast()))) { - writer.hilightSpecial(fullTypeName.toPrintableString(as3), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString(as3)); + writer.hilightSpecial(fullTypeName.toPrintableString(as3), HighlightSpecialType.TYPE_NAME, fullTypeName.toRawString()); } else { - writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(as3, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toPrintableString(as3)); + writer.hilightSpecial(IdentifiersDeobfuscation.printIdentifier(as3, fullTypeName.getLast()), HighlightSpecialType.TYPE_NAME, fullTypeName.toRawString()); } return writer; diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index fe4a1e1e9..b4ae86549 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -1037,7 +1037,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se updateClassesList(); reload(true); ABCPanel abcPanel = getABCPanel(); - abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toString()); + abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.decompiledTextArea.getScriptLeaf().getClassPath().toRawString()); } } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 242422bf6..e2fce8c2b 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -73,6 +73,7 @@ import com.jpexs.decompiler.flash.tags.ABCContainerTag; import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.treeitems.TreeItem; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import de.hameister.treetable.MyTreeTable; @@ -97,6 +98,7 @@ import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Objects; @@ -881,7 +883,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener usages = abc.findMultinameDefinition(multinameIndex); Multiname m = abc.constants.getMultiname(multinameIndex); + //search other ABC tags if this is not private multiname - if (m.namespace_index > 0 && abc.constants.getNamespace(m.namespace_index).kind != Namespace.KIND_PRIVATE) { + if (m.getSingleNamespaceIndex(abc.constants) > 0 && abc.constants.getNamespace(m.getSingleNamespaceIndex(abc.constants)).kind != Namespace.KIND_PRIVATE) { for (ABCContainerTag at : getAbcList()) { ABC a = at.getABC(); if (a == abc) { continue; } - int mid = a.constants.getMultinameId(m, false); + + int mid = a.constants.getMultinameId(m, abc.constants); if (mid > 0) { usages.addAll(a.findMultinameDefinition(mid)); } @@ -943,13 +947,13 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener 0 && abc.constants.getNamespace(m.namespace_index).kind != Namespace.KIND_PRIVATE) { + if (m.getSingleNamespaceIndex(abc.constants) > 0 && m.getSingleNamespace(abc.constants).kind != Namespace.KIND_PRIVATE) { for (ABCContainerTag at : getAbcList()) { ABC a = at.getABC(); if (a == abc) { continue; } - int mid = a.constants.getMultinameId(m, false); + int mid = a.constants.getMultinameId(m, abc.constants); if (mid > 0) { usages.addAll(a.findMultinameDefinition(mid)); } @@ -1075,7 +1079,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener packs = abc.script_info.get(oldIndex).getPacks(abc, oldIndex, null, pack.allABCs); if (!packs.isEmpty()) { diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 205dc9be3..91184b9b8 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -401,7 +401,16 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL return getMultinameAtPos(pos, false); } - public int getMultinameAtPos(int pos, boolean codeOnly) { + private int getMultinameAtPos(int pos, boolean codeOnly) { + int multinameIndex = _getMultinameAtPos(pos, codeOnly); + if (multinameIndex > -1) { + ABC abc = getABC(); + multinameIndex = abc.constants.convertToQname(abc.constants, multinameIndex); + } + return multinameIndex; + } + + public int _getMultinameAtPos(int pos, boolean codeOnly) { Highlighting tm = Highlighting.searchPos(methodHighlights, pos); Trait currentTrait = null; int currentMethod = -1; @@ -472,7 +481,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL for (int i = 1; i < abc.constants.getMultinameCount(); i++) { Multiname m = abc.constants.getMultiname(i); if (m != null) { - if (typeName.equals(m.getNameWithNamespace(abc.constants).toString())) { + if (typeName.equals(m.getNameWithNamespace(abc.constants).toRawString())) { return i; } } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java index abfdc3f38..5114a4f57 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/UsageFrame.java @@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.gui.abc; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.types.Multiname; import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.usages.ClassNameMultinameUsage; import com.jpexs.decompiler.flash.abc.usages.InsideClassMultinameUsage; import com.jpexs.decompiler.flash.abc.usages.MethodMultinameUsage; import com.jpexs.decompiler.flash.abc.usages.MultinameUsage; @@ -133,7 +134,7 @@ public class UsageFrame extends AppDialog implements MouseListener { settrait.run(); } else { abcPanel.decompiledTextArea.addScriptListener(settrait); - abcPanel.hilightScript(abcPanel.getSwf(), abcPanel.abc.instance_info.get(icu.classIndex).getName(abcPanel.abc.constants).getNameWithNamespace(abcPanel.abc.constants).toPrintableString(true)); + abcPanel.hilightScript(abcPanel.getSwf(), icu.abc.instance_info.get(icu.classIndex).getName(icu.abc.constants).getNameWithNamespace(icu.abc.constants).toRawString()); } } }