summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/gui/MatchingGui.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/cuchaz/enigma/gui/MatchingGui.java')
-rw-r--r--src/cuchaz/enigma/gui/MatchingGui.java141
1 files changed, 102 insertions, 39 deletions
diff --git a/src/cuchaz/enigma/gui/MatchingGui.java b/src/cuchaz/enigma/gui/MatchingGui.java
index e2d517e..04dbd7a 100644
--- a/src/cuchaz/enigma/gui/MatchingGui.java
+++ b/src/cuchaz/enigma/gui/MatchingGui.java
@@ -11,10 +11,12 @@ import java.util.Arrays;
11import java.util.Collection; 11import java.util.Collection;
12import java.util.Collections; 12import java.util.Collections;
13import java.util.List; 13import java.util.List;
14import java.util.Map;
14 15
15import javax.swing.BoxLayout; 16import javax.swing.BoxLayout;
16import javax.swing.ButtonGroup; 17import javax.swing.ButtonGroup;
17import javax.swing.JButton; 18import javax.swing.JButton;
19import javax.swing.JCheckBox;
18import javax.swing.JEditorPane; 20import javax.swing.JEditorPane;
19import javax.swing.JFrame; 21import javax.swing.JFrame;
20import javax.swing.JLabel; 22import javax.swing.JLabel;
@@ -22,9 +24,12 @@ import javax.swing.JPanel;
22import javax.swing.JRadioButton; 24import javax.swing.JRadioButton;
23import javax.swing.JScrollPane; 25import javax.swing.JScrollPane;
24import javax.swing.JSplitPane; 26import javax.swing.JSplitPane;
27import javax.swing.SwingConstants;
25import javax.swing.WindowConstants; 28import javax.swing.WindowConstants;
29import javax.swing.tree.TreePath;
26 30
27import com.beust.jcommander.internal.Lists; 31import com.beust.jcommander.internal.Lists;
32import com.beust.jcommander.internal.Maps;
28import com.google.common.collect.ArrayListMultimap; 33import com.google.common.collect.ArrayListMultimap;
29import com.google.common.collect.BiMap; 34import com.google.common.collect.BiMap;
30import com.google.common.collect.Multimap; 35import com.google.common.collect.Multimap;
@@ -34,6 +39,7 @@ import cuchaz.enigma.Deobfuscator;
34import cuchaz.enigma.convert.ClassIdentifier; 39import cuchaz.enigma.convert.ClassIdentifier;
35import cuchaz.enigma.convert.ClassIdentity; 40import cuchaz.enigma.convert.ClassIdentity;
36import cuchaz.enigma.convert.ClassMatch; 41import cuchaz.enigma.convert.ClassMatch;
42import cuchaz.enigma.convert.ClassMatching;
37import cuchaz.enigma.convert.ClassNamer; 43import cuchaz.enigma.convert.ClassNamer;
38import cuchaz.enigma.convert.MappingsConverter; 44import cuchaz.enigma.convert.MappingsConverter;
39import cuchaz.enigma.convert.Matches; 45import cuchaz.enigma.convert.Matches;
@@ -95,6 +101,8 @@ public class MatchingGui {
95 private JLabel m_sourceClassLabel; 101 private JLabel m_sourceClassLabel;
96 private JLabel m_destClassLabel; 102 private JLabel m_destClassLabel;
97 private JButton m_matchButton; 103 private JButton m_matchButton;
104 private Map<SourceType,JRadioButton> m_sourceTypeButtons;
105 private JCheckBox m_advanceCheck;
98 106
99 private Matches m_matches; 107 private Matches m_matches;
100 private Deobfuscator m_sourceDeobfuscator; 108 private Deobfuscator m_sourceDeobfuscator;
@@ -133,8 +141,11 @@ public class MatchingGui {
133 } 141 }
134 }; 142 };
135 ButtonGroup sourceTypeButtons = new ButtonGroup(); 143 ButtonGroup sourceTypeButtons = new ButtonGroup();
144 m_sourceTypeButtons = Maps.newHashMap();
136 for (SourceType sourceType : SourceType.values()) { 145 for (SourceType sourceType : SourceType.values()) {
137 sourceTypePanel.add(sourceType.newRadio(sourceTypeListener, sourceTypeButtons)); 146 JRadioButton button = sourceType.newRadio(sourceTypeListener, sourceTypeButtons);
147 m_sourceTypeButtons.put(sourceType, button);
148 sourceTypePanel.add(button);
138 } 149 }
139 150
140 m_sourceClasses = new ClassSelector(ClassSelector.DeobfuscatedClassEntryComparator); 151 m_sourceClasses = new ClassSelector(ClassSelector.DeobfuscatedClassEntryComparator);
@@ -164,6 +175,15 @@ public class MatchingGui {
164 JScrollPane destScroller = new JScrollPane(m_destClasses); 175 JScrollPane destScroller = new JScrollPane(m_destClasses);
165 destPanel.add(destScroller); 176 destPanel.add(destScroller);
166 177
178 JButton autoMatchButton = new JButton("AutoMatch");
179 autoMatchButton.addActionListener(new ActionListener() {
180 @Override
181 public void actionPerformed(ActionEvent event) {
182 autoMatch();
183 }
184 });
185 destPanel.add(autoMatchButton);
186
167 // init source panels 187 // init source panels
168 DefaultSyntaxKit.initKit(); 188 DefaultSyntaxKit.initKit();
169 m_sourceReader = new JEditorPane(); 189 m_sourceReader = new JEditorPane();
@@ -188,18 +208,21 @@ public class MatchingGui {
188 bottomPanel.setLayout(new FlowLayout()); 208 bottomPanel.setLayout(new FlowLayout());
189 209
190 m_sourceClassLabel = new JLabel(); 210 m_sourceClassLabel = new JLabel();
191 m_sourceClassLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT); 211 m_sourceClassLabel.setHorizontalAlignment(SwingConstants.RIGHT);
192 m_sourceClassLabel.setPreferredSize(new Dimension(300, 24)); 212 m_sourceClassLabel.setPreferredSize(new Dimension(300, 24));
193 m_destClassLabel = new JLabel(); 213 m_destClassLabel = new JLabel();
194 m_destClassLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT); 214 m_destClassLabel.setHorizontalAlignment(SwingConstants.LEFT);
195 m_destClassLabel.setPreferredSize(new Dimension(300, 24)); 215 m_destClassLabel.setPreferredSize(new Dimension(300, 24));
196 216
197 m_matchButton = new JButton(); 217 m_matchButton = new JButton();
198 m_matchButton.setPreferredSize(new Dimension(140, 24)); 218 m_matchButton.setPreferredSize(new Dimension(140, 24));
199 219
220 m_advanceCheck = new JCheckBox("Advance to next likely match");
221
200 bottomPanel.add(m_sourceClassLabel); 222 bottomPanel.add(m_sourceClassLabel);
201 bottomPanel.add(m_matchButton); 223 bottomPanel.add(m_matchButton);
202 bottomPanel.add(m_destClassLabel); 224 bottomPanel.add(m_destClassLabel);
225 bottomPanel.add(m_advanceCheck);
203 pane.add(bottomPanel, BorderLayout.SOUTH); 226 pane.add(bottomPanel, BorderLayout.SOUTH);
204 227
205 // show the frame 228 // show the frame
@@ -210,7 +233,7 @@ public class MatchingGui {
210 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 233 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
211 234
212 // init state 235 // init state
213 updateMappings(); 236 updateDestMappings();
214 setSourceType(SourceType.getDefault()); 237 setSourceType(SourceType.getDefault());
215 updateMatchButton(); 238 updateMatchButton();
216 m_saveListener = null; 239 m_saveListener = null;
@@ -220,7 +243,7 @@ public class MatchingGui {
220 m_saveListener = val; 243 m_saveListener = val;
221 } 244 }
222 245
223 private void updateMappings() { 246 private void updateDestMappings() {
224 m_destDeobfuscator.setMappings(MappingsConverter.newMappings( 247 m_destDeobfuscator.setMappings(MappingsConverter.newMappings(
225 m_matches, 248 m_matches,
226 m_sourceDeobfuscator.getMappings(), 249 m_sourceDeobfuscator.getMappings(),
@@ -230,9 +253,18 @@ public class MatchingGui {
230 } 253 }
231 254
232 protected void setSourceType(SourceType val) { 255 protected void setSourceType(SourceType val) {
256
233 // show the source classes 257 // show the source classes
234 m_sourceType = val; 258 m_sourceType = val;
235 m_sourceClasses.setClasses(deobfuscateClasses(m_sourceType.getSourceClasses(m_matches), m_sourceDeobfuscator)); 259 m_sourceClasses.setClasses(deobfuscateClasses(m_sourceType.getSourceClasses(m_matches), m_sourceDeobfuscator));
260
261 // update counts
262 for (SourceType sourceType : SourceType.values()) {
263 m_sourceTypeButtons.get(sourceType).setText(String.format("%s (%d)",
264 sourceType.name(),
265 sourceType.getSourceClasses(m_matches).size()
266 ));
267 }
236 } 268 }
237 269
238 private Collection<ClassEntry> deobfuscateClasses(Collection<ClassEntry> in, Deobfuscator deobfuscator) { 270 private Collection<ClassEntry> deobfuscateClasses(Collection<ClassEntry> in, Deobfuscator deobfuscator) {
@@ -296,31 +328,37 @@ public class MatchingGui {
296 namer.getDestNamer(), true 328 namer.getDestNamer(), true
297 ); 329 );
298 330
299 // rank all the unmatched dest classes against the source class 331 try {
300 ClassIdentity sourceIdentity = sourceIdentifier.identify(obfSourceClass); 332
301 Multimap<Float,ClassEntry> scoredDestClasses = ArrayListMultimap.create(); 333 // rank all the unmatched dest classes against the source class
302 for (ClassEntry unmatchedDestClass : m_matches.getUnmatchedDestClasses()) { 334 ClassIdentity sourceIdentity = sourceIdentifier.identify(obfSourceClass);
303 ClassIdentity destIdentity = destIdentifier.identify(unmatchedDestClass); 335 Multimap<Float,ClassEntry> scoredDestClasses = ArrayListMultimap.create();
304 float score = 100.0f*(sourceIdentity.getMatchScore(destIdentity) + destIdentity.getMatchScore(sourceIdentity)) 336 for (ClassEntry unmatchedDestClass : m_matches.getUnmatchedDestClasses()) {
305 /(sourceIdentity.getMaxMatchScore() + destIdentity.getMaxMatchScore()); 337 ClassIdentity destIdentity = destIdentifier.identify(unmatchedDestClass);
306 scoredDestClasses.put(score, unmatchedDestClass); 338 float score = 100.0f*(sourceIdentity.getMatchScore(destIdentity) + destIdentity.getMatchScore(sourceIdentity))
307 } 339 /(sourceIdentity.getMaxMatchScore() + destIdentity.getMaxMatchScore());
340 scoredDestClasses.put(score, unmatchedDestClass);
341 }
308 342
309 // sort by scores 343 // sort by scores
310 List<Float> scores = new ArrayList<Float>(scoredDestClasses.keySet()); 344 List<Float> scores = new ArrayList<Float>(scoredDestClasses.keySet());
311 Collections.sort(scores, Collections.reverseOrder()); 345 Collections.sort(scores, Collections.reverseOrder());
312 346
313 // collect the scored classes in order 347 // collect the scored classes in order
314 List<ClassEntry> scoredClasses = Lists.newArrayList(); 348 List<ClassEntry> scoredClasses = Lists.newArrayList();
315 for (float score : scores) { 349 for (float score : scores) {
316 for (ClassEntry classEntry : scoredDestClasses.get(score)) { 350 for (ClassEntry classEntry : scoredDestClasses.get(score)) {
317 scoredClasses.add(new DecoratedClassEntry(classEntry, String.format("%.0f%% ", score))); 351 scoredClasses.add(new DecoratedClassEntry(classEntry, String.format("%2.0f%% ", score)));
318 if (scoredClasses.size() > 10) { 352 if (scoredClasses.size() > 10) {
319 return scoredClasses; 353 return scoredClasses;
354 }
320 } 355 }
321 } 356 }
357 return scoredClasses;
358
359 } catch (ClassNotFoundException ex) {
360 throw new Error("Unable to find class " + ex.getMessage());
322 } 361 }
323 return scoredClasses;
324 } 362 }
325 363
326 protected void setDestClass(ClassEntry classEntry) { 364 protected void setDestClass(ClassEntry classEntry) {
@@ -419,15 +457,18 @@ public class MatchingGui {
419 // add them as matched classes 457 // add them as matched classes
420 m_matches.add(new ClassMatch(obfSource, obfDest)); 458 m_matches.add(new ClassMatch(obfSource, obfDest));
421 459
422 // TEMP 460 // remember where we were in the source tree
423 System.out.println("Match: " + obfSource + " <-> " + obfDest); 461 TreePath path = m_sourceClasses.getSelectionPath();
424 462
425 //save(); 463 save();
426 updateMappings(); 464 updateMatches();
427 setDestClass(null); 465
428 m_destClasses.setClasses(null); 466 // put the tree back to where it was
429 updateMatchButton(); 467 m_sourceClasses.expandPath(path);
430 setSourceType(m_sourceType); 468
469 if (m_advanceCheck.isSelected()) {
470
471 }
431 } 472 }
432 473
433 private void onUnmatchClick() { 474 private void onUnmatchClick() {
@@ -439,11 +480,12 @@ public class MatchingGui {
439 m_matches.removeSource(obfSource); 480 m_matches.removeSource(obfSource);
440 m_matches.add(new ClassMatch(obfSource, null)); 481 m_matches.add(new ClassMatch(obfSource, null));
441 482
442 // TEMP 483 save();
443 System.out.println("Unmatch: " + obfSource + " <-> " + m_destDeobfuscator.obfuscateEntry(m_destClass)); 484 updateMatches();
444 485 }
445 //save(); 486
446 updateMappings(); 487 private void updateMatches() {
488 updateDestMappings();
447 setDestClass(null); 489 setDestClass(null);
448 m_destClasses.setClasses(null); 490 m_destClasses.setClasses(null);
449 updateMatchButton(); 491 updateMatchButton();
@@ -455,4 +497,25 @@ public class MatchingGui {
455 m_saveListener.save(m_matches); 497 m_saveListener.save(m_matches);
456 } 498 }
457 } 499 }
500
501 private void autoMatch() {
502
503 System.out.println("Automatching...");
504
505 // compute a new matching
506 ClassMatching matching = MappingsConverter.computeMatching(
507 m_sourceDeobfuscator.getJar(), m_sourceDeobfuscator.getJarIndex(),
508 m_destDeobfuscator.getJar(), m_destDeobfuscator.getJarIndex(),
509 m_matches.getUniqueMatches()
510 );
511 Matches newMatches = new Matches(matching.matches());
512 System.out.println(String.format("Automatch found %d new matches",
513 newMatches.getUniqueMatches().size() - m_matches.getUniqueMatches().size()
514 ));
515
516 // update the current matches
517 m_matches = newMatches;
518 save();
519 updateMatches();
520 }
458} 521}