summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar jeff2014-07-31 22:27:26 -0400
committerGravatar jeff2014-07-31 22:27:26 -0400
commitfaae0a6514c2565a10f9a62dd18c5d79fbbe4156 (patch)
tree9369f3b920919dd4a4bb2aa449c3dc467d4a43ea /src
parentswitched to line-by-line mergable, human-readable file format for mappings (diff)
downloadenigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.tar.gz
enigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.tar.xz
enigma-fork-faae0a6514c2565a10f9a62dd18c5d79fbbe4156.zip
fixed bug with save mappings menu
gui shows deobfuscated classes list now working on name validation/sanitization
Diffstat (limited to 'src')
-rw-r--r--src/cuchaz/enigma/ClassFile.java34
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java60
-rw-r--r--src/cuchaz/enigma/gui/ClassListCellRenderer.java (renamed from src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java)4
-rw-r--r--src/cuchaz/enigma/gui/Gui.java64
-rw-r--r--src/cuchaz/enigma/gui/GuiController.java18
-rw-r--r--src/cuchaz/enigma/mapping/NameValidator.java67
6 files changed, 178 insertions, 69 deletions
diff --git a/src/cuchaz/enigma/ClassFile.java b/src/cuchaz/enigma/ClassFile.java
index 221a119..c3c72a4 100644
--- a/src/cuchaz/enigma/ClassFile.java
+++ b/src/cuchaz/enigma/ClassFile.java
@@ -10,36 +10,42 @@
10 ******************************************************************************/ 10 ******************************************************************************/
11package cuchaz.enigma; 11package cuchaz.enigma;
12 12
13import java.util.regex.Pattern;
14 13
15public class ClassFile 14public class ClassFile
16{ 15{
17 private static Pattern m_obfuscatedClassPattern; 16 private String m_obfName;
17 private String m_deobfName;
18 18
19 static 19 public ClassFile( String obfName )
20 { 20 {
21 m_obfuscatedClassPattern = Pattern.compile( "^[a-z]+$" ); 21 m_obfName = obfName;
22 } 22 }
23 23
24 private String m_name; 24 public String getName( )
25
26 public ClassFile( String name )
27 { 25 {
28 m_name = name; 26 if( m_deobfName != null )
27 {
28 return m_deobfName;
29 }
30 return m_obfName;
29 } 31 }
30 32
31 public String getName( ) 33 public String getObfName( )
32 { 34 {
33 return m_name; 35 return m_obfName;
34 } 36 }
35 37
36 public boolean isObfuscated( ) 38 public String getDeobfName( )
37 { 39 {
38 return m_obfuscatedClassPattern.matcher( m_name ).matches(); 40 return m_deobfName;
39 } 41 }
40 42 public void setDeobfName( String val )
43 {
44 m_deobfName = val;
45 }
46
41 public String getPath( ) 47 public String getPath( )
42 { 48 {
43 return m_name.replace( ".", "/" ) + ".class"; 49 return m_deobfName.replace( ".", "/" ) + ".class";
44 } 50 }
45} 51}
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index 7be5706..619eebf 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -15,9 +15,6 @@ import java.io.FileInputStream;
15import java.io.IOException; 15import java.io.IOException;
16import java.io.InputStream; 16import java.io.InputStream;
17import java.io.StringWriter; 17import java.io.StringWriter;
18import java.util.ArrayList;
19import java.util.Collections;
20import java.util.Comparator;
21import java.util.Enumeration; 18import java.util.Enumeration;
22import java.util.List; 19import java.util.List;
23import java.util.jar.JarEntry; 20import java.util.jar.JarEntry;
@@ -30,10 +27,12 @@ import com.strobel.decompiler.PlainTextOutput;
30import cuchaz.enigma.mapping.Ancestries; 27import cuchaz.enigma.mapping.Ancestries;
31import cuchaz.enigma.mapping.ArgumentEntry; 28import cuchaz.enigma.mapping.ArgumentEntry;
32import cuchaz.enigma.mapping.ClassEntry; 29import cuchaz.enigma.mapping.ClassEntry;
30import cuchaz.enigma.mapping.ClassMapping;
33import cuchaz.enigma.mapping.Entry; 31import cuchaz.enigma.mapping.Entry;
34import cuchaz.enigma.mapping.FieldEntry; 32import cuchaz.enigma.mapping.FieldEntry;
35import cuchaz.enigma.mapping.Mappings; 33import cuchaz.enigma.mapping.Mappings;
36import cuchaz.enigma.mapping.MethodEntry; 34import cuchaz.enigma.mapping.MethodEntry;
35import cuchaz.enigma.mapping.NameValidator;
37import cuchaz.enigma.mapping.Renamer; 36import cuchaz.enigma.mapping.Renamer;
38import cuchaz.enigma.mapping.TranslationDirection; 37import cuchaz.enigma.mapping.TranslationDirection;
39import cuchaz.enigma.mapping.Translator; 38import cuchaz.enigma.mapping.Translator;
@@ -47,25 +46,6 @@ public class Deobfuscator
47 private Mappings m_mappings; 46 private Mappings m_mappings;
48 private Renamer m_renamer; 47 private Renamer m_renamer;
49 48
50 private static Comparator<ClassFile> m_obfuscatedClassSorter;
51
52 static
53 {
54 m_obfuscatedClassSorter = new Comparator<ClassFile>( )
55 {
56 @Override
57 public int compare( ClassFile a, ClassFile b )
58 {
59 if( a.getName().length() != b.getName().length() )
60 {
61 return a.getName().length() - b.getName().length();
62 }
63
64 return a.getName().compareTo( b.getName() );
65 }
66 };
67 }
68
69 public Deobfuscator( File file ) 49 public Deobfuscator( File file )
70 throws IOException 50 throws IOException
71 { 51 {
@@ -120,48 +100,38 @@ public class Deobfuscator
120 ) ); 100 ) );
121 } 101 }
122 102
123 public List<ClassFile> getObfuscatedClasses( ) 103 public void getSortedClasses( List<ClassFile> obfClasses, List<ClassFile> deobfClasses )
124 { 104 {
125 List<ClassFile> classes = new ArrayList<ClassFile>();
126 Enumeration<JarEntry> entries = m_jar.entries(); 105 Enumeration<JarEntry> entries = m_jar.entries();
127 while( entries.hasMoreElements() ) 106 while( entries.hasMoreElements() )
128 { 107 {
129 JarEntry entry = entries.nextElement(); 108 JarEntry entry = entries.nextElement();
130 109
131 // get the class name 110 // get the class name
132 String className = toClassName( entry.getName() ); 111 String obfName = NameValidator.fileNameToClassName( entry.getName() );
133 if( className == null ) 112 if( obfName == null )
134 { 113 {
135 continue; 114 continue;
136 } 115 }
137 116
138 ClassFile classFile = new ClassFile( className ); 117 ClassFile classFile = new ClassFile( obfName );
139 if( classFile.isObfuscated() ) 118 ClassMapping classMapping = m_mappings.getClassByObf( classFile.getName() );
119 if( classMapping != null )
140 { 120 {
141 classes.add( classFile ); 121 classFile.setDeobfName( classMapping.getDeobfName() );
122 deobfClasses.add( classFile );
123 }
124 else
125 {
126 obfClasses.add( classFile );
142 } 127 }
143 } 128 }
144 Collections.sort( classes, m_obfuscatedClassSorter );
145 return classes;
146 }
147
148 // TODO: could go somewhere more generic
149 private static String toClassName( String fileName )
150 {
151 final String suffix = ".class";
152
153 if( !fileName.endsWith( suffix ) )
154 {
155 return null;
156 }
157
158 return fileName.substring( 0, fileName.length() - suffix.length() ).replace( "/", "." );
159 } 129 }
160 130
161 public String getSource( final ClassFile classFile ) 131 public String getSource( final ClassFile classFile )
162 { 132 {
163 StringWriter buf = new StringWriter(); 133 StringWriter buf = new StringWriter();
164 Decompiler.decompile( classFile.getName(), new PlainTextOutput( buf ), m_settings ); 134 Decompiler.decompile( classFile.getObfName(), new PlainTextOutput( buf ), m_settings );
165 return buf.toString(); 135 return buf.toString();
166 } 136 }
167 137
diff --git a/src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java b/src/cuchaz/enigma/gui/ClassListCellRenderer.java
index 0badb3b..302f140 100644
--- a/src/cuchaz/enigma/gui/ObfuscatedClassListCellRenderer.java
+++ b/src/cuchaz/enigma/gui/ClassListCellRenderer.java
@@ -19,11 +19,11 @@ import javax.swing.ListCellRenderer;
19 19
20import cuchaz.enigma.ClassFile; 20import cuchaz.enigma.ClassFile;
21 21
22public class ObfuscatedClassListCellRenderer implements ListCellRenderer<ClassFile> 22public class ClassListCellRenderer implements ListCellRenderer<ClassFile>
23{ 23{
24 private DefaultListCellRenderer m_defaultRenderer; 24 private DefaultListCellRenderer m_defaultRenderer;
25 25
26 public ObfuscatedClassListCellRenderer( ) 26 public ClassListCellRenderer( )
27 { 27 {
28 m_defaultRenderer = new DefaultListCellRenderer(); 28 m_defaultRenderer = new DefaultListCellRenderer();
29 } 29 }
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index a86ff9b..d448dc2 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -21,6 +21,8 @@ import java.awt.event.ActionListener;
21import java.awt.event.MouseAdapter; 21import java.awt.event.MouseAdapter;
22import java.awt.event.MouseEvent; 22import java.awt.event.MouseEvent;
23import java.io.IOException; 23import java.io.IOException;
24import java.util.Collections;
25import java.util.Comparator;
24import java.util.List; 26import java.util.List;
25import java.util.Vector; 27import java.util.Vector;
26 28
@@ -58,6 +60,25 @@ import cuchaz.enigma.mapping.MethodEntry;
58 60
59public class Gui 61public class Gui
60{ 62{
63 private static Comparator<ClassFile> m_obfuscatedClassSorter;
64
65 static
66 {
67 m_obfuscatedClassSorter = new Comparator<ClassFile>( )
68 {
69 @Override
70 public int compare( ClassFile a, ClassFile b )
71 {
72 if( a.getName().length() != b.getName().length() )
73 {
74 return a.getName().length() - b.getName().length();
75 }
76
77 return a.getName().compareTo( b.getName() );
78 }
79 };
80 }
81
61 private GuiController m_controller; 82 private GuiController m_controller;
62 83
63 // controls 84 // controls
@@ -101,7 +122,7 @@ public class Gui
101 m_obfClasses = new JList<ClassFile>(); 122 m_obfClasses = new JList<ClassFile>();
102 m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); 123 m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
103 m_obfClasses.setLayoutOrientation( JList.VERTICAL ); 124 m_obfClasses.setLayoutOrientation( JList.VERTICAL );
104 m_obfClasses.setCellRenderer( new ObfuscatedClassListCellRenderer() ); 125 m_obfClasses.setCellRenderer( new ClassListCellRenderer() );
105 m_obfClasses.addMouseListener( new MouseAdapter() 126 m_obfClasses.addMouseListener( new MouseAdapter()
106 { 127 {
107 public void mouseClicked( MouseEvent event ) 128 public void mouseClicked( MouseEvent event )
@@ -124,8 +145,23 @@ public class Gui
124 145
125 // init deobfuscated classes list 146 // init deobfuscated classes list
126 m_deobfClasses = new JList<ClassFile>(); 147 m_deobfClasses = new JList<ClassFile>();
127 m_obfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); 148 m_deobfClasses.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
128 m_obfClasses.setLayoutOrientation( JList.VERTICAL ); 149 m_deobfClasses.setLayoutOrientation( JList.VERTICAL );
150 m_deobfClasses.setCellRenderer( new ClassListCellRenderer() );
151 m_deobfClasses.addMouseListener( new MouseAdapter()
152 {
153 public void mouseClicked( MouseEvent event )
154 {
155 if( event.getClickCount() == 2 )
156 {
157 ClassFile selected = m_deobfClasses.getSelectedValue();
158 if( selected != null )
159 {
160 m_controller.deobfuscateClass( selected );
161 }
162 }
163 }
164 } );
129 JScrollPane deobfScroller = new JScrollPane( m_deobfClasses ); 165 JScrollPane deobfScroller = new JScrollPane( m_deobfClasses );
130 JPanel deobfPanel = new JPanel(); 166 JPanel deobfPanel = new JPanel();
131 deobfPanel.setLayout( new BorderLayout() ); 167 deobfPanel.setLayout( new BorderLayout() );
@@ -248,7 +284,6 @@ public class Gui
248 try 284 try
249 { 285 {
250 m_controller.openMappings( m_mappingFileChooser.getSelectedFile() ); 286 m_controller.openMappings( m_mappingFileChooser.getSelectedFile() );
251 m_saveMappingsMenu.setEnabled( true );
252 } 287 }
253 catch( IOException ex ) 288 catch( IOException ex )
254 { 289 {
@@ -383,7 +418,9 @@ public class Gui
383 { 418 {
384 if( classes != null ) 419 if( classes != null )
385 { 420 {
386 m_obfClasses.setListData( new Vector<ClassFile>( classes ) ); 421 Vector<ClassFile> sortedClasses = new Vector<ClassFile>( classes );
422 Collections.sort( sortedClasses, m_obfuscatedClassSorter );
423 m_obfClasses.setListData( sortedClasses );
387 } 424 }
388 else 425 else
389 { 426 {
@@ -391,6 +428,23 @@ public class Gui
391 } 428 }
392 } 429 }
393 430
431 public void setDeobfClasses( List<ClassFile> classes )
432 {
433 if( classes != null )
434 {
435 m_deobfClasses.setListData( new Vector<ClassFile>( classes ) );
436 }
437 else
438 {
439 m_deobfClasses.setListData( new Vector<ClassFile>() );
440 }
441 }
442
443 public void setMappingsLoaded( boolean isLoaded )
444 {
445 m_saveMappingsMenu.setEnabled( isLoaded );
446 }
447
394 public void setSource( String source ) 448 public void setSource( String source )
395 { 449 {
396 setSource( source, null ); 450 setSource( source, null );
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java
index fb22b96..ce1c31b 100644
--- a/src/cuchaz/enigma/gui/GuiController.java
+++ b/src/cuchaz/enigma/gui/GuiController.java
@@ -14,6 +14,8 @@ import java.io.File;
14import java.io.FileReader; 14import java.io.FileReader;
15import java.io.FileWriter; 15import java.io.FileWriter;
16import java.io.IOException; 16import java.io.IOException;
17import java.util.ArrayList;
18import java.util.List;
17 19
18import cuchaz.enigma.ClassFile; 20import cuchaz.enigma.ClassFile;
19import cuchaz.enigma.Deobfuscator; 21import cuchaz.enigma.Deobfuscator;
@@ -45,7 +47,7 @@ public class GuiController
45 { 47 {
46 m_deobfuscator = new Deobfuscator( file ); 48 m_deobfuscator = new Deobfuscator( file );
47 m_gui.onOpenJar( m_deobfuscator.getJarName() ); 49 m_gui.onOpenJar( m_deobfuscator.getJarName() );
48 m_gui.setObfClasses( m_deobfuscator.getObfuscatedClasses() ); 50 refreshClasses();
49 } 51 }
50 52
51 public void closeJar( ) 53 public void closeJar( )
@@ -60,8 +62,8 @@ public class GuiController
60 FileReader in = new FileReader( file ); 62 FileReader in = new FileReader( file );
61 m_deobfuscator.setMappings( new MappingsReader().read( in ) ); 63 m_deobfuscator.setMappings( new MappingsReader().read( in ) );
62 in.close(); 64 in.close();
63 // TEMP 65 m_gui.setMappingsLoaded( true );
64 System.out.println( m_deobfuscator.getMappings() ); 66 refreshClasses();
65 refreshOpenFiles(); 67 refreshOpenFiles();
66 } 68 }
67 69
@@ -76,6 +78,7 @@ public class GuiController
76 public void closeMappings( ) 78 public void closeMappings( )
77 { 79 {
78 m_deobfuscator.setMappings( null ); 80 m_deobfuscator.setMappings( null );
81 m_gui.setMappingsLoaded( false );
79 refreshOpenFiles(); 82 refreshOpenFiles();
80 } 83 }
81 84
@@ -119,6 +122,15 @@ public class GuiController
119 refreshOpenFiles(); 122 refreshOpenFiles();
120 } 123 }
121 124
125 private void refreshClasses( )
126 {
127 List<ClassFile> obfClasses = new ArrayList<ClassFile>();
128 List<ClassFile> deobfClasses = new ArrayList<ClassFile>();
129 m_deobfuscator.getSortedClasses( obfClasses, deobfClasses );
130 m_gui.setObfClasses( obfClasses );
131 m_gui.setDeobfClasses( deobfClasses );
132 }
133
122 private void refreshOpenFiles( ) 134 private void refreshOpenFiles( )
123 { 135 {
124 if( m_currentFile != null ) 136 if( m_currentFile != null )
diff --git a/src/cuchaz/enigma/mapping/NameValidator.java b/src/cuchaz/enigma/mapping/NameValidator.java
new file mode 100644
index 0000000..30982dc
--- /dev/null
+++ b/src/cuchaz/enigma/mapping/NameValidator.java
@@ -0,0 +1,67 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.mapping;
12
13import java.util.regex.Pattern;
14
15public class NameValidator
16{
17 private static final String IdentifierPattern;
18 private static final Pattern ClassPattern;
19
20 static
21 {
22 // java allows all kinds of weird characters...
23 StringBuilder startChars = new StringBuilder();
24 StringBuilder partChars = new StringBuilder();
25 for( int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++ )
26 {
27 if( Character.isJavaIdentifierStart( i ) )
28 {
29 startChars.appendCodePoint( i );
30 }
31 if( Character.isJavaIdentifierPart( i ) )
32 {
33 partChars.appendCodePoint( i );
34 }
35 }
36
37 IdentifierPattern = String.format( "[\\Q%s\\E][\\Q%s\\E]*", startChars.toString(), partChars.toString() );
38 ClassPattern = Pattern.compile( String.format( "^(%s(\\.|/))*(%s)$", IdentifierPattern, IdentifierPattern ) );
39 }
40
41 public String validateClassName( String name )
42 {
43 if( !ClassPattern.matcher( name ).matches() )
44 {
45 throw new IllegalArgumentException( "Illegal name: " + name );
46 }
47
48 return classNameToJavaName( name );
49 }
50
51 public static String fileNameToClassName( String fileName )
52 {
53 final String suffix = ".class";
54
55 if( !fileName.endsWith( suffix ) )
56 {
57 return null;
58 }
59
60 return fileName.substring( 0, fileName.length() - suffix.length() ).replace( "/", "." );
61 }
62
63 public static String classNameToJavaName( String className )
64 {
65 return className.replace( ".", "/" );
66 }
67}