From b280104d2f926ab74772cef2bf1602663cefa312 Mon Sep 17 00:00:00 2001
From: Thog
Date: Tue, 16 May 2017 00:24:29 +0200
Subject: Remove the converter + some reorganization
---
.../java/cuchaz/enigma/gui/ClassMatchingGui.java | 536 ---------------------
.../java/cuchaz/enigma/gui/MemberMatchingGui.java | 435 -----------------
2 files changed, 971 deletions(-)
delete mode 100644 src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
delete mode 100644 src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
(limited to 'src/main/java/cuchaz/enigma/gui')
diff --git a/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java b/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
deleted file mode 100644
index 833a534..0000000
--- a/src/main/java/cuchaz/enigma/gui/ClassMatchingGui.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Jeff Martin.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the GNU Lesser General Public
- * License v3.0 which accompanies this distribution, and is available at
- * http://www.gnu.org/licenses/lgpl.html
- *
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.gui;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import cuchaz.enigma.Constants;
-import cuchaz.enigma.Deobfuscator;
-import cuchaz.enigma.convert.*;
-import cuchaz.enigma.gui.node.ClassSelectorClassNode;
-import cuchaz.enigma.gui.node.ClassSelectorPackageNode;
-import cuchaz.enigma.mapping.ClassEntry;
-import cuchaz.enigma.mapping.Mappings;
-import cuchaz.enigma.mapping.MappingsChecker;
-import cuchaz.enigma.throwables.MappingConflict;
-import de.sciss.syntaxpane.DefaultSyntaxKit;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionListener;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-public class ClassMatchingGui {
-
- // controls
- private JFrame frame;
- private ClassSelector sourceClasses;
- private ClassSelector destClasses;
- private CodeReader sourceReader;
- private CodeReader destReader;
- private JLabel sourceClassLabel;
- private JLabel destClassLabel;
- private JButton matchButton;
- private Map sourceTypeButtons;
- private JCheckBox advanceCheck;
- private JCheckBox top10Matches;
- private ClassMatches classMatches;
- private Deobfuscator sourceDeobfuscator;
- private Deobfuscator destDeobfuscator;
- private ClassEntry sourceClass;
- private ClassEntry destClass;
- private SourceType sourceType;
- private SaveListener saveListener;
-
- public ClassMatchingGui(ClassMatches matches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
-
- classMatches = matches;
- this.sourceDeobfuscator = sourceDeobfuscator;
- this.destDeobfuscator = destDeobfuscator;
-
- // init frame
- frame = new JFrame(Constants.NAME + " - Class Matcher");
- final Container pane = frame.getContentPane();
- pane.setLayout(new BorderLayout());
-
- // init source side
- JPanel sourcePanel = new JPanel();
- sourcePanel.setLayout(new BoxLayout(sourcePanel, BoxLayout.PAGE_AXIS));
- sourcePanel.setPreferredSize(new Dimension(200, 0));
- pane.add(sourcePanel, BorderLayout.WEST);
- sourcePanel.add(new JLabel("Source Classes"));
-
- // init source type radios
- JPanel sourceTypePanel = new JPanel();
- sourcePanel.add(sourceTypePanel);
- sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS));
- ActionListener sourceTypeListener = event -> setSourceType(SourceType.valueOf(event.getActionCommand()));
- ButtonGroup sourceTypeButtons = new ButtonGroup();
- this.sourceTypeButtons = Maps.newHashMap();
- for (SourceType sourceType : SourceType.values()) {
- JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons);
- this.sourceTypeButtons.put(sourceType, button);
- sourceTypePanel.add(button);
- }
-
- sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
- sourceClasses.setSelectionListener(this::setSourceClass);
- JScrollPane sourceScroller = new JScrollPane(sourceClasses);
- sourcePanel.add(sourceScroller);
-
- // init dest side
- JPanel destPanel = new JPanel();
- destPanel.setLayout(new BoxLayout(destPanel, BoxLayout.PAGE_AXIS));
- destPanel.setPreferredSize(new Dimension(200, 0));
- pane.add(destPanel, BorderLayout.WEST);
- destPanel.add(new JLabel("Destination Classes"));
-
- top10Matches = new JCheckBox("Show only top 10 matches");
- destPanel.add(top10Matches);
- top10Matches.addActionListener(event -> toggleTop10Matches());
-
- destClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
- destClasses.setSelectionListener(this::setDestClass);
- JScrollPane destScroller = new JScrollPane(destClasses);
- destPanel.add(destScroller);
-
- JButton autoMatchButton = new JButton("AutoMatch");
- autoMatchButton.addActionListener(event -> autoMatch());
- destPanel.add(autoMatchButton);
-
- // init source panels
- DefaultSyntaxKit.initKit();
- sourceReader = new CodeReader();
- destReader = new CodeReader();
-
- // init all the splits
- JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, sourcePanel, new JScrollPane(
- sourceReader));
- splitLeft.setResizeWeight(0); // let the right side take all the slack
- JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(destReader), destPanel);
- splitRight.setResizeWeight(1); // let the left side take all the slack
- JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, splitLeft, splitRight);
- splitCenter.setResizeWeight(0.5); // resize 50:50
- pane.add(splitCenter, BorderLayout.CENTER);
- splitCenter.resetToPreferredSizes();
-
- // init bottom panel
- JPanel bottomPanel = new JPanel();
- bottomPanel.setLayout(new FlowLayout());
-
- sourceClassLabel = new JLabel();
- sourceClassLabel.setHorizontalAlignment(SwingConstants.RIGHT);
- destClassLabel = new JLabel();
- destClassLabel.setHorizontalAlignment(SwingConstants.LEFT);
-
- matchButton = new JButton();
-
- advanceCheck = new JCheckBox("Advance to next likely match");
- advanceCheck.addActionListener(event -> {
- if (advanceCheck.isSelected()) {
- advance();
- }
- });
-
- bottomPanel.add(sourceClassLabel);
- bottomPanel.add(matchButton);
- bottomPanel.add(destClassLabel);
- bottomPanel.add(advanceCheck);
- pane.add(bottomPanel, BorderLayout.SOUTH);
-
- // show the frame
- pane.doLayout();
- frame.setSize(1024, 576);
- frame.setMinimumSize(new Dimension(640, 480));
- frame.setVisible(true);
- frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-
- // init state
- updateDestMappings();
- setSourceType(SourceType.getDefault());
- updateMatchButton();
- saveListener = null;
- }
-
- public void setSaveListener(SaveListener val) {
- saveListener = val;
- }
-
- private void updateDestMappings() {
- try {
- Mappings newMappings = MappingsConverter.newMappings(classMatches,
- sourceDeobfuscator.getMappings(), sourceDeobfuscator, destDeobfuscator
- );
-
- // look for dropped mappings
- MappingsChecker checker = new MappingsChecker(destDeobfuscator.getJarIndex());
- checker.dropBrokenMappings(newMappings);
-
- // count them
- int numDroppedFields = checker.getDroppedFieldMappings().size();
- int numDroppedMethods = checker.getDroppedMethodMappings().size();
- System.out.println(String.format(
- "%d mappings from matched classes don't match the dest jar:\n\t%5d fields\n\t%5d methods",
- numDroppedFields + numDroppedMethods,
- numDroppedFields,
- numDroppedMethods
- ));
-
- destDeobfuscator.setMappings(newMappings);
- } catch (MappingConflict ex) {
- System.out.println(ex.getMessage());
- ex.printStackTrace();
- }
- }
-
- protected void setSourceType(SourceType val) {
-
- // show the source classes
- sourceType = val;
- sourceClasses.setClasses(deobfuscateClasses(sourceType.getSourceClasses(classMatches), sourceDeobfuscator));
-
- // update counts
- for (SourceType sourceType : SourceType.values()) {
- sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)",
- sourceType.name(),
- sourceType.getSourceClasses(classMatches).size()
- ));
- }
- }
-
- private Collection deobfuscateClasses(Collection in, Deobfuscator deobfuscator) {
- List out = Lists.newArrayList();
- for (ClassEntry entry : in) {
-
- ClassEntry deobf = deobfuscator.deobfuscateEntry(entry);
-
- // make sure we preserve any scores
- if (entry instanceof ScoredClassEntry) {
- deobf = new ScoredClassEntry(deobf, ((ScoredClassEntry) entry).getScore());
- }
-
- out.add(deobf);
- }
- return out;
- }
-
- protected void setSourceClass(ClassEntry classEntry) {
-
- Runnable onGetDestClasses = null;
- if (advanceCheck.isSelected()) {
- onGetDestClasses = this::pickBestDestClass;
- }
-
- setSourceClass(classEntry, onGetDestClasses);
- }
-
- protected void setSourceClass(ClassEntry classEntry, final Runnable onGetDestClasses) {
-
- // update the current source class
- sourceClass = classEntry;
- sourceClassLabel.setText(sourceClass != null ? sourceClass.getName() : "");
-
- if (sourceClass != null) {
-
- // show the dest class(es)
- ClassMatch match = classMatches.getMatchBySource(sourceDeobfuscator.obfuscateEntry(sourceClass));
- assert (match != null);
- if (match.destClasses.isEmpty()) {
-
- destClasses.setClasses(null);
-
- // run in a separate thread to keep ui responsive
- new Thread(() ->
- {
- destClasses.setClasses(deobfuscateClasses(getLikelyMatches(sourceClass), destDeobfuscator));
- destClasses.expandAll();
-
- if (onGetDestClasses != null) {
- onGetDestClasses.run();
- }
- }).start();
-
- } else {
-
- destClasses.setClasses(deobfuscateClasses(match.destClasses, destDeobfuscator));
- destClasses.expandAll();
-
- if (onGetDestClasses != null) {
- onGetDestClasses.run();
- }
- }
- }
-
- setDestClass(null);
- sourceReader.decompileClass(
- sourceClass, sourceDeobfuscator, () -> sourceReader.navigateToClassDeclaration(sourceClass));
-
- updateMatchButton();
- }
-
- private Collection getLikelyMatches(ClassEntry sourceClass) {
-
- ClassEntry obfSourceClass = sourceDeobfuscator.obfuscateEntry(sourceClass);
-
- // set up identifiers
- ClassNamer namer = new ClassNamer(classMatches.getUniqueMatches());
- ClassIdentifier sourceIdentifier = new ClassIdentifier(
- sourceDeobfuscator.getJar(), sourceDeobfuscator.getJarIndex(),
- namer.getSourceNamer(), true
- );
- ClassIdentifier destIdentifier = new ClassIdentifier(
- destDeobfuscator.getJar(), destDeobfuscator.getJarIndex(),
- namer.getDestNamer(), true
- );
-
- try {
-
- // rank all the unmatched dest classes against the source class
- ClassIdentity sourceIdentity = sourceIdentifier.identify(obfSourceClass);
- List scoredDestClasses = Lists.newArrayList();
- for (ClassEntry unmatchedDestClass : classMatches.getUnmatchedDestClasses()) {
- ClassIdentity destIdentity = destIdentifier.identify(unmatchedDestClass);
- float score = 100.0f * (sourceIdentity.getMatchScore(destIdentity) + destIdentity.getMatchScore(sourceIdentity))
- / (sourceIdentity.getMaxMatchScore() + destIdentity.getMaxMatchScore());
- scoredDestClasses.add(new ScoredClassEntry(unmatchedDestClass, score));
- }
-
- if (top10Matches.isSelected() && scoredDestClasses.size() > 10) {
- scoredDestClasses.sort((a, b) ->
- {
- ScoredClassEntry sa = (ScoredClassEntry) a;
- ScoredClassEntry sb = (ScoredClassEntry) b;
- return -Float.compare(sa.getScore(), sb.getScore());
- });
- scoredDestClasses = scoredDestClasses.subList(0, 10);
- }
-
- return scoredDestClasses;
-
- } catch (ClassNotFoundException ex) {
- throw new Error("Unable to find class " + ex.getMessage());
- }
- }
-
- protected void setDestClass(ClassEntry classEntry) {
-
- // update the current source class
- destClass = classEntry;
- destClassLabel.setText(destClass != null ? destClass.getName() : "");
-
- destReader.decompileClass(destClass, destDeobfuscator, () -> destReader.navigateToClassDeclaration(destClass));
-
- updateMatchButton();
- }
-
- private void updateMatchButton() {
-
- ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
- ClassEntry obfDest = destDeobfuscator.obfuscateEntry(destClass);
-
- BiMap uniqueMatches = classMatches.getUniqueMatches();
- boolean twoSelected = sourceClass != null && destClass != null;
- boolean isMatched = uniqueMatches.containsKey(obfSource) && uniqueMatches.containsValue(obfDest);
- boolean canMatch = !uniqueMatches.containsKey(obfSource) && !uniqueMatches.containsValue(obfDest);
-
- GuiTricks.deactivateButton(matchButton);
- if (twoSelected) {
- if (isMatched) {
- GuiTricks.activateButton(matchButton, "Unmatch", event -> onUnmatchClick());
- } else if (canMatch) {
- GuiTricks.activateButton(matchButton, "Match", event -> onMatchClick());
- }
- }
- }
-
- private void onMatchClick() {
- // precondition: source and dest classes are set correctly
-
- ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
- ClassEntry obfDest = destDeobfuscator.obfuscateEntry(destClass);
-
- // remove the classes from their match
- classMatches.removeSource(obfSource);
- classMatches.removeDest(obfDest);
-
- // add them as matched classes
- classMatches.add(new ClassMatch(obfSource, obfDest));
-
- ClassEntry nextClass = null;
- if (advanceCheck.isSelected()) {
- nextClass = sourceClasses.getNextClass(sourceClass);
- }
-
- save();
- updateMatches();
-
- if (nextClass != null) {
- advance(nextClass);
- }
- }
-
- private void onUnmatchClick() {
- // precondition: source and dest classes are set to a unique match
-
- ClassEntry obfSource = sourceDeobfuscator.obfuscateEntry(sourceClass);
-
- // remove the source to break the match, then add the source back as unmatched
- classMatches.removeSource(obfSource);
- classMatches.add(new ClassMatch(obfSource, null));
-
- save();
- updateMatches();
- }
-
- private void updateMatches() {
- updateDestMappings();
- setDestClass(null);
- destClasses.setClasses(null);
- updateMatchButton();
-
- // remember where we were in the source tree
- String packageName = sourceClasses.getSelectedPackage();
-
- setSourceType(sourceType);
-
- sourceClasses.expandPackage(packageName);
- }
-
- private void save() {
- if (saveListener != null) {
- saveListener.save(classMatches);
- }
- }
-
- private void autoMatch() {
-
- System.out.println("Automatching...");
-
- // compute a new matching
- ClassMatching matching = MappingsConverter.computeMatching(
- sourceDeobfuscator.getJar(), sourceDeobfuscator.getJarIndex(),
- destDeobfuscator.getJar(), destDeobfuscator.getJarIndex(),
- classMatches.getUniqueMatches()
- );
- ClassMatches newMatches = new ClassMatches(matching.matches());
- System.out.println(String.format("Automatch found %d new matches",
- newMatches.getUniqueMatches().size() - classMatches.getUniqueMatches().size()
- ));
-
- // update the current matches
- classMatches = newMatches;
- save();
- updateMatches();
- }
-
- private void advance() {
- advance(null);
- }
-
- private void advance(ClassEntry sourceClass) {
-
- // make sure we have a source class
- if (sourceClass == null) {
- sourceClass = sourceClasses.getSelectedClass();
- if (sourceClass != null) {
- sourceClass = sourceClasses.getNextClass(sourceClass);
- } else {
- sourceClass = sourceClasses.getFirstClass();
- }
- }
-
- // set the source class
- setSourceClass(sourceClass, this::pickBestDestClass);
- sourceClasses.setSelectionClass(sourceClass);
- }
-
- private void pickBestDestClass() {
-
- // then, pick the best dest class
- ClassEntry firstClass = null;
- ScoredClassEntry bestDestClass = null;
- for (ClassSelectorPackageNode packageNode : destClasses.packageNodes()) {
- for (ClassSelectorClassNode classNode : destClasses.classNodes(packageNode)) {
- if (firstClass == null) {
- firstClass = classNode.getClassEntry();
- }
- if (classNode.getClassEntry() instanceof ScoredClassEntry) {
- ScoredClassEntry scoredClass = (ScoredClassEntry) classNode.getClassEntry();
- if (bestDestClass == null || bestDestClass.getScore() < scoredClass.getScore()) {
- bestDestClass = scoredClass;
- }
- }
- }
- }
-
- // pick the entry to show
- ClassEntry destClass = null;
- if (bestDestClass != null) {
- destClass = bestDestClass;
- } else if (firstClass != null) {
- destClass = firstClass;
- }
-
- setDestClass(destClass);
- destClasses.setSelectionClass(destClass);
- }
-
- private void toggleTop10Matches() {
- if (sourceClass != null) {
- destClasses.clearSelection();
- destClasses.setClasses(deobfuscateClasses(getLikelyMatches(sourceClass), destDeobfuscator));
- destClasses.expandAll();
- }
- }
-
- private enum SourceType {
- Matched {
- @Override
- public Collection getSourceClasses(ClassMatches matches) {
- return matches.getUniqueMatches().keySet();
- }
- },
- Unmatched {
- @Override
- public Collection getSourceClasses(ClassMatches matches) {
- return matches.getUnmatchedSourceClasses();
- }
- },
- Ambiguous {
- @Override
- public Collection getSourceClasses(ClassMatches matches) {
- return matches.getAmbiguouslyMatchedSourceClasses();
- }
- };
-
- public static SourceType getDefault() {
- return values()[0];
- }
-
- public JRadioButton newRadio(ActionListener listener, ButtonGroup group) {
- JRadioButton button = new JRadioButton(name(), this == getDefault());
- button.setActionCommand(name());
- button.addActionListener(listener);
- group.add(button);
- return button;
- }
-
- public abstract Collection getSourceClasses(ClassMatches matches);
- }
-
- public interface SaveListener {
- void save(ClassMatches matches);
- }
-}
diff --git a/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java b/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
deleted file mode 100644
index fe6a3b0..0000000
--- a/src/main/java/cuchaz/enigma/gui/MemberMatchingGui.java
+++ /dev/null
@@ -1,435 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2015 Jeff Martin.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the GNU Lesser General Public
- * License v3.0 which accompanies this distribution, and is available at
- * http://www.gnu.org/licenses/lgpl.html
- *
- * Contributors:
- * Jeff Martin - initial API and implementation
- ******************************************************************************/
-
-package cuchaz.enigma.gui;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import cuchaz.enigma.Constants;
-import cuchaz.enigma.Deobfuscator;
-import cuchaz.enigma.analysis.SourceIndex;
-import cuchaz.enigma.analysis.Token;
-import cuchaz.enigma.convert.ClassMatches;
-import cuchaz.enigma.convert.MemberMatches;
-import cuchaz.enigma.gui.highlight.DeobfuscatedHighlightPainter;
-import cuchaz.enigma.gui.highlight.ObfuscatedHighlightPainter;
-import cuchaz.enigma.mapping.ClassEntry;
-import cuchaz.enigma.mapping.Entry;
-import de.sciss.syntaxpane.DefaultSyntaxKit;
-
-import javax.swing.*;
-import javax.swing.text.Highlighter.HighlightPainter;
-import java.awt.*;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
-import java.awt.event.KeyEvent;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-public class MemberMatchingGui {
-
- // controls
- private JFrame frame;
- private Map sourceTypeButtons;
- private ClassSelector sourceClasses;
- private CodeReader sourceReader;
- private CodeReader destReader;
- private JButton matchButton;
- private JButton unmatchableButton;
- private JLabel sourceLabel;
- private JLabel destLabel;
- private HighlightPainter unmatchedHighlightPainter;
- private HighlightPainter matchedHighlightPainter;
- private ClassMatches classMatches;
- private MemberMatches memberMatches;
- private Deobfuscator sourceDeobfuscator;
- private Deobfuscator destDeobfuscator;
- private SaveListener saveListener;
- private SourceType sourceType;
- private ClassEntry obfSourceClass;
- private ClassEntry obfDestClass;
- private T obfSourceEntry;
- private T obfDestEntry;
-
- public MemberMatchingGui(ClassMatches classMatches, MemberMatches fieldMatches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
-
- this.classMatches = classMatches;
- memberMatches = fieldMatches;
- this.sourceDeobfuscator = sourceDeobfuscator;
- this.destDeobfuscator = destDeobfuscator;
-
- // init frame
- frame = new JFrame(Constants.NAME + " - Member Matcher");
- final Container pane = frame.getContentPane();
- pane.setLayout(new BorderLayout());
-
- // init classes side
- JPanel classesPanel = new JPanel();
- classesPanel.setLayout(new BoxLayout(classesPanel, BoxLayout.PAGE_AXIS));
- classesPanel.setPreferredSize(new Dimension(200, 0));
- pane.add(classesPanel, BorderLayout.WEST);
- classesPanel.add(new JLabel("Classes"));
-
- // init source type radios
- JPanel sourceTypePanel = new JPanel();
- classesPanel.add(sourceTypePanel);
- sourceTypePanel.setLayout(new BoxLayout(sourceTypePanel, BoxLayout.PAGE_AXIS));
- ActionListener sourceTypeListener = event -> setSourceType(SourceType.valueOf(event.getActionCommand()));
- ButtonGroup sourceTypeButtons = new ButtonGroup();
- this.sourceTypeButtons = Maps.newHashMap();
- for (SourceType sourceType : SourceType.values()) {
- JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons);
- this.sourceTypeButtons.put(sourceType, button);
- sourceTypePanel.add(button);
- }
-
- sourceClasses = new ClassSelector(null, ClassSelector.DEOBF_CLASS_COMPARATOR, false);
- sourceClasses.setSelectionListener(this::setSourceClass);
- JScrollPane sourceScroller = new JScrollPane(sourceClasses);
- classesPanel.add(sourceScroller);
-
- // init readers
- DefaultSyntaxKit.initKit();
- sourceReader = new CodeReader();
- sourceReader.setSelectionListener(reference ->
- {
- if (reference != null) {
- onSelectSource(reference.entry);
- } else {
- onSelectSource(null);
- }
- });
- destReader = new CodeReader();
- destReader.setSelectionListener(reference ->
- {
- if (reference != null) {
- onSelectDest(reference.entry);
- } else {
- onSelectDest(null);
- }
- });
-
- // add key bindings
- KeyAdapter keyListener = new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent event) {
- if (event.getKeyCode() == KeyEvent.VK_M)
- matchButton.doClick();
- }
- };
- sourceReader.addKeyListener(keyListener);
- destReader.addKeyListener(keyListener);
-
- // init all the splits
- JSplitPane splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(sourceReader), new JScrollPane(
- destReader));
- splitRight.setResizeWeight(0.5); // resize 50:50
- JSplitPane splitLeft = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, classesPanel, splitRight);
- splitLeft.setResizeWeight(0); // let the right side take all the slack
- pane.add(splitLeft, BorderLayout.CENTER);
- splitLeft.resetToPreferredSizes();
-
- // init bottom panel
- JPanel bottomPanel = new JPanel();
- bottomPanel.setLayout(new FlowLayout());
- pane.add(bottomPanel, BorderLayout.SOUTH);
-
- matchButton = new JButton();
- unmatchableButton = new JButton();
-
- sourceLabel = new JLabel();
- bottomPanel.add(sourceLabel);
- bottomPanel.add(matchButton);
- bottomPanel.add(unmatchableButton);
- destLabel = new JLabel();
- bottomPanel.add(destLabel);
-
- // show the frame
- pane.doLayout();
- frame.setSize(1024, 576);
- frame.setMinimumSize(new Dimension(640, 480));
- frame.setVisible(true);
- frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
-
- unmatchedHighlightPainter = new ObfuscatedHighlightPainter();
- matchedHighlightPainter = new DeobfuscatedHighlightPainter();
-
- // init state
- saveListener = null;
- obfSourceClass = null;
- obfDestClass = null;
- obfSourceEntry = null;
- obfDestEntry = null;
- setSourceType(SourceType.getDefault());
- updateButtons();
- }
-
- protected void setSourceType(SourceType val) {
- sourceType = val;
- updateSourceClasses();
- }
-
- public void setSaveListener(SaveListener val) {
- saveListener = val;
- }
-
- private void updateSourceClasses() {
-
- String selectedPackage = sourceClasses.getSelectedPackage();
-
- List deobfClassEntries = Lists.newArrayList();
- for (ClassEntry entry : sourceType.getObfSourceClasses(memberMatches)) {
- deobfClassEntries.add(sourceDeobfuscator.deobfuscateEntry(entry));
- }
- sourceClasses.setClasses(deobfClassEntries);
-
- if (selectedPackage != null) {
- sourceClasses.expandPackage(selectedPackage);
- }
-
- for (SourceType sourceType : SourceType.values()) {
- sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)",
- sourceType.name(), sourceType.getObfSourceClasses(memberMatches).size()
- ));
- }
- }
-
- protected void setSourceClass(ClassEntry sourceClass) {
-
- obfSourceClass = sourceDeobfuscator.obfuscateEntry(sourceClass);
- obfDestClass = classMatches.getUniqueMatches().get(obfSourceClass);
- if (obfDestClass == null) {
- throw new Error("No matching dest class for source class: " + obfSourceClass);
- }
-
- sourceReader.decompileClass(obfSourceClass, sourceDeobfuscator, false, this::updateSourceHighlights);
- destReader.decompileClass(obfDestClass, destDeobfuscator, false, this::updateDestHighlights);
- }
-
- protected void updateSourceHighlights() {
- highlightEntries(sourceReader, sourceDeobfuscator, memberMatches.matches().keySet(), memberMatches.getUnmatchedSourceEntries());
- }
-
- protected void updateDestHighlights() {
- highlightEntries(destReader, destDeobfuscator, memberMatches.matches().values(), memberMatches.getUnmatchedDestEntries());
- }
-
- private void highlightEntries(CodeReader reader, Deobfuscator deobfuscator, Collection obfMatchedEntries, Collection obfUnmatchedEntries) {
- reader.clearHighlights();
- // matched fields
- updateHighlighted(obfMatchedEntries, deobfuscator, reader, matchedHighlightPainter);
- // unmatched fields
- updateHighlighted(obfUnmatchedEntries, deobfuscator, reader, unmatchedHighlightPainter);
- }
-
- private void updateHighlighted(Collection entries, Deobfuscator deobfuscator, CodeReader reader, HighlightPainter painter) {
- SourceIndex index = reader.getSourceIndex();
- for (T obfT : entries) {
- T deobfT = deobfuscator.deobfuscateEntry(obfT);
- Token token = index.getDeclarationToken(deobfT);
- if (token != null) {
- reader.setHighlightedToken(token, painter);
- }
- }
- }
-
- private boolean isSelectionMatched() {
- return obfSourceEntry != null && obfDestEntry != null
- && memberMatches.isMatched(obfSourceEntry, obfDestEntry);
- }
-
- protected void onSelectSource(Entry source) {
-
- // start with no selection
- if (isSelectionMatched()) {
- setDest(null);
- }
- setSource(null);
-
- // then look for a valid source selection
- if (source != null) {
-
- // this looks really scary, but it's actually ok
- // Deobfuscator.obfuscateEntry can handle all implementations of Entry
- // and MemberMatches.hasSource() will only pass entries that actually match T
- @SuppressWarnings("unchecked")
- T sourceEntry = (T) source;
-
- T obfSourceEntry = sourceDeobfuscator.obfuscateEntry(sourceEntry);
- if (memberMatches.hasSource(obfSourceEntry)) {
- setSource(obfSourceEntry);
-
- // look for a matched dest too
- T obfDestEntry = memberMatches.matches().get(obfSourceEntry);
- if (obfDestEntry != null) {
- setDest(obfDestEntry);
- }
- }
- }
-
- updateButtons();
- }
-
- protected void onSelectDest(Entry dest) {
-
- // start with no selection
- if (isSelectionMatched()) {
- setSource(null);
- }
- setDest(null);
-
- // then look for a valid dest selection
- if (dest != null) {
-
- // this looks really scary, but it's actually ok
- // Deobfuscator.obfuscateEntry can handle all implementations of Entry
- // and MemberMatches.hasSource() will only pass entries that actually match T
- @SuppressWarnings("unchecked")
- T destEntry = (T) dest;
-
- T obfDestEntry = destDeobfuscator.obfuscateEntry(destEntry);
- if (memberMatches.hasDest(obfDestEntry)) {
- setDest(obfDestEntry);
-
- // look for a matched source too
- T obfSourceEntry = memberMatches.matches().inverse().get(obfDestEntry);
- if (obfSourceEntry != null) {
- setSource(obfSourceEntry);
- }
- }
- }
-
- updateButtons();
- }
-
- private void setSource(T obfEntry) {
- if (obfEntry == null) {
- obfSourceEntry = null;
- sourceLabel.setText("");
- } else {
- obfSourceEntry = obfEntry;
- sourceLabel.setText(getEntryLabel(obfEntry, sourceDeobfuscator));
- }
- }
-
- private void setDest(T obfEntry) {
- if (obfEntry == null) {
- obfDestEntry = null;
- destLabel.setText("");
- } else {
- obfDestEntry = obfEntry;
- destLabel.setText(getEntryLabel(obfEntry, destDeobfuscator));
- }
- }
-
- private String getEntryLabel(T obfEntry, Deobfuscator deobfuscator) {
- // show obfuscated and deobfuscated names, but no types/signatures
- T deobfEntry = deobfuscator.deobfuscateEntry(obfEntry);
- return String.format("%s (%s)", deobfEntry.getName(), obfEntry.getName());
- }
-
- private void updateButtons() {
-
- GuiTricks.deactivateButton(matchButton);
- GuiTricks.deactivateButton(unmatchableButton);
-
- if (obfSourceEntry != null && obfDestEntry != null) {
- if (memberMatches.isMatched(obfSourceEntry, obfDestEntry))
- GuiTricks.activateButton(matchButton, "Unmatch", event -> unmatch());
- else if (!memberMatches.isMatchedSourceEntry(obfSourceEntry) && !memberMatches.isMatchedDestEntry(
- obfDestEntry))
- GuiTricks.activateButton(matchButton, "Match", event -> match());
- } else if (obfSourceEntry != null)
- GuiTricks.activateButton(unmatchableButton, "Set Unmatchable", event -> unmatchable());
- }
-
- protected void match() {
-
- // update the field matches
- memberMatches.makeMatch(obfSourceEntry, obfDestEntry, sourceDeobfuscator, destDeobfuscator);
- save();
-
- // update the ui
- onSelectSource(null);
- onSelectDest(null);
- updateSourceHighlights();
- updateDestHighlights();
- updateSourceClasses();
- }
-
- protected void unmatch() {
-
- // update the field matches
- memberMatches.unmakeMatch(obfSourceEntry, obfDestEntry, sourceDeobfuscator, destDeobfuscator);
- save();
-
- // update the ui
- onSelectSource(null);
- onSelectDest(null);
- updateSourceHighlights();
- updateDestHighlights();
- updateSourceClasses();
- }
-
- protected void unmatchable() {
-
- // update the field matches
- memberMatches.makeSourceUnmatchable(obfSourceEntry, sourceDeobfuscator);
- save();
-
- // update the ui
- onSelectSource(null);
- onSelectDest(null);
- updateSourceHighlights();
- updateDestHighlights();
- updateSourceClasses();
- }
-
- private void save() {
- if (saveListener != null) {
- saveListener.save(memberMatches);
- }
- }
-
- private enum SourceType {
- Matched {
- @Override
- public Collection getObfSourceClasses(MemberMatches matches) {
- return matches.getSourceClassesWithoutUnmatchedEntries();
- }
- },
- Unmatched {
- @Override
- public Collection getObfSourceClasses(MemberMatches matches) {
- return matches.getSourceClassesWithUnmatchedEntries();
- }
- };
-
- public static SourceType getDefault() {
- return values()[0];
- }
-
- public JRadioButton newRadio(ActionListener listener, ButtonGroup group) {
- JRadioButton button = new JRadioButton(name(), this == getDefault());
- button.setActionCommand(name());
- button.addActionListener(listener);
- group.add(button);
- return button;
- }
-
- public abstract Collection getObfSourceClasses(MemberMatches matches);
- }
-
- public interface SaveListener {
- void save(MemberMatches matches);
- }
-}
--
cgit v1.2.3