diff options
| author | 2014-08-23 16:20:15 -0400 | |
|---|---|---|
| committer | 2014-08-23 16:20:15 -0400 | |
| commit | a700b403d790c23989da524c934f0185b87c7b32 (patch) | |
| tree | 10a6b279927efea8cbfd12288edd6ad06f046eb2 /src/cuchaz | |
| parent | Added tag v0.3 beta for changeset d90963ed6887 (diff) | |
| download | enigma-a700b403d790c23989da524c934f0185b87c7b32.tar.gz enigma-a700b403d790c23989da524c934f0185b87c7b32.tar.xz enigma-a700b403d790c23989da524c934f0185b87c7b32.zip | |
added export command with progress bar
Diffstat (limited to 'src/cuchaz')
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 78 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 38 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 26 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiTricks.java | 25 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/ProgressDialog.java | 89 |
5 files changed, 233 insertions, 23 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index 38f7af56..5d87ad0a 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | package cuchaz.enigma; | 11 | package cuchaz.enigma; |
| 12 | 12 | ||
| 13 | import java.io.File; | 13 | import java.io.File; |
| 14 | import java.io.FileWriter; | ||
| 14 | import java.io.IOException; | 15 | import java.io.IOException; |
| 15 | import java.io.StringWriter; | 16 | import java.io.StringWriter; |
| 16 | import java.util.List; | 17 | import java.util.List; |
| @@ -44,6 +45,12 @@ import cuchaz.enigma.mapping.Translator; | |||
| 44 | 45 | ||
| 45 | public class Deobfuscator | 46 | public class Deobfuscator |
| 46 | { | 47 | { |
| 48 | public interface ProgressListener | ||
| 49 | { | ||
| 50 | void init( int totalWork ); | ||
| 51 | void onProgress( int numDone, String message ); | ||
| 52 | } | ||
| 53 | |||
| 47 | private File m_file; | 54 | private File m_file; |
| 48 | private JarFile m_jar; | 55 | private JarFile m_jar; |
| 49 | private DecompilerSettings m_settings; | 56 | private DecompilerSettings m_settings; |
| @@ -137,7 +144,7 @@ public class Deobfuscator | |||
| 137 | } | 144 | } |
| 138 | } | 145 | } |
| 139 | 146 | ||
| 140 | public SourceIndex getSource( String className ) | 147 | public CompilationUnit getSourceTree( String className ) |
| 141 | { | 148 | { |
| 142 | // is this class deobfuscated? | 149 | // is this class deobfuscated? |
| 143 | // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out | 150 | // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out |
| @@ -156,19 +163,18 @@ public class Deobfuscator | |||
| 156 | AstBuilder builder = new AstBuilder( context ); | 163 | AstBuilder builder = new AstBuilder( context ); |
| 157 | builder.addType( resolvedType ); | 164 | builder.addType( resolvedType ); |
| 158 | builder.runTransformations( null ); | 165 | builder.runTransformations( null ); |
| 159 | CompilationUnit root = builder.getCompilationUnit(); | 166 | return builder.getCompilationUnit(); |
| 167 | } | ||
| 168 | |||
| 169 | public SourceIndex getSourceIndex( CompilationUnit sourceTree, String source ) | ||
| 170 | { | ||
| 171 | // build the source index | ||
| 172 | SourceIndex index = new SourceIndex( source ); | ||
| 173 | sourceTree.acceptVisitor( new SourceIndexVisitor(), index ); | ||
| 160 | 174 | ||
| 161 | // render the AST into source | ||
| 162 | StringWriter buf = new StringWriter(); | ||
| 163 | root.acceptVisitor( new InsertParenthesesVisitor(), null ); | ||
| 164 | // DEBUG | 175 | // DEBUG |
| 165 | //root.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); | 176 | //root.acceptVisitor( new TreeDumpVisitor( new File( "tree.txt" ) ), null ); |
| 166 | root.acceptVisitor( new JavaOutputVisitor( new PlainTextOutput( buf ), m_settings ), null ); | 177 | |
| 167 | |||
| 168 | // build the source index | ||
| 169 | SourceIndex index = new SourceIndex( buf.toString() ); | ||
| 170 | root.acceptVisitor( new SourceIndexVisitor(), index ); | ||
| 171 | |||
| 172 | /* DEBUG | 178 | /* DEBUG |
| 173 | for( Token token : index.referenceTokens() ) | 179 | for( Token token : index.referenceTokens() ) |
| 174 | { | 180 | { |
| @@ -180,6 +186,56 @@ public class Deobfuscator | |||
| 180 | return index; | 186 | return index; |
| 181 | } | 187 | } |
| 182 | 188 | ||
| 189 | public String getSource( CompilationUnit sourceTree ) | ||
| 190 | { | ||
| 191 | // render the AST into source | ||
| 192 | StringWriter buf = new StringWriter(); | ||
| 193 | sourceTree.acceptVisitor( new InsertParenthesesVisitor(), null ); | ||
| 194 | sourceTree.acceptVisitor( new JavaOutputVisitor( new PlainTextOutput( buf ), m_settings ), null ); | ||
| 195 | return buf.toString(); | ||
| 196 | } | ||
| 197 | |||
| 198 | public void writeSources( File dirOut, ProgressListener progress ) | ||
| 199 | throws IOException | ||
| 200 | { | ||
| 201 | int numClasses = m_jarIndex.getObfClassNames().size(); | ||
| 202 | if( progress != null ) | ||
| 203 | { | ||
| 204 | progress.init( numClasses ); | ||
| 205 | } | ||
| 206 | int i = 0; | ||
| 207 | |||
| 208 | // DEOBFUSCATE ALL THE THINGS!! @_@ | ||
| 209 | for( String obfClassName : m_jarIndex.getObfClassNames() ) | ||
| 210 | { | ||
| 211 | // skip inner classes | ||
| 212 | if( m_jarIndex.getOuterClass( obfClassName ) != null ) | ||
| 213 | { | ||
| 214 | continue; | ||
| 215 | } | ||
| 216 | |||
| 217 | ClassEntry deobfClassEntry = deobfuscateEntry( new ClassEntry( obfClassName ) ); | ||
| 218 | if( progress != null ) | ||
| 219 | { | ||
| 220 | progress.onProgress( i++, deobfClassEntry.toString() ); | ||
| 221 | } | ||
| 222 | |||
| 223 | // get the source | ||
| 224 | String source = getSource( getSourceTree( obfClassName ) ); | ||
| 225 | |||
| 226 | // write the file | ||
| 227 | File file = new File( dirOut, deobfClassEntry.getName().replace( '.', '/' ) + ".java" ); | ||
| 228 | file.getParentFile().mkdirs(); | ||
| 229 | try( FileWriter out = new FileWriter( file ) ) | ||
| 230 | { | ||
| 231 | out.write( source ); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | // done! | ||
| 236 | progress.onProgress( numClasses, "Done!" ); | ||
| 237 | } | ||
| 238 | |||
| 183 | public <T extends Entry> T obfuscateEntry( T deobfEntry ) | 239 | public <T extends Entry> T obfuscateEntry( T deobfEntry ) |
| 184 | { | 240 | { |
| 185 | if( deobfEntry == null ) | 241 | if( deobfEntry == null ) |
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index dd82b8e0..febdfd43 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -15,7 +15,6 @@ import java.awt.Color; | |||
| 15 | import java.awt.Container; | 15 | import java.awt.Container; |
| 16 | import java.awt.Dimension; | 16 | import java.awt.Dimension; |
| 17 | import java.awt.FlowLayout; | 17 | import java.awt.FlowLayout; |
| 18 | import java.awt.Font; | ||
| 19 | import java.awt.GridLayout; | 18 | import java.awt.GridLayout; |
| 20 | import java.awt.Rectangle; | 19 | import java.awt.Rectangle; |
| 21 | import java.awt.event.ActionEvent; | 20 | import java.awt.event.ActionEvent; |
| @@ -169,6 +168,7 @@ public class Gui | |||
| 169 | private EntryReference<Entry,Entry> m_reference; | 168 | private EntryReference<Entry,Entry> m_reference; |
| 170 | private JFileChooser m_jarFileChooser; | 169 | private JFileChooser m_jarFileChooser; |
| 171 | private JFileChooser m_mappingsFileChooser; | 170 | private JFileChooser m_mappingsFileChooser; |
| 171 | private JFileChooser m_exportFileChooser; | ||
| 172 | 172 | ||
| 173 | public Gui( ) | 173 | public Gui( ) |
| 174 | { | 174 | { |
| @@ -177,6 +177,8 @@ public class Gui | |||
| 177 | // init file choosers | 177 | // init file choosers |
| 178 | m_jarFileChooser = new JFileChooser(); | 178 | m_jarFileChooser = new JFileChooser(); |
| 179 | m_mappingsFileChooser = new JFileChooser(); | 179 | m_mappingsFileChooser = new JFileChooser(); |
| 180 | m_exportFileChooser = new JFileChooser(); | ||
| 181 | m_exportFileChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY ); | ||
| 180 | 182 | ||
| 181 | // init frame | 183 | // init frame |
| 182 | m_frame = new JFrame( Constants.Name ); | 184 | m_frame = new JFrame( Constants.Name ); |
| @@ -637,6 +639,22 @@ public class Gui | |||
| 637 | } | 639 | } |
| 638 | menu.addSeparator(); | 640 | menu.addSeparator(); |
| 639 | { | 641 | { |
| 642 | JMenuItem item = new JMenuItem( "Export..." ); | ||
| 643 | menu.add( item ); | ||
| 644 | item.addActionListener( new ActionListener( ) | ||
| 645 | { | ||
| 646 | @Override | ||
| 647 | public void actionPerformed( ActionEvent event ) | ||
| 648 | { | ||
| 649 | if( m_exportFileChooser.showSaveDialog( m_frame ) == JFileChooser.APPROVE_OPTION ) | ||
| 650 | { | ||
| 651 | m_controller.export( m_exportFileChooser.getSelectedFile() ); | ||
| 652 | } | ||
| 653 | } | ||
| 654 | } ); | ||
| 655 | } | ||
| 656 | menu.addSeparator(); | ||
| 657 | { | ||
| 640 | JMenuItem item = new JMenuItem( "Exit" ); | 658 | JMenuItem item = new JMenuItem( "Exit" ); |
| 641 | menu.add( item ); | 659 | menu.add( item ); |
| 642 | item.addActionListener( new ActionListener( ) | 660 | item.addActionListener( new ActionListener( ) |
| @@ -686,6 +704,11 @@ public class Gui | |||
| 686 | m_frame.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); | 704 | m_frame.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); |
| 687 | } | 705 | } |
| 688 | 706 | ||
| 707 | public JFrame getFrame( ) | ||
| 708 | { | ||
| 709 | return m_frame; | ||
| 710 | } | ||
| 711 | |||
| 689 | public GuiController getController( ) | 712 | public GuiController getController( ) |
| 690 | { | 713 | { |
| 691 | return m_controller; | 714 | return m_controller; |
| @@ -887,7 +910,7 @@ public class Gui | |||
| 887 | { | 910 | { |
| 888 | m_infoPanel.removeAll(); | 911 | m_infoPanel.removeAll(); |
| 889 | JLabel label = new JLabel( "No identifier selected" ); | 912 | JLabel label = new JLabel( "No identifier selected" ); |
| 890 | unboldLabel( label ); | 913 | GuiTricks.unboldLabel( label ); |
| 891 | label.setHorizontalAlignment( JLabel.CENTER ); | 914 | label.setHorizontalAlignment( JLabel.CENTER ); |
| 892 | m_infoPanel.add( label ); | 915 | m_infoPanel.add( label ); |
| 893 | 916 | ||
| @@ -975,7 +998,7 @@ public class Gui | |||
| 975 | label.setPreferredSize( new Dimension( 100, label.getPreferredSize().height ) ); | 998 | label.setPreferredSize( new Dimension( 100, label.getPreferredSize().height ) ); |
| 976 | panel.add( label ); | 999 | panel.add( label ); |
| 977 | 1000 | ||
| 978 | panel.add( unboldLabel( new JLabel( value, JLabel.LEFT ) ) ); | 1001 | panel.add( GuiTricks.unboldLabel( new JLabel( value, JLabel.LEFT ) ) ); |
| 979 | } | 1002 | } |
| 980 | 1003 | ||
| 981 | private void onCaretMove( int pos ) | 1004 | private void onCaretMove( int pos ) |
| @@ -1059,7 +1082,7 @@ public class Gui | |||
| 1059 | // abort the rename | 1082 | // abort the rename |
| 1060 | JPanel panel = (JPanel)m_infoPanel.getComponent( 0 ); | 1083 | JPanel panel = (JPanel)m_infoPanel.getComponent( 0 ); |
| 1061 | panel.remove( panel.getComponentCount() - 1 ); | 1084 | panel.remove( panel.getComponentCount() - 1 ); |
| 1062 | panel.add( unboldLabel( new JLabel( m_reference.entry.getName(), JLabel.LEFT ) ) ); | 1085 | panel.add( GuiTricks.unboldLabel( new JLabel( m_reference.entry.getName(), JLabel.LEFT ) ) ); |
| 1063 | 1086 | ||
| 1064 | m_editor.grabFocus(); | 1087 | m_editor.grabFocus(); |
| 1065 | 1088 | ||
| @@ -1203,13 +1226,6 @@ public class Gui | |||
| 1203 | } | 1226 | } |
| 1204 | } | 1227 | } |
| 1205 | 1228 | ||
| 1206 | private JLabel unboldLabel( JLabel label ) | ||
| 1207 | { | ||
| 1208 | Font font = label.getFont(); | ||
| 1209 | label.setFont( font.deriveFont( font.getStyle() & ~Font.BOLD ) ); | ||
| 1210 | return label; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | private void redraw( ) | 1229 | private void redraw( ) |
| 1214 | { | 1230 | { |
| 1215 | m_frame.validate(); | 1231 | m_frame.validate(); |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index a35db056..cf4f002e 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -20,6 +20,7 @@ import java.util.List; | |||
| 20 | 20 | ||
| 21 | import com.google.common.collect.Lists; | 21 | import com.google.common.collect.Lists; |
| 22 | import com.google.common.collect.Queues; | 22 | import com.google.common.collect.Queues; |
| 23 | import com.strobel.decompiler.languages.java.ast.CompilationUnit; | ||
| 23 | 24 | ||
| 24 | import cuchaz.enigma.Deobfuscator; | 25 | import cuchaz.enigma.Deobfuscator; |
| 25 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; | 26 | import cuchaz.enigma.analysis.BehaviorReferenceTreeNode; |
| @@ -106,6 +107,27 @@ public class GuiController | |||
| 106 | refreshCurrentClass(); | 107 | refreshCurrentClass(); |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 110 | public void export( final File dirOut ) | ||
| 111 | { | ||
| 112 | new Thread( ) | ||
| 113 | { | ||
| 114 | @Override | ||
| 115 | public void run( ) | ||
| 116 | { | ||
| 117 | try | ||
| 118 | { | ||
| 119 | ProgressDialog progress = new ProgressDialog( m_gui.getFrame() ); | ||
| 120 | m_deobfuscator.writeSources( dirOut, progress ); | ||
| 121 | progress.close(); | ||
| 122 | } | ||
| 123 | catch( IOException ex ) | ||
| 124 | { | ||
| 125 | throw new Error( ex ); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | }.start(); | ||
| 129 | } | ||
| 130 | |||
| 109 | public Token getToken( int pos ) | 131 | public Token getToken( int pos ) |
| 110 | { | 132 | { |
| 111 | if( m_index == null ) | 133 | if( m_index == null ) |
| @@ -295,7 +317,9 @@ public class GuiController | |||
| 295 | public void run( ) | 317 | public void run( ) |
| 296 | { | 318 | { |
| 297 | // decompile,deobfuscate the bytecode | 319 | // decompile,deobfuscate the bytecode |
| 298 | m_index = m_deobfuscator.getSource( classEntry.getClassName() ); | 320 | CompilationUnit sourceTree = m_deobfuscator.getSourceTree( classEntry.getClassName() ); |
| 321 | String source = m_deobfuscator.getSource( sourceTree ); | ||
| 322 | m_index = m_deobfuscator.getSourceIndex( sourceTree, source ); | ||
| 299 | m_gui.setSource( m_index.getSource() ); | 323 | m_gui.setSource( m_index.getSource() ); |
| 300 | if( obfReference != null ) | 324 | if( obfReference != null ) |
| 301 | { | 325 | { |
diff --git a/src/cuchaz/enigma/gui/GuiTricks.java b/src/cuchaz/enigma/gui/GuiTricks.java new file mode 100644 index 00000000..c79f4329 --- /dev/null +++ b/src/cuchaz/enigma/gui/GuiTricks.java | |||
| @@ -0,0 +1,25 @@ | |||
| 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 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.gui; | ||
| 12 | |||
| 13 | import java.awt.Font; | ||
| 14 | |||
| 15 | import javax.swing.JLabel; | ||
| 16 | |||
| 17 | public class GuiTricks | ||
| 18 | { | ||
| 19 | public static JLabel unboldLabel( JLabel label ) | ||
| 20 | { | ||
| 21 | Font font = label.getFont(); | ||
| 22 | label.setFont( font.deriveFont( font.getStyle() & ~Font.BOLD ) ); | ||
| 23 | return label; | ||
| 24 | } | ||
| 25 | } | ||
diff --git a/src/cuchaz/enigma/gui/ProgressDialog.java b/src/cuchaz/enigma/gui/ProgressDialog.java new file mode 100644 index 00000000..40ac6a69 --- /dev/null +++ b/src/cuchaz/enigma/gui/ProgressDialog.java | |||
| @@ -0,0 +1,89 @@ | |||
| 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 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.gui; | ||
| 12 | |||
| 13 | import java.awt.BorderLayout; | ||
| 14 | import java.awt.Container; | ||
| 15 | import java.awt.Dimension; | ||
| 16 | import java.awt.FlowLayout; | ||
| 17 | |||
| 18 | import javax.swing.BorderFactory; | ||
| 19 | import javax.swing.JFrame; | ||
| 20 | import javax.swing.JLabel; | ||
| 21 | import javax.swing.JPanel; | ||
| 22 | import javax.swing.JProgressBar; | ||
| 23 | import javax.swing.WindowConstants; | ||
| 24 | |||
| 25 | import cuchaz.enigma.Constants; | ||
| 26 | import cuchaz.enigma.Deobfuscator.ProgressListener; | ||
| 27 | |||
| 28 | public class ProgressDialog implements ProgressListener | ||
| 29 | { | ||
| 30 | private JFrame m_frame; | ||
| 31 | private JLabel m_text; | ||
| 32 | private JProgressBar m_progress; | ||
| 33 | |||
| 34 | public ProgressDialog( JFrame parent ) | ||
| 35 | { | ||
| 36 | // init frame | ||
| 37 | m_frame = new JFrame( Constants.Name + " - Export" ); | ||
| 38 | final Container pane = m_frame.getContentPane(); | ||
| 39 | FlowLayout layout = new FlowLayout(); | ||
| 40 | layout.setAlignment( FlowLayout.LEFT ); | ||
| 41 | pane.setLayout( layout ); | ||
| 42 | |||
| 43 | pane.add( new JLabel( "Decompiling classes..." ) ); | ||
| 44 | |||
| 45 | // set up the progress bar | ||
| 46 | JPanel panel = new JPanel(); | ||
| 47 | pane.add( panel ); | ||
| 48 | panel.setLayout( new BorderLayout() ); | ||
| 49 | m_text = GuiTricks.unboldLabel( new JLabel() ); | ||
| 50 | m_progress = new JProgressBar(); | ||
| 51 | m_text.setBorder( BorderFactory.createEmptyBorder( 0, 0, 10, 0 ) ); | ||
| 52 | panel.add( m_text, BorderLayout.NORTH ); | ||
| 53 | panel.add( m_progress, BorderLayout.CENTER ); | ||
| 54 | panel.setPreferredSize( new Dimension( 360, 50 ) ); | ||
| 55 | |||
| 56 | // show the frame | ||
| 57 | pane.doLayout(); | ||
| 58 | m_frame.setSize( 400, 120 ); | ||
| 59 | m_frame.setResizable( false ); | ||
| 60 | m_frame.setLocationRelativeTo( parent ); | ||
| 61 | m_frame.setVisible( true ); | ||
| 62 | m_frame.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); | ||
| 63 | } | ||
| 64 | |||
| 65 | public void close( ) | ||
| 66 | { | ||
| 67 | m_frame.dispose(); | ||
| 68 | } | ||
| 69 | |||
| 70 | @Override | ||
| 71 | public void init( int totalWork ) | ||
| 72 | { | ||
| 73 | m_text.setText( "Decompiling " + totalWork + " classes..." ); | ||
| 74 | m_progress.setMinimum( 0 ); | ||
| 75 | m_progress.setMaximum( totalWork ); | ||
| 76 | m_progress.setValue( 0 ); | ||
| 77 | } | ||
| 78 | |||
| 79 | @Override | ||
| 80 | public void onProgress( int numDone, String message ) | ||
| 81 | { | ||
| 82 | m_text.setText( message ); | ||
| 83 | m_progress.setValue( numDone ); | ||
| 84 | |||
| 85 | // update the frame | ||
| 86 | m_frame.validate(); | ||
| 87 | m_frame.repaint(); | ||
| 88 | } | ||
| 89 | } | ||