private void gotoDeclaration(int pos) { Reference<Integer> abcIndex = new Reference<>(0); Reference<Integer> classIndex = new Reference<>(0); Reference<Integer> traitIndex = new Reference<>(0); Reference<Boolean> classTrait = new Reference<>(false); Reference<Integer> multinameIndexRef = new Reference<>(0); if (decompiledTextArea.getPropertyTypeAtPos( pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef)) { UsageFrame.gotoUsage( ABCPanel.this, new TraitMultinameUsage( getAbcList().get(abcIndex.getVal()).getABC(), multinameIndexRef.getVal(), classIndex.getVal(), traitIndex.getVal(), classTrait.getVal(), null, -1) {}); return; } int multinameIndex = decompiledTextArea.getMultinameAtPos(pos); if (multinameIndex > -1) { List<MultinameUsage> usages = abc.findMultinameDefinition(multinameIndex); Multiname m = abc.constants.constant_multiname.get(multinameIndex); // search other ABC tags if this is not private multiname if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { for (ABCContainerTag at : getAbcList()) { ABC a = at.getABC(); if (a == abc) { continue; } int mid = a.constants.getMultinameId(m, false); if (mid > 0) { usages.addAll(a.findMultinameDefinition(mid)); } } } // more than one? display list if (usages.size() > 1) { UsageFrame usageFrame = new UsageFrame(abc, multinameIndex, ABCPanel.this, true); usageFrame.setVisible(true); return; } else if (!usages.isEmpty()) { // one UsageFrame.gotoUsage(ABCPanel.this, usages.get(0)); return; } } int dpos = decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>("")); if (dpos > -1) { decompiledTextArea.setCaretPosition(dpos); } }
public GraphTextWriter getModifiers(ABC abc, boolean isStatic, GraphTextWriter writer) { if ((kindFlags & ATTR_Override) > 0) { writer.appendNoHilight("override "); } Multiname m = getName(abc); if (m != null) { String nsname = ""; for (ABCContainerTag abcTag : abc.getAbcTags()) { if (m.namespace_index == -1) { break; } DottedChain dc = abcTag .getABC() .nsValueToName( abc.constants.getNamespace(m.namespace_index).getName(abc.constants)); nsname = dc.getLast(); if (nsname == null) { break; } if (!nsname.isEmpty()) { break; } } Namespace ns = m.getNamespace(abc.constants); if (nsname != null) { String identifier = IdentifiersDeobfuscation.printIdentifier(true, nsname); if (identifier != null && !identifier.isEmpty()) { writer.appendNoHilight(identifier).appendNoHilight(" "); } } if (ns != null) { String nsPrefix = ns.getPrefix(abc); if (nsPrefix != null && !nsPrefix.isEmpty()) { writer.appendNoHilight(nsPrefix).appendNoHilight(" "); } } } if (isStatic) { if ((this instanceof TraitSlotConst) && ((TraitSlotConst) this).isNamespace()) { // static is automatic } else { writer.appendNoHilight("static "); } } if ((kindFlags & ATTR_Final) > 0) { if (!isStatic) { writer.appendNoHilight("final "); } } return writer; }
private boolean hasDeclaration(int pos) { SyntaxDocument sd = (SyntaxDocument) decompiledTextArea.getDocument(); Token t = sd.getTokenAt(pos); if (t == null || (t.type != TokenType.IDENTIFIER && t.type != TokenType.KEYWORD && t.type != TokenType.REGEX)) { return false; } Reference<Integer> abcIndex = new Reference<>(0); Reference<Integer> classIndex = new Reference<>(0); Reference<Integer> traitIndex = new Reference<>(0); Reference<Integer> multinameIndexRef = new Reference<>(0); Reference<Boolean> classTrait = new Reference<>(false); if (decompiledTextArea.getPropertyTypeAtPos( pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef)) { return true; } int multinameIndex = decompiledTextArea.getMultinameAtPos(pos); if (multinameIndex > -1) { if (multinameIndex == 0) { return false; } List<MultinameUsage> usages = abc.findMultinameDefinition(multinameIndex); Multiname m = abc.constants.constant_multiname.get(multinameIndex); // search other ABC tags if this is not private multiname if (m.namespace_index > 0 && abc.constants.constant_namespace.get(m.namespace_index).kind != Namespace.KIND_PRIVATE) { for (ABCContainerTag at : getAbcList()) { ABC a = at.getABC(); if (a == abc) { continue; } int mid = a.constants.getMultinameId(m, false); if (mid > 0) { usages.addAll(a.findMultinameDefinition(mid)); } } } // more than one? display list if (!usages.isEmpty()) { return true; } } return decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>("")) != -1; }
@Test(dataProvider = "provideFiles") public void testDirectEditing(String filePath) throws IOException, InterruptedException, AVM2ParseException, CompilationException { File playerSWC = Configuration.getPlayerSWC(); if (playerSWC == null) { throw new IOException( "Player SWC library not found, please place it to " + Configuration.getFlashLibPath()); } try { SWF swf = new SWF(new BufferedInputStream(new FileInputStream(filePath)), false); if (swf.isAS3()) { boolean dotest = false; List<ABC> allAbcs = new ArrayList<>(); for (ABCContainerTag ct : swf.getAbcList()) { allAbcs.add(ct.getABC()); } for (ABC abc : allAbcs) { for (int s = 0; s < abc.script_info.size(); s++) { String startAfter = null; HighlightedTextWriter htw = new HighlightedTextWriter(new CodeFormatting(), false); ScriptPack en = abc.script_info.get(s).getPacks(abc, s, null, allAbcs).get(0); String classPathString = en.getClassPath().toString(); if (startAfter == null || classPathString.equals(startAfter)) { dotest = true; } if (!dotest) { System.out.println("Skipped:" + classPathString); continue; } System.out.println("Recompiling:" + classPathString + "..."); en.toSource(htw, abc.script_info.get(s).traits.traits, ScriptExportMode.AS, false); String original = htw.toString(); com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScriptParser.compile( original, abc, allAbcs, false, en.getClassPath().className + ".as", abc.instance_info.size()); // remove last compiled script: abc.script_info.remove(abc.script_info.size() - 1); } } } else { Map<String, ASMSource> asms = swf.getASMs(false); for (ASMSource asm : asms.values()) { try { HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer); String as = writer.toString(); as = asm.removePrefixAndSuffix(as); ActionScriptParser par = new ActionScriptParser(swf.version); try { asm.setActions(par.actionsFromString(as)); } catch (ActionParseException | CompilationException ex) { fail("Unable to parse: " + as + "/" + asm.toString(), ex); } writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer); String as2 = writer.toString(); as2 = asm.removePrefixAndSuffix(as2); try { asm.setActions(par.actionsFromString(as2)); } catch (ActionParseException | CompilationException ex) { fail( "Unable to parse: " + asm.getSwf().getShortFileName() + "/" + asm.toString(), ex); } writer = new HighlightedTextWriter(new CodeFormatting(), false); Action.actionsToSource(asm, asm.getActions(), asm.toString() /*FIXME?*/, writer); String as3 = writer.toString(); as3 = asm.removePrefixAndSuffix(as3); if (!as3.equals(as2)) { fail( "ActionScript is different: " + asm.getSwf().getShortFileName() + "/" + asm.toString()); } } catch (InterruptedException | IOException | OutOfMemoryError | TranslateException | StackOverflowError ex) { } } } } catch (Exception ex) { fail("Exception during decompilation: " + filePath, ex); } }