diff options
| author | 2014-08-21 01:10:37 -0400 | |
|---|---|---|
| committer | 2014-08-21 01:10:37 -0400 | |
| commit | 237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375 (patch) | |
| tree | ebad059c7fa0bc7723858cb25eed0bb6e95fe42a /src/cuchaz/enigma/gui | |
| parent | fixed recognition of inner class tokens (diff) | |
| download | enigma-fork-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.tar.gz enigma-fork-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.tar.xz enigma-fork-237b2ed2a6b6f537cdbdf9fc9c6d0c7743f34375.zip | |
fixed call graph searching
added system to navigate multiple tokens for the same entry in a behavior
Diffstat (limited to 'src/cuchaz/enigma/gui')
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 53 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 75 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/ReadableToken.java | 38 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/TokenListCellRenderer.java | 40 |
4 files changed, 167 insertions, 39 deletions
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 341c149..a5471a7 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java | |||
| @@ -28,6 +28,7 @@ import java.awt.event.WindowAdapter; | |||
| 28 | import java.awt.event.WindowEvent; | 28 | import java.awt.event.WindowEvent; |
| 29 | import java.io.File; | 29 | import java.io.File; |
| 30 | import java.io.IOException; | 30 | import java.io.IOException; |
| 31 | import java.util.Collection; | ||
| 31 | import java.util.Collections; | 32 | import java.util.Collections; |
| 32 | import java.util.Comparator; | 33 | import java.util.Comparator; |
| 33 | import java.util.List; | 34 | import java.util.List; |
| @@ -145,6 +146,7 @@ public class Gui | |||
| 145 | private BoxHighlightPainter m_deobfuscatedHighlightPainter; | 146 | private BoxHighlightPainter m_deobfuscatedHighlightPainter; |
| 146 | private JTree m_inheritanceTree; | 147 | private JTree m_inheritanceTree; |
| 147 | private JTree m_callsTree; | 148 | private JTree m_callsTree; |
| 149 | private JList<Token> m_tokens; | ||
| 148 | private JTabbedPane m_tabs; | 150 | private JTabbedPane m_tabs; |
| 149 | 151 | ||
| 150 | // dynamic menu items | 152 | // dynamic menu items |
| @@ -457,9 +459,29 @@ public class Gui | |||
| 457 | } | 459 | } |
| 458 | } | 460 | } |
| 459 | } ); | 461 | } ); |
| 460 | JPanel callPanel = new JPanel(); | 462 | m_tokens = new JList<Token>(); |
| 461 | callPanel.setLayout( new BorderLayout() ); | 463 | m_tokens.setCellRenderer( new TokenListCellRenderer( m_controller ) ); |
| 462 | callPanel.add( new JScrollPane( m_callsTree ) ); | 464 | m_tokens.setSelectionMode( ListSelectionModel.SINGLE_SELECTION ); |
| 465 | m_tokens.setLayoutOrientation( JList.VERTICAL ); | ||
| 466 | m_tokens.addMouseListener( new MouseAdapter() | ||
| 467 | { | ||
| 468 | @Override | ||
| 469 | public void mouseClicked( MouseEvent event ) | ||
| 470 | { | ||
| 471 | if( event.getClickCount() == 2 ) | ||
| 472 | { | ||
| 473 | Token selected = m_tokens.getSelectedValue(); | ||
| 474 | if( selected != null ) | ||
| 475 | { | ||
| 476 | showToken( selected ); | ||
| 477 | } | ||
| 478 | } | ||
| 479 | } | ||
| 480 | } ); | ||
| 481 | m_tokens.setPreferredSize( new Dimension( 0, 200 ) ); | ||
| 482 | JSplitPane callPanel = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, new JScrollPane( m_callsTree ), new JScrollPane( m_tokens ) ); | ||
| 483 | callPanel.setResizeWeight( 1 ); // let the top side take all the slack | ||
| 484 | callPanel.resetToPreferredSizes(); | ||
| 463 | 485 | ||
| 464 | // layout controls | 486 | // layout controls |
| 465 | JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); | 487 | JSplitPane splitLeft = new JSplitPane( JSplitPane.VERTICAL_SPLIT, true, obfPanel, deobfPanel ); |
| @@ -743,6 +765,21 @@ public class Gui | |||
| 743 | m_editor.grabFocus(); | 765 | m_editor.grabFocus(); |
| 744 | } | 766 | } |
| 745 | 767 | ||
| 768 | public void showTokens( Collection<Token> tokens ) | ||
| 769 | { | ||
| 770 | Vector<Token> sortedTokens = new Vector<Token>( tokens ); | ||
| 771 | Collections.sort( sortedTokens ); | ||
| 772 | if( sortedTokens.size() > 1 ) | ||
| 773 | { | ||
| 774 | // sort the tokens and update the tokens panel | ||
| 775 | m_tokens.setListData( sortedTokens ); | ||
| 776 | m_tokens.setSelectedIndex( 0 ); | ||
| 777 | } | ||
| 778 | |||
| 779 | // show the first token | ||
| 780 | showToken( sortedTokens.get( 0 ) ); | ||
| 781 | } | ||
| 782 | |||
| 746 | public void setHighlightedTokens( Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens ) | 783 | public void setHighlightedTokens( Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens ) |
| 747 | { | 784 | { |
| 748 | // remove any old highlighters | 785 | // remove any old highlighters |
| @@ -900,17 +937,9 @@ public class Gui | |||
| 900 | 937 | ||
| 901 | private void startRename( ) | 938 | private void startRename( ) |
| 902 | { | 939 | { |
| 903 | // get the class name | ||
| 904 | ClassEntry classEntry = m_reference.entry.getClassEntry(); | ||
| 905 | String className = classEntry.getName(); | ||
| 906 | if( classEntry.isInnerClass() ) | ||
| 907 | { | ||
| 908 | className = classEntry.getInnerClassName(); | ||
| 909 | } | ||
| 910 | |||
| 911 | // init the text box | 940 | // init the text box |
| 912 | final JTextField text = new JTextField(); | 941 | final JTextField text = new JTextField(); |
| 913 | text.setText( className ); | 942 | text.setText( m_reference.entry.getName() ); |
| 914 | text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); | 943 | text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); |
| 915 | text.addKeyListener( new KeyAdapter( ) | 944 | text.addKeyListener( new KeyAdapter( ) |
| 916 | { | 945 | { |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index dfa2557..a35db05 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -14,6 +14,7 @@ import java.io.File; | |||
| 14 | import java.io.FileReader; | 14 | import java.io.FileReader; |
| 15 | import java.io.FileWriter; | 15 | import java.io.FileWriter; |
| 16 | import java.io.IOException; | 16 | import java.io.IOException; |
| 17 | import java.util.Collection; | ||
| 17 | import java.util.Deque; | 18 | import java.util.Deque; |
| 18 | import java.util.List; | 19 | import java.util.List; |
| 19 | 20 | ||
| @@ -45,7 +46,7 @@ public class GuiController | |||
| 45 | private SourceIndex m_index; | 46 | private SourceIndex m_index; |
| 46 | private ClassEntry m_currentObfClass; | 47 | private ClassEntry m_currentObfClass; |
| 47 | private boolean m_isDirty; | 48 | private boolean m_isDirty; |
| 48 | private Deque<EntryReference<Entry,Entry>> m_referenceStack; // TODO: make a location class, can be either Entry or EntryReference | 49 | private Deque<EntryReference<Entry,Entry>> m_referenceStack; |
| 49 | 50 | ||
| 50 | public GuiController( Gui gui ) | 51 | public GuiController( Gui gui ) |
| 51 | { | 52 | { |
| @@ -111,7 +112,6 @@ public class GuiController | |||
| 111 | { | 112 | { |
| 112 | return null; | 113 | return null; |
| 113 | } | 114 | } |
| 114 | |||
| 115 | return m_index.getReferenceToken( pos ); | 115 | return m_index.getReferenceToken( pos ); |
| 116 | } | 116 | } |
| 117 | 117 | ||
| @@ -124,6 +124,19 @@ public class GuiController | |||
| 124 | return m_index.getDeobfReference( token ); | 124 | return m_index.getDeobfReference( token ); |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | public ReadableToken getReadableToken( Token token ) | ||
| 128 | { | ||
| 129 | if( m_index == null ) | ||
| 130 | { | ||
| 131 | return null; | ||
| 132 | } | ||
| 133 | return new ReadableToken( | ||
| 134 | m_index.getLineNumber( token.start ), | ||
| 135 | m_index.getColumnNumber( token.start ), | ||
| 136 | m_index.getColumnNumber( token.end ) | ||
| 137 | ); | ||
| 138 | } | ||
| 139 | |||
| 127 | public boolean entryHasMapping( Entry deobfEntry ) | 140 | public boolean entryHasMapping( Entry deobfEntry ) |
| 128 | { | 141 | { |
| 129 | return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); | 142 | return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); |
| @@ -134,8 +147,9 @@ public class GuiController | |||
| 134 | return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); | 147 | return m_deobfuscator.isObfuscatedIdentifier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); |
| 135 | } | 148 | } |
| 136 | 149 | ||
| 137 | public ClassInheritanceTreeNode getClassInheritance( ClassEntry obfClassEntry ) | 150 | public ClassInheritanceTreeNode getClassInheritance( ClassEntry deobfClassEntry ) |
| 138 | { | 151 | { |
| 152 | ClassEntry obfClassEntry = m_deobfuscator.obfuscateEntry( deobfClassEntry ); | ||
| 139 | ClassInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getClassInheritance( | 153 | ClassInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getClassInheritance( |
| 140 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | 154 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), |
| 141 | obfClassEntry | 155 | obfClassEntry |
| @@ -143,8 +157,9 @@ public class GuiController | |||
| 143 | return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); | 157 | return ClassInheritanceTreeNode.findNode( rootNode, obfClassEntry ); |
| 144 | } | 158 | } |
| 145 | 159 | ||
| 146 | public MethodInheritanceTreeNode getMethodInheritance( MethodEntry obfMethodEntry ) | 160 | public MethodInheritanceTreeNode getMethodInheritance( MethodEntry deobfMethodEntry ) |
| 147 | { | 161 | { |
| 162 | MethodEntry obfMethodEntry = m_deobfuscator.obfuscateEntry( deobfMethodEntry ); | ||
| 148 | MethodInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodInheritance( | 163 | MethodInheritanceTreeNode rootNode = m_deobfuscator.getJarIndex().getMethodInheritance( |
| 149 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | 164 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), |
| 150 | obfMethodEntry | 165 | obfMethodEntry |
| @@ -152,8 +167,9 @@ public class GuiController | |||
| 152 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); | 167 | return MethodInheritanceTreeNode.findNode( rootNode, obfMethodEntry ); |
| 153 | } | 168 | } |
| 154 | 169 | ||
| 155 | public FieldReferenceTreeNode getFieldReferences( FieldEntry obfFieldEntry ) | 170 | public FieldReferenceTreeNode getFieldReferences( FieldEntry deobfFieldEntry ) |
| 156 | { | 171 | { |
| 172 | FieldEntry obfFieldEntry = m_deobfuscator.obfuscateEntry( deobfFieldEntry ); | ||
| 157 | FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode( | 173 | FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode( |
| 158 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | 174 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), |
| 159 | obfFieldEntry | 175 | obfFieldEntry |
| @@ -162,11 +178,12 @@ public class GuiController | |||
| 162 | return rootNode; | 178 | return rootNode; |
| 163 | } | 179 | } |
| 164 | 180 | ||
| 165 | public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry obfEntry ) | 181 | public BehaviorReferenceTreeNode getMethodReferences( BehaviorEntry deobfBehaviorEntry ) |
| 166 | { | 182 | { |
| 183 | BehaviorEntry obfBehaviorEntry = m_deobfuscator.obfuscateEntry( deobfBehaviorEntry ); | ||
| 167 | BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode( | 184 | BehaviorReferenceTreeNode rootNode = new BehaviorReferenceTreeNode( |
| 168 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), | 185 | m_deobfuscator.getTranslator( TranslationDirection.Deobfuscating ), |
| 169 | obfEntry | 186 | obfBehaviorEntry |
| 170 | ); | 187 | ); |
| 171 | rootNode.load( m_deobfuscator.getJarIndex(), true ); | 188 | rootNode.load( m_deobfuscator.getJarIndex(), true ); |
| 172 | return rootNode; | 189 | return rootNode; |
| @@ -181,13 +198,13 @@ public class GuiController | |||
| 181 | refreshCurrentClass( obfReference ); | 198 | refreshCurrentClass( obfReference ); |
| 182 | } | 199 | } |
| 183 | 200 | ||
| 184 | public void openDeclaration( Entry entry ) | 201 | public void openDeclaration( Entry deobfEntry ) |
| 185 | { | 202 | { |
| 186 | if( entry == null ) | 203 | if( deobfEntry == null ) |
| 187 | { | 204 | { |
| 188 | throw new IllegalArgumentException( "Entry cannot be null!" ); | 205 | throw new IllegalArgumentException( "Entry cannot be null!" ); |
| 189 | } | 206 | } |
| 190 | openReference( new EntryReference<Entry,Entry>( entry ) ); | 207 | openReference( new EntryReference<Entry,Entry>( deobfEntry ) ); |
| 191 | } | 208 | } |
| 192 | 209 | ||
| 193 | public void openReference( EntryReference<Entry,Entry> deobfReference ) | 210 | public void openReference( EntryReference<Entry,Entry> deobfReference ) |
| @@ -208,8 +225,22 @@ public class GuiController | |||
| 208 | } | 225 | } |
| 209 | else | 226 | else |
| 210 | { | 227 | { |
| 211 | // the class file is already open, just navigate to the reference | 228 | showReference( obfReference ); |
| 212 | m_gui.showToken( m_index.getReferenceToken( deobfReference ) ); | 229 | } |
| 230 | } | ||
| 231 | |||
| 232 | private void showReference( EntryReference<Entry,Entry> obfReference ) | ||
| 233 | { | ||
| 234 | EntryReference<Entry,Entry> deobfReference = m_deobfuscator.deobfuscateReference( obfReference ); | ||
| 235 | Collection<Token> tokens = m_index.getReferenceTokens( deobfReference ); | ||
| 236 | if( tokens.isEmpty() ) | ||
| 237 | { | ||
| 238 | // DEBUG | ||
| 239 | System.err.println( String.format( "WARNING: no tokens found for %s in %s", deobfReference, m_currentObfClass ) ); | ||
| 240 | } | ||
| 241 | else | ||
| 242 | { | ||
| 243 | m_gui.showTokens( tokens ); | ||
| 213 | } | 244 | } |
| 214 | } | 245 | } |
| 215 | 246 | ||
| @@ -245,15 +276,15 @@ public class GuiController | |||
| 245 | refreshCurrentClass( null ); | 276 | refreshCurrentClass( null ); |
| 246 | } | 277 | } |
| 247 | 278 | ||
| 248 | private void refreshCurrentClass( EntryReference<Entry,Entry> obfReferenceToShow ) | 279 | private void refreshCurrentClass( EntryReference<Entry,Entry> obfReference ) |
| 249 | { | 280 | { |
| 250 | if( m_currentObfClass != null ) | 281 | if( m_currentObfClass != null ) |
| 251 | { | 282 | { |
| 252 | deobfuscate( m_currentObfClass, obfReferenceToShow ); | 283 | deobfuscate( m_currentObfClass, obfReference ); |
| 253 | } | 284 | } |
| 254 | } | 285 | } |
| 255 | 286 | ||
| 256 | private void deobfuscate( final ClassEntry classEntry, final EntryReference<Entry,Entry> obfReferenceToShow ) | 287 | private void deobfuscate( final ClassEntry classEntry, final EntryReference<Entry,Entry> obfReference ) |
| 257 | { | 288 | { |
| 258 | m_gui.setSource( "(deobfuscating...)" ); | 289 | m_gui.setSource( "(deobfuscating...)" ); |
| 259 | 290 | ||
| @@ -266,19 +297,9 @@ public class GuiController | |||
| 266 | // decompile,deobfuscate the bytecode | 297 | // decompile,deobfuscate the bytecode |
| 267 | m_index = m_deobfuscator.getSource( classEntry.getClassName() ); | 298 | m_index = m_deobfuscator.getSource( classEntry.getClassName() ); |
| 268 | m_gui.setSource( m_index.getSource() ); | 299 | m_gui.setSource( m_index.getSource() ); |
| 269 | if( obfReferenceToShow != null ) | 300 | if( obfReference != null ) |
| 270 | { | 301 | { |
| 271 | EntryReference<Entry,Entry> deobfReferenceToShow = m_deobfuscator.deobfuscateReference( obfReferenceToShow ); | 302 | showReference( obfReference ); |
| 272 | Token token = m_index.getReferenceToken( deobfReferenceToShow ); | ||
| 273 | if( token == null ) | ||
| 274 | { | ||
| 275 | // DEBUG | ||
| 276 | System.out.println( "WARNING: can't find token for " + obfReferenceToShow + " -> " + deobfReferenceToShow ); | ||
| 277 | } | ||
| 278 | else | ||
| 279 | { | ||
| 280 | m_gui.showToken( token ); | ||
| 281 | } | ||
| 282 | } | 303 | } |
| 283 | 304 | ||
| 284 | // set the highlighted tokens | 305 | // set the highlighted tokens |
diff --git a/src/cuchaz/enigma/gui/ReadableToken.java b/src/cuchaz/enigma/gui/ReadableToken.java new file mode 100644 index 0000000..3f43045 --- /dev/null +++ b/src/cuchaz/enigma/gui/ReadableToken.java | |||
| @@ -0,0 +1,38 @@ | |||
| 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 | public class ReadableToken | ||
| 14 | { | ||
| 15 | public int line; | ||
| 16 | public int startColumn; | ||
| 17 | public int endColumn; | ||
| 18 | |||
| 19 | public ReadableToken( int line, int startColumn, int endColumn ) | ||
| 20 | { | ||
| 21 | this.line = line; | ||
| 22 | this.startColumn = startColumn; | ||
| 23 | this.endColumn = endColumn; | ||
| 24 | } | ||
| 25 | |||
| 26 | @Override | ||
| 27 | public String toString( ) | ||
| 28 | { | ||
| 29 | StringBuilder buf = new StringBuilder(); | ||
| 30 | buf.append( "line " ); | ||
| 31 | buf.append( line ); | ||
| 32 | buf.append( " columns " ); | ||
| 33 | buf.append( startColumn ); | ||
| 34 | buf.append( "-" ); | ||
| 35 | buf.append( endColumn ); | ||
| 36 | return buf.toString(); | ||
| 37 | } | ||
| 38 | } | ||
diff --git a/src/cuchaz/enigma/gui/TokenListCellRenderer.java b/src/cuchaz/enigma/gui/TokenListCellRenderer.java new file mode 100644 index 0000000..9247c06 --- /dev/null +++ b/src/cuchaz/enigma/gui/TokenListCellRenderer.java | |||
| @@ -0,0 +1,40 @@ | |||
| 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.Component; | ||
| 14 | |||
| 15 | import javax.swing.DefaultListCellRenderer; | ||
| 16 | import javax.swing.JLabel; | ||
| 17 | import javax.swing.JList; | ||
| 18 | import javax.swing.ListCellRenderer; | ||
| 19 | |||
| 20 | import cuchaz.enigma.analysis.Token; | ||
| 21 | |||
| 22 | public class TokenListCellRenderer implements ListCellRenderer<Token> | ||
| 23 | { | ||
| 24 | private GuiController m_controller; | ||
| 25 | private DefaultListCellRenderer m_defaultRenderer; | ||
| 26 | |||
| 27 | public TokenListCellRenderer( GuiController controller ) | ||
| 28 | { | ||
| 29 | m_controller = controller; | ||
| 30 | m_defaultRenderer = new DefaultListCellRenderer(); | ||
| 31 | } | ||
| 32 | |||
| 33 | @Override | ||
| 34 | public Component getListCellRendererComponent( JList<? extends Token> list, Token token, int index, boolean isSelected, boolean hasFocus ) | ||
| 35 | { | ||
| 36 | JLabel label = (JLabel)m_defaultRenderer.getListCellRendererComponent( list, token, index, isSelected, hasFocus ); | ||
| 37 | label.setText( m_controller.getReadableToken( token ).toString() ); | ||
| 38 | return label; | ||
| 39 | } | ||
| 40 | } | ||