summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cuchaz/enigma/ConvertMain.java15
-rw-r--r--src/cuchaz/enigma/bytecode/LocalVariableRenamer.java7
-rw-r--r--src/cuchaz/enigma/convert/ClassMatch.java12
-rw-r--r--src/cuchaz/enigma/convert/Matches.java38
-rw-r--r--src/cuchaz/enigma/gui/MatchingGui.java157
5 files changed, 193 insertions, 36 deletions
diff --git a/src/cuchaz/enigma/ConvertMain.java b/src/cuchaz/enigma/ConvertMain.java
index 4fc58e8..cad49f5 100644
--- a/src/cuchaz/enigma/ConvertMain.java
+++ b/src/cuchaz/enigma/ConvertMain.java
@@ -10,6 +10,7 @@ import cuchaz.enigma.convert.Matches;
10import cuchaz.enigma.convert.MatchesReader; 10import cuchaz.enigma.convert.MatchesReader;
11import cuchaz.enigma.convert.MatchesWriter; 11import cuchaz.enigma.convert.MatchesWriter;
12import cuchaz.enigma.gui.MatchingGui; 12import cuchaz.enigma.gui.MatchingGui;
13import cuchaz.enigma.gui.MatchingGui.SaveListener;
13import cuchaz.enigma.mapping.MappingParseException; 14import cuchaz.enigma.mapping.MappingParseException;
14import cuchaz.enigma.mapping.Mappings; 15import cuchaz.enigma.mapping.Mappings;
15import cuchaz.enigma.mapping.MappingsReader; 16import cuchaz.enigma.mapping.MappingsReader;
@@ -49,7 +50,7 @@ public class ConvertMain {
49 System.out.println("Wrote:\n\t" + matchingFile.getAbsolutePath()); 50 System.out.println("Wrote:\n\t" + matchingFile.getAbsolutePath());
50 } 51 }
51 52
52 private static void editMatches(File matchingFile, JarFile sourceJar, JarFile destJar, Mappings mappings) 53 private static void editMatches(final File matchingFile, JarFile sourceJar, JarFile destJar, Mappings mappings)
53 throws IOException { 54 throws IOException {
54 System.out.println("Reading matches..."); 55 System.out.println("Reading matches...");
55 Matches matches = MatchesReader.read(matchingFile); 56 Matches matches = MatchesReader.read(matchingFile);
@@ -58,9 +59,17 @@ public class ConvertMain {
58 sourceDeobfuscator.setMappings(mappings); 59 sourceDeobfuscator.setMappings(mappings);
59 System.out.println("Indexing dest jar..."); 60 System.out.println("Indexing dest jar...");
60 Deobfuscator destDeobfuscator = new Deobfuscator(destJar); 61 Deobfuscator destDeobfuscator = new Deobfuscator(destJar);
61 destDeobfuscator.setMappings(MappingsConverter.newMappings(matches, mappings, sourceDeobfuscator, destDeobfuscator));
62 System.out.println("Starting GUI..."); 62 System.out.println("Starting GUI...");
63 new MatchingGui(matches, sourceDeobfuscator, destDeobfuscator); 63 new MatchingGui(matches, sourceDeobfuscator, destDeobfuscator).setSaveListener(new SaveListener() {
64 @Override
65 public void save(Matches matches) {
66 try {
67 MatchesWriter.write(matches, matchingFile);
68 } catch (IOException ex) {
69 throw new Error(ex);
70 }
71 }
72 });
64 } 73 }
65 74
66 private static void convertMappings(File outMappingsFile, Mappings mappings, File matchingFile) 75 private static void convertMappings(File outMappingsFile, Mappings mappings, File matchingFile)
diff --git a/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java b/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java
index 53f207c..c87c25b 100644
--- a/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java
+++ b/src/cuchaz/enigma/bytecode/LocalVariableRenamer.java
@@ -3,6 +3,7 @@ package cuchaz.enigma.bytecode;
3import javassist.CtBehavior; 3import javassist.CtBehavior;
4import javassist.CtClass; 4import javassist.CtClass;
5import javassist.bytecode.ByteArray; 5import javassist.bytecode.ByteArray;
6import javassist.bytecode.CodeAttribute;
6import javassist.bytecode.ConstPool; 7import javassist.bytecode.ConstPool;
7import javassist.bytecode.LocalVariableAttribute; 8import javassist.bytecode.LocalVariableAttribute;
8 9
@@ -13,7 +14,11 @@ public class LocalVariableRenamer {
13 for (CtBehavior behavior : c.getDeclaredBehaviors()) { 14 for (CtBehavior behavior : c.getDeclaredBehaviors()) {
14 15
15 // if there's a local variable table, just rename everything to v1, v2, v3, ... for now 16 // if there's a local variable table, just rename everything to v1, v2, v3, ... for now
16 LocalVariableAttribute table = (LocalVariableAttribute)behavior.getMethodInfo().getCodeAttribute().getAttribute(LocalVariableAttribute.tag); 17 CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute();
18 if (codeAttribute == null) {
19 continue;
20 }
21 LocalVariableAttribute table = (LocalVariableAttribute)codeAttribute.getAttribute(LocalVariableAttribute.tag);
17 if (table == null) { 22 if (table == null) {
18 continue; 23 continue;
19 } 24 }
diff --git a/src/cuchaz/enigma/convert/ClassMatch.java b/src/cuchaz/enigma/convert/ClassMatch.java
index 9cecf70..eaaaa41 100644
--- a/src/cuchaz/enigma/convert/ClassMatch.java
+++ b/src/cuchaz/enigma/convert/ClassMatch.java
@@ -20,10 +20,16 @@ public class ClassMatch {
20 } 20 }
21 21
22 public ClassMatch(ClassEntry sourceClass, ClassEntry destClass) { 22 public ClassMatch(ClassEntry sourceClass, ClassEntry destClass) {
23 this.sourceClasses = Sets.newHashSet(sourceClass); 23 sourceClasses = Sets.newHashSet();
24 this.destClasses = Sets.newHashSet(destClass); 24 if (sourceClass != null) {
25 sourceClasses.add(sourceClass);
26 }
27 destClasses = Sets.newHashSet();
28 if (destClass != null) {
29 destClasses.add(destClass);
30 }
25 } 31 }
26 32
27 public boolean isMatched() { 33 public boolean isMatched() {
28 return sourceClasses.size() > 0 && destClasses.size() > 0; 34 return sourceClasses.size() > 0 && destClasses.size() > 0;
29 } 35 }
diff --git a/src/cuchaz/enigma/convert/Matches.java b/src/cuchaz/enigma/convert/Matches.java
index 5faa923..0b00b29 100644
--- a/src/cuchaz/enigma/convert/Matches.java
+++ b/src/cuchaz/enigma/convert/Matches.java
@@ -48,6 +48,22 @@ public class Matches implements Iterable<ClassMatch> {
48 m_matches.add(match); 48 m_matches.add(match);
49 indexMatch(match); 49 indexMatch(match);
50 } 50 }
51
52 public void remove(ClassMatch match) {
53 for (ClassEntry sourceClass : match.sourceClasses) {
54 m_matchesBySource.remove(sourceClass);
55 m_uniqueMatches.remove(sourceClass);
56 m_ambiguousMatchesBySource.remove(sourceClass);
57 m_unmatchedSourceClasses.remove(sourceClass);
58 }
59 for (ClassEntry destClass : match.sourceClasses) {
60 m_matchesByDest.remove(destClass);
61 m_uniqueMatches.inverse().remove(destClass);
62 m_ambiguousMatchesByDest.remove(destClass);
63 m_unmatchedDestClasses.remove(destClass);
64 }
65 m_matches.remove(match);
66 }
51 67
52 public int size() { 68 public int size() {
53 return m_matches.size(); 69 return m_matches.size();
@@ -112,4 +128,26 @@ public class Matches implements Iterable<ClassMatch> {
112 public ClassMatch getMatchByDest(ClassEntry destClass) { 128 public ClassMatch getMatchByDest(ClassEntry destClass) {
113 return m_matchesByDest.get(destClass); 129 return m_matchesByDest.get(destClass);
114 } 130 }
131
132 public void removeSource(ClassEntry sourceClass) {
133 ClassMatch match = m_matchesBySource.get(sourceClass);
134 if (match != null) {
135 remove(match);
136 match.sourceClasses.remove(sourceClass);
137 if (!match.sourceClasses.isEmpty() || !match.destClasses.isEmpty()) {
138 add(match);
139 }
140 }
141 }
142
143 public void removeDest(ClassEntry destClass) {
144 ClassMatch match = m_matchesByDest.get(destClass);
145 if (match != null) {
146 remove(match);
147 match.destClasses.remove(destClass);
148 if (!match.sourceClasses.isEmpty() || !match.destClasses.isEmpty()) {
149 add(match);
150 }
151 }
152 }
115} 153}
diff --git a/src/cuchaz/enigma/gui/MatchingGui.java b/src/cuchaz/enigma/gui/MatchingGui.java
index e9dff16..e2d517e 100644
--- a/src/cuchaz/enigma/gui/MatchingGui.java
+++ b/src/cuchaz/enigma/gui/MatchingGui.java
@@ -7,6 +7,7 @@ import java.awt.FlowLayout;
7import java.awt.event.ActionEvent; 7import java.awt.event.ActionEvent;
8import java.awt.event.ActionListener; 8import java.awt.event.ActionListener;
9import java.util.ArrayList; 9import java.util.ArrayList;
10import java.util.Arrays;
10import java.util.Collection; 11import java.util.Collection;
11import java.util.Collections; 12import java.util.Collections;
12import java.util.List; 13import java.util.List;
@@ -25,6 +26,7 @@ import javax.swing.WindowConstants;
25 26
26import com.beust.jcommander.internal.Lists; 27import com.beust.jcommander.internal.Lists;
27import com.google.common.collect.ArrayListMultimap; 28import com.google.common.collect.ArrayListMultimap;
29import com.google.common.collect.BiMap;
28import com.google.common.collect.Multimap; 30import com.google.common.collect.Multimap;
29 31
30import cuchaz.enigma.Constants; 32import cuchaz.enigma.Constants;
@@ -33,6 +35,7 @@ import cuchaz.enigma.convert.ClassIdentifier;
33import cuchaz.enigma.convert.ClassIdentity; 35import cuchaz.enigma.convert.ClassIdentity;
34import cuchaz.enigma.convert.ClassMatch; 36import cuchaz.enigma.convert.ClassMatch;
35import cuchaz.enigma.convert.ClassNamer; 37import cuchaz.enigma.convert.ClassNamer;
38import cuchaz.enigma.convert.MappingsConverter;
36import cuchaz.enigma.convert.Matches; 39import cuchaz.enigma.convert.Matches;
37import cuchaz.enigma.gui.ClassSelector.ClassSelectionListener; 40import cuchaz.enigma.gui.ClassSelector.ClassSelectionListener;
38import cuchaz.enigma.mapping.ClassEntry; 41import cuchaz.enigma.mapping.ClassEntry;
@@ -79,6 +82,10 @@ public class MatchingGui {
79 } 82 }
80 } 83 }
81 84
85 public static interface SaveListener {
86 public void save(Matches matches);
87 }
88
82 // controls 89 // controls
83 private JFrame m_frame; 90 private JFrame m_frame;
84 private ClassSelector m_sourceClasses; 91 private ClassSelector m_sourceClasses;
@@ -94,6 +101,8 @@ public class MatchingGui {
94 private Deobfuscator m_destDeobfuscator; 101 private Deobfuscator m_destDeobfuscator;
95 private ClassEntry m_sourceClass; 102 private ClassEntry m_sourceClass;
96 private ClassEntry m_destClass; 103 private ClassEntry m_destClass;
104 private SourceType m_sourceType;
105 private SaveListener m_saveListener;
97 106
98 public MatchingGui(Matches matches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) { 107 public MatchingGui(Matches matches, Deobfuscator sourceDeobfuscator, Deobfuscator destDeobfuscator) {
99 108
@@ -179,17 +188,13 @@ public class MatchingGui {
179 bottomPanel.setLayout(new FlowLayout()); 188 bottomPanel.setLayout(new FlowLayout());
180 189
181 m_sourceClassLabel = new JLabel(); 190 m_sourceClassLabel = new JLabel();
182 m_sourceClassLabel.setPreferredSize(new Dimension(300, 0)); 191 m_sourceClassLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
192 m_sourceClassLabel.setPreferredSize(new Dimension(300, 24));
183 m_destClassLabel = new JLabel(); 193 m_destClassLabel = new JLabel();
184 m_destClassLabel.setPreferredSize(new Dimension(300, 0)); 194 m_destClassLabel.setAlignmentX(JLabel.CENTER_ALIGNMENT);
195 m_destClassLabel.setPreferredSize(new Dimension(300, 24));
185 196
186 m_matchButton = new JButton(); 197 m_matchButton = new JButton();
187 m_matchButton.addActionListener(new ActionListener() {
188 @Override
189 public void actionPerformed(ActionEvent event) {
190 onMatchClick();
191 }
192 });
193 m_matchButton.setPreferredSize(new Dimension(140, 24)); 198 m_matchButton.setPreferredSize(new Dimension(140, 24));
194 199
195 bottomPanel.add(m_sourceClassLabel); 200 bottomPanel.add(m_sourceClassLabel);
@@ -205,13 +210,29 @@ public class MatchingGui {
205 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 210 m_frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
206 211
207 // init state 212 // init state
213 updateMappings();
208 setSourceType(SourceType.getDefault()); 214 setSourceType(SourceType.getDefault());
209 updateMatchButton(); 215 updateMatchButton();
216 m_saveListener = null;
217 }
218
219 public void setSaveListener(SaveListener val) {
220 m_saveListener = val;
221 }
222
223 private void updateMappings() {
224 m_destDeobfuscator.setMappings(MappingsConverter.newMappings(
225 m_matches,
226 m_sourceDeobfuscator.getMappings(),
227 m_sourceDeobfuscator,
228 m_destDeobfuscator
229 ));
210 } 230 }
211 231
212 protected void setSourceType(SourceType val) { 232 protected void setSourceType(SourceType val) {
213 // show the source classes 233 // show the source classes
214 m_sourceClasses.setClasses(deobfuscateClasses(val.getSourceClasses(m_matches), m_sourceDeobfuscator)); 234 m_sourceType = val;
235 m_sourceClasses.setClasses(deobfuscateClasses(m_sourceType.getSourceClasses(m_matches), m_sourceDeobfuscator));
215 } 236 }
216 237
217 private Collection<ClassEntry> deobfuscateClasses(Collection<ClassEntry> in, Deobfuscator deobfuscator) { 238 private Collection<ClassEntry> deobfuscateClasses(Collection<ClassEntry> in, Deobfuscator deobfuscator) {
@@ -234,11 +255,24 @@ public class MatchingGui {
234 ClassMatch match = m_matches.getMatchBySource(m_sourceDeobfuscator.obfuscateEntry(m_sourceClass)); 255 ClassMatch match = m_matches.getMatchBySource(m_sourceDeobfuscator.obfuscateEntry(m_sourceClass));
235 assert(match != null); 256 assert(match != null);
236 if (match.destClasses.isEmpty()) { 257 if (match.destClasses.isEmpty()) {
237 m_destClasses.setClasses(deobfuscateClasses(getLikelyMatches(m_sourceClass), m_destDeobfuscator)); 258
259 m_destClasses.setClasses(null);
260
261 // run in a separate thread to keep ui responsive
262 new Thread() {
263 @Override
264 public void run() {
265 m_destClasses.setClasses(deobfuscateClasses(getLikelyMatches(m_sourceClass), m_destDeobfuscator));
266 m_destClasses.expandRow(0);
267 }
268 }.start();
269
238 } else { 270 } else {
271
239 m_destClasses.setClasses(deobfuscateClasses(match.destClasses, m_destDeobfuscator)); 272 m_destClasses.setClasses(deobfuscateClasses(match.destClasses, m_destDeobfuscator));
273 m_destClasses.expandRow(0);
274
240 } 275 }
241 m_destClasses.expandRow(0);
242 } 276 }
243 277
244 setDestClass(null); 278 setDestClass(null);
@@ -309,7 +343,7 @@ public class MatchingGui {
309 343
310 reader.setText("(decompiling...)"); 344 reader.setText("(decompiling...)");
311 345
312 // run decompiler in a separate thread to keep ui responsive 346 // run in a separate thread to keep ui responsive
313 new Thread() { 347 new Thread() {
314 @Override 348 @Override
315 public void run() { 349 public void run() {
@@ -327,33 +361,98 @@ public class MatchingGui {
327 361
328 private void updateMatchButton() { 362 private void updateMatchButton() {
329 363
364 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass);
365 ClassEntry obfDest = m_destDeobfuscator.obfuscateEntry(m_destClass);
366
367 BiMap<ClassEntry,ClassEntry> uniqueMatches = m_matches.getUniqueMatches();
330 boolean twoSelected = m_sourceClass != null && m_destClass != null; 368 boolean twoSelected = m_sourceClass != null && m_destClass != null;
331 boolean isMatched = twoSelected && m_matches.getUniqueMatches().containsKey(m_sourceDeobfuscator.obfuscateEntry(m_sourceClass)); 369 boolean isMatched = uniqueMatches.containsKey(obfSource) && uniqueMatches.containsValue(obfDest);
370 boolean canMatch = !uniqueMatches.containsKey(obfSource) && ! uniqueMatches.containsValue(obfDest);
332 371
333 m_matchButton.setEnabled(twoSelected); 372 deactivateButton(m_matchButton);
334 if (twoSelected) { 373 if (twoSelected) {
335 if (isMatched) { 374 if (isMatched) {
336 m_matchButton.setText("Unmatch"); 375 activateButton(m_matchButton, "Unmatch", new ActionListener() {
337 } else { 376 @Override
338 m_matchButton.setText("Match"); 377 public void actionPerformed(ActionEvent event) {
378 onUnmatchClick();
379 }
380 });
381 } else if (canMatch) {
382 activateButton(m_matchButton, "Match", new ActionListener() {
383 @Override
384 public void actionPerformed(ActionEvent event) {
385 onMatchClick();
386 }
387 });
339 } 388 }
340 } else {
341 m_matchButton.setText("");
342 } 389 }
343 } 390 }
344 391
345 protected void onMatchClick() { 392 private void deactivateButton(JButton button) {
346 // TODO 393 button.setEnabled(false);
394 button.setText("");
395 for (ActionListener listener : Arrays.asList(button.getActionListeners())) {
396 button.removeActionListener(listener);
397 }
347 } 398 }
348 399
349 /* 400 private void activateButton(JButton button, String text, ActionListener newListener) {
350 private static List<String> getClassNames(Collection<ClassEntry> classes) { 401 button.setText(text);
351 List<String> out = Lists.newArrayList(); 402 button.setEnabled(true);
352 for (ClassEntry c : classes) { 403 for (ActionListener listener : Arrays.asList(button.getActionListeners())) {
353 out.add(c.getName()); 404 button.removeActionListener(listener);
405 }
406 button.addActionListener(newListener);
407 }
408
409 private void onMatchClick() {
410 // precondition: source and dest classes are set correctly
411
412 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass);
413 ClassEntry obfDest = m_destDeobfuscator.obfuscateEntry(m_destClass);
414
415 // remove the classes from their match
416 m_matches.removeSource(obfSource);
417 m_matches.removeDest(obfDest);
418
419 // add them as matched classes
420 m_matches.add(new ClassMatch(obfSource, obfDest));
421
422 // TEMP
423 System.out.println("Match: " + obfSource + " <-> " + obfDest);
424
425 //save();
426 updateMappings();
427 setDestClass(null);
428 m_destClasses.setClasses(null);
429 updateMatchButton();
430 setSourceType(m_sourceType);
431 }
432
433 private void onUnmatchClick() {
434 // precondition: source and dest classes are set to a unique match
435
436 ClassEntry obfSource = m_sourceDeobfuscator.obfuscateEntry(m_sourceClass);
437
438 // remove the source to break the match, then add the source back as unmatched
439 m_matches.removeSource(obfSource);
440 m_matches.add(new ClassMatch(obfSource, null));
441
442 // TEMP
443 System.out.println("Unmatch: " + obfSource + " <-> " + m_destDeobfuscator.obfuscateEntry(m_destClass));
444
445 //save();
446 updateMappings();
447 setDestClass(null);
448 m_destClasses.setClasses(null);
449 updateMatchButton();
450 setSourceType(m_sourceType);
451 }
452
453 private void save() {
454 if (m_saveListener != null) {
455 m_saveListener.save(m_matches);
354 } 456 }
355 Collections.sort(out);
356 return out;
357 } 457 }
358 */
359} 458}