summaryrefslogtreecommitdiff
path: root/src/cuchaz
diff options
context:
space:
mode:
authorGravatar jeff2014-09-30 00:25:36 -0400
committerGravatar jeff2014-09-30 00:25:36 -0400
commita83bbfd5c510367a194073b1db132022cacf65ed (patch)
treeabfd7520b79ef1e64b7430bd81e75a30353b7f14 /src/cuchaz
parentfixed recognition of static initializer tokens (diff)
downloadenigma-a83bbfd5c510367a194073b1db132022cacf65ed.tar.gz
enigma-a83bbfd5c510367a194073b1db132022cacf65ed.tar.xz
enigma-a83bbfd5c510367a194073b1db132022cacf65ed.zip
fixed nasty issue with renaming inner classes, but alas, more bugs remain
Diffstat (limited to 'src/cuchaz')
-rw-r--r--src/cuchaz/enigma/Deobfuscator.java3
-rw-r--r--src/cuchaz/enigma/TranslatingTypeLoader.java10
-rw-r--r--src/cuchaz/enigma/analysis/EntryReference.java15
-rw-r--r--src/cuchaz/enigma/analysis/JarIndex.java7
-rw-r--r--src/cuchaz/enigma/analysis/SourceIndex.java2
-rw-r--r--src/cuchaz/enigma/bytecode/ClassRenamer.java31
-rw-r--r--src/cuchaz/enigma/bytecode/ClassTranslator.java6
-rw-r--r--src/cuchaz/enigma/bytecode/InnerClassWriter.java20
-rw-r--r--src/cuchaz/enigma/gui/Gui.java4
-rw-r--r--src/cuchaz/enigma/mapping/ClassMapping.java18
-rw-r--r--src/cuchaz/enigma/mapping/MappingsReader.java41
-rw-r--r--src/cuchaz/enigma/mapping/MappingsRenamer.java6
-rw-r--r--src/cuchaz/enigma/mapping/NameValidator.java6
-rw-r--r--src/cuchaz/enigma/mapping/Translator.java17
14 files changed, 108 insertions, 78 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java
index bd4345e7..d45ffb41 100644
--- a/src/cuchaz/enigma/Deobfuscator.java
+++ b/src/cuchaz/enigma/Deobfuscator.java
@@ -45,7 +45,6 @@ import cuchaz.enigma.analysis.JarIndex;
45import cuchaz.enigma.analysis.SourceIndex; 45import cuchaz.enigma.analysis.SourceIndex;
46import cuchaz.enigma.analysis.SourceIndexVisitor; 46import cuchaz.enigma.analysis.SourceIndexVisitor;
47import cuchaz.enigma.analysis.Token; 47import cuchaz.enigma.analysis.Token;
48import cuchaz.enigma.analysis.TreeDumpVisitor;
49import cuchaz.enigma.mapping.ArgumentEntry; 48import cuchaz.enigma.mapping.ArgumentEntry;
50import cuchaz.enigma.mapping.BehaviorEntry; 49import cuchaz.enigma.mapping.BehaviorEntry;
51import cuchaz.enigma.mapping.BehaviorEntryFactory; 50import cuchaz.enigma.mapping.BehaviorEntryFactory;
@@ -221,7 +220,7 @@ public class Deobfuscator
221 String outerClassName = m_jarIndex.getOuterClass( classMapping.getObfName() ); 220 String outerClassName = m_jarIndex.getOuterClass( classMapping.getObfName() );
222 if( outerClassName != null ) 221 if( outerClassName != null )
223 { 222 {
224 classEntry = new ClassEntry( outerClassName + "$" + classEntry.getSimpleName() ); 223 classEntry = new ClassEntry( outerClassName + "$" + classMapping.getObfName() );
225 } 224 }
226 if( !m_jarIndex.getObfClassEntries().contains( classEntry ) ) 225 if( !m_jarIndex.getObfClassEntries().contains( classEntry ) )
227 { 226 {
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java
index 6179879a..86e52a34 100644
--- a/src/cuchaz/enigma/TranslatingTypeLoader.java
+++ b/src/cuchaz/enigma/TranslatingTypeLoader.java
@@ -13,6 +13,7 @@ package cuchaz.enigma;
13import java.io.ByteArrayOutputStream; 13import java.io.ByteArrayOutputStream;
14import java.io.IOException; 14import java.io.IOException;
15import java.io.InputStream; 15import java.io.InputStream;
16import java.util.Arrays;
16import java.util.Map; 17import java.util.Map;
17import java.util.jar.JarEntry; 18import java.util.jar.JarEntry;
18import java.util.jar.JarFile; 19import java.util.jar.JarFile;
@@ -119,7 +120,6 @@ public class TranslatingTypeLoader implements ITypeLoader
119 120
120 private byte[] loadType( String deobfClassName ) 121 private byte[] loadType( String deobfClassName )
121 { 122 {
122 // what class file should we actually load?
123 ClassEntry deobfClassEntry = new ClassEntry( deobfClassName ); 123 ClassEntry deobfClassEntry = new ClassEntry( deobfClassName );
124 ClassEntry obfClassEntry = m_obfuscatingTranslator.translateEntry( deobfClassEntry ); 124 ClassEntry obfClassEntry = m_obfuscatingTranslator.translateEntry( deobfClassEntry );
125 125
@@ -143,7 +143,7 @@ public class TranslatingTypeLoader implements ITypeLoader
143 String classFileName; 143 String classFileName;
144 if( obfClassEntry.isInnerClass() ) 144 if( obfClassEntry.isInnerClass() )
145 { 145 {
146 // use just the inner class simple name for inner classes 146 // use just the inner class name for inner classes
147 classFileName = obfClassEntry.getInnerClassName(); 147 classFileName = obfClassEntry.getInnerClassName();
148 } 148 }
149 else if( obfClassEntry.getPackageName().equals( Constants.NonePackage ) ) 149 else if( obfClassEntry.getPackageName().equals( Constants.NonePackage ) )
@@ -193,6 +193,9 @@ public class TranslatingTypeLoader implements ITypeLoader
193 // sanity checking 193 // sanity checking
194 assertClassName( c, deobfClassEntry ); 194 assertClassName( c, deobfClassEntry );
195 195
196 // DEBUG
197 //Util.writeClass( c );
198
196 // we have a transformed class! 199 // we have a transformed class!
197 return c.toBytecode(); 200 return c.toBytecode();
198 } 201 }
@@ -227,9 +230,6 @@ public class TranslatingTypeLoader implements ITypeLoader
227 new MethodParameterWriter( m_deobfuscatingTranslator ).writeMethodArguments( c ); 230 new MethodParameterWriter( m_deobfuscatingTranslator ).writeMethodArguments( c );
228 new ClassTranslator( m_deobfuscatingTranslator ).translate( c ); 231 new ClassTranslator( m_deobfuscatingTranslator ).translate( c );
229 232
230 // DEBUG
231 //Util.writeClass( c );
232
233 return c; 233 return c;
234 } 234 }
235 235
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java
index 4da2f589..0cde8759 100644
--- a/src/cuchaz/enigma/analysis/EntryReference.java
+++ b/src/cuchaz/enigma/analysis/EntryReference.java
@@ -79,6 +79,21 @@ public class EntryReference<E extends Entry, C extends Entry>
79 return entry; 79 return entry;
80 } 80 }
81 81
82 public String getNamableName( )
83 {
84 if( getNameableEntry() instanceof ClassEntry )
85 {
86 ClassEntry classEntry = (ClassEntry)getNameableEntry();
87 if( classEntry.isInnerClass() )
88 {
89 // make sure we only rename the inner class name
90 return classEntry.getInnerClassName();
91 }
92 }
93
94 return getNameableEntry().getName();
95 }
96
82 @Override 97 @Override
83 public int hashCode( ) 98 public int hashCode( )
84 { 99 {
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java
index 604e4853..ba082064 100644
--- a/src/cuchaz/enigma/analysis/JarIndex.java
+++ b/src/cuchaz/enigma/analysis/JarIndex.java
@@ -164,9 +164,10 @@ public class JarIndex
164 String outerClassName = findOuterClass( c ); 164 String outerClassName = findOuterClass( c );
165 if( outerClassName != null ) 165 if( outerClassName != null )
166 { 166 {
167 String innerClassName = Descriptor.toJvmName( c.getName() ); 167 String innerClassName = c.getSimpleName();
168 m_innerClasses.put( outerClassName, innerClassName ); 168 m_innerClasses.put( outerClassName, innerClassName );
169 m_outerClasses.put( innerClassName, outerClassName ); 169 boolean innerWasAdded = m_outerClasses.put( innerClassName, outerClassName ) == null;
170 assert( innerWasAdded );
170 171
171 BehaviorEntry enclosingBehavior = isAnonymousClass( c, outerClassName ); 172 BehaviorEntry enclosingBehavior = isAnonymousClass( c, outerClassName );
172 if( enclosingBehavior != null ) 173 if( enclosingBehavior != null )
@@ -188,7 +189,7 @@ public class JarIndex
188 Map<String,String> renames = Maps.newHashMap(); 189 Map<String,String> renames = Maps.newHashMap();
189 for( Map.Entry<String,String> entry : m_outerClasses.entrySet() ) 190 for( Map.Entry<String,String> entry : m_outerClasses.entrySet() )
190 { 191 {
191 renames.put( entry.getKey(), entry.getValue() + "$" + new ClassEntry( entry.getKey() ).getSimpleName() ); 192 renames.put( Constants.NonePackage + "/" + entry.getKey(), entry.getValue() + "$" + entry.getKey() );
192 } 193 }
193 EntryRenamer.renameClassesInSet( renames, m_obfClassEntries ); 194 EntryRenamer.renameClassesInSet( renames, m_obfClassEntries );
194 m_translationIndex.renameClasses( renames ); 195 m_translationIndex.renameClasses( renames );
diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java
index faae1a14..21a499e8 100644
--- a/src/cuchaz/enigma/analysis/SourceIndex.java
+++ b/src/cuchaz/enigma/analysis/SourceIndex.java
@@ -89,14 +89,12 @@ public class SourceIndex
89 // DEBUG 89 // DEBUG
90 //System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) ); 90 //System.out.println( String.format( "%s \"%s\" region: %s", node.getNodeType(), name, region ) );
91 91
92 /* TODO: double check that we still need this
93 // for tokens representing inner classes, make sure we only get the simple name 92 // for tokens representing inner classes, make sure we only get the simple name
94 int pos = node.getText().lastIndexOf( '$' ); 93 int pos = node.getText().lastIndexOf( '$' );
95 if( pos >= 0 ) 94 if( pos >= 0 )
96 { 95 {
97 token.end -= pos + 1; 96 token.end -= pos + 1;
98 } 97 }
99 */
100 98
101 return token; 99 return token;
102 } 100 }
diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java
index 9f0845da..849a3233 100644
--- a/src/cuchaz/enigma/bytecode/ClassRenamer.java
+++ b/src/cuchaz/enigma/bytecode/ClassRenamer.java
@@ -37,34 +37,25 @@ public class ClassRenamer
37 { 37 {
38 nameMap.put( entry.getKey().getName(), entry.getValue().getName() ); 38 nameMap.put( entry.getKey().getName(), entry.getValue().getName() );
39 } 39 }
40
40 c.replaceClassName( nameMap ); 41 c.replaceClassName( nameMap );
41 42
42 // translate the names in the InnerClasses attribute 43 // replace simple names in the InnerClasses attribute too
43 ConstPool constants = c.getClassFile().getConstPool(); 44 ConstPool constants = c.getClassFile().getConstPool();
44 InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute( InnerClassesAttribute.tag ); 45 InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute( InnerClassesAttribute.tag );
45 if( attr != null ) 46 if( attr != null )
46 { 47 {
47 for( int i=0; i<attr.tableLength(); i++ ) 48 for( int i=0; i<attr.tableLength(); i++ )
48 { 49 {
49 ClassEntry inClassEntry = new ClassEntry( Descriptor.toJvmName( attr.innerClass( i ) ) ); 50 ClassEntry classEntry = new ClassEntry( Descriptor.toJvmName( attr.innerClass( i ) ) );
50 ClassEntry outClassEntry = map.get( inClassEntry );
51 if( outClassEntry == null )
52 {
53 continue;
54 }
55 attr.setInnerClassIndex( i, constants.addClassInfo( outClassEntry.getName() ) );
56 if( attr.outerClassIndex( i ) != 0 )
57 {
58 attr.setOuterClassIndex( i, constants.addClassInfo( outClassEntry.getOuterClassName() ) );
59 }
60 if( attr.innerNameIndex( i ) != 0 ) 51 if( attr.innerNameIndex( i ) != 0 )
61 { 52 {
62 attr.setInnerNameIndex( i, constants.addUtf8Info( outClassEntry.getInnerClassName() ) ); 53 attr.setInnerNameIndex( i, constants.addUtf8Info( classEntry.getInnerClassName() ) );
63 } 54 }
64 55
65 /* DEBUG 56 /* DEBUG
66 System.out.println( String.format( "\tOBF: %s DEOBF: %s-> ATTR: %s,%s,%s", 57 System.out.println( String.format( "\tDEOBF: %s-> ATTR: %s,%s,%s",
67 obfClassEntry, deobfClassEntry, 58 classEntry,
68 attr.outerClass( i ), 59 attr.outerClass( i ),
69 attr.innerClass( i ), 60 attr.innerClass( i ),
70 attr.innerName( i ) 61 attr.innerName( i )
@@ -109,16 +100,6 @@ public class ClassRenamer
109 }; 100 };
110 c.replaceClassName( map ); 101 c.replaceClassName( map );
111 102
112 // also check InnerClassesAttribute
113 InnerClassesAttribute attr = (InnerClassesAttribute)c.getClassFile().getAttribute( InnerClassesAttribute.tag );
114 if( attr != null )
115 {
116 for( int i=0; i<attr.tableLength(); i++ )
117 {
118 entries.add( new ClassEntry( Descriptor.toJvmName( attr.innerClass( i ) ) ) );
119 }
120 }
121
122 return entries; 103 return entries;
123 } 104 }
124 105
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java
index db28f21b..181fadb1 100644
--- a/src/cuchaz/enigma/bytecode/ClassTranslator.java
+++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java
@@ -132,7 +132,11 @@ public class ClassTranslator
132 Map<ClassEntry,ClassEntry> map = Maps.newHashMap(); 132 Map<ClassEntry,ClassEntry> map = Maps.newHashMap();
133 for( ClassEntry obfClassEntry : ClassRenamer.getAllClassEntries( c ) ) 133 for( ClassEntry obfClassEntry : ClassRenamer.getAllClassEntries( c ) )
134 { 134 {
135 map.put( obfClassEntry, m_translator.translateEntry( obfClassEntry ) ); 135 ClassEntry deobfClassEntry = m_translator.translateEntry( obfClassEntry );
136 if( !obfClassEntry.equals( deobfClassEntry ) )
137 {
138 map.put( obfClassEntry, deobfClassEntry );
139 }
136 } 140 }
137 ClassRenamer.renameClasses( c, map ); 141 ClassRenamer.renameClasses( c, map );
138 } 142 }
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
index a0617925..5e593078 100644
--- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java
+++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java
@@ -18,6 +18,7 @@ import javassist.bytecode.ConstPool;
18import javassist.bytecode.Descriptor; 18import javassist.bytecode.Descriptor;
19import javassist.bytecode.EnclosingMethodAttribute; 19import javassist.bytecode.EnclosingMethodAttribute;
20import javassist.bytecode.InnerClassesAttribute; 20import javassist.bytecode.InnerClassesAttribute;
21import cuchaz.enigma.Constants;
21import cuchaz.enigma.analysis.JarIndex; 22import cuchaz.enigma.analysis.JarIndex;
22import cuchaz.enigma.mapping.BehaviorEntry; 23import cuchaz.enigma.mapping.BehaviorEntry;
23import cuchaz.enigma.mapping.ClassEntry; 24import cuchaz.enigma.mapping.ClassEntry;
@@ -33,21 +34,21 @@ public class InnerClassWriter
33 34
34 public void write( CtClass c ) 35 public void write( CtClass c )
35 { 36 {
36 // get the outer class name 37 // is this an inner or outer class?
37 String obfClassName = Descriptor.toJvmName( c.getName() ); 38 String obfInnerClassName = new ClassEntry( Descriptor.toJvmName( c.getName() ) ).getSimpleName();
38 String obfOuterClassName = m_jarIndex.getOuterClass( obfClassName ); 39 String obfOuterClassName = m_jarIndex.getOuterClass( obfInnerClassName );
39 if( obfOuterClassName == null ) 40 if( obfOuterClassName == null )
40 { 41 {
41 // this is an outer class 42 // this is an outer class
42 obfOuterClassName = obfClassName; 43 obfOuterClassName = Descriptor.toJvmName( c.getName() );
43 } 44 }
44 else 45 else
45 { 46 {
46 // this is an inner class, rename it to outer$inner 47 // this is an inner class, rename it to outer$inner
47 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + new ClassEntry( obfClassName ).getSimpleName() ); 48 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + obfInnerClassName );
48 c.setName( obfClassEntry.getName() ); 49 c.setName( obfClassEntry.getName() );
49 50
50 BehaviorEntry caller = m_jarIndex.getAnonymousClassCaller( obfClassName ); 51 BehaviorEntry caller = m_jarIndex.getAnonymousClassCaller( obfInnerClassName );
51 if( caller != null ) 52 if( caller != null )
52 { 53 {
53 // write the enclosing method attribute 54 // write the enclosing method attribute
@@ -85,7 +86,7 @@ public class InnerClassWriter
85 for( String obfInnerClassName : obfInnerClassNames ) 86 for( String obfInnerClassName : obfInnerClassNames )
86 { 87 {
87 // get the new inner class name 88 // get the new inner class name
88 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + new ClassEntry( obfInnerClassName ).getSimpleName() ); 89 ClassEntry obfClassEntry = new ClassEntry( obfOuterClassName + "$" + obfInnerClassName );
89 90
90 // here's what the JVM spec says about the InnerClasses attribute 91 // here's what the JVM spec says about the InnerClasses attribute
91 // append( inner, outer of inner if inner is member of outer 0 ow, name after $ if inner not anonymous 0 ow, flags ); 92 // append( inner, outer of inner if inner is member of outer 0 ow, name after $ if inner not anonymous 0 ow, flags );
@@ -114,12 +115,13 @@ public class InnerClassWriter
114 attr.outerClass( attr.tableLength() - 1 ), 115 attr.outerClass( attr.tableLength() - 1 ),
115 attr.innerClass( attr.tableLength() - 1 ), 116 attr.innerClass( attr.tableLength() - 1 ),
116 attr.innerName( attr.tableLength() - 1 ), 117 attr.innerName( attr.tableLength() - 1 ),
117 obfInnerClassName, obfClassEntry.getName() 118 Constants.NonePackage + "/" + obfInnerClassName,
119 obfClassEntry.getName()
118 ) ); 120 ) );
119 */ 121 */
120 122
121 // make sure the outer class references only the new inner class names 123 // make sure the outer class references only the new inner class names
122 c.replaceClassName( obfInnerClassName, obfClassEntry.getName() ); 124 c.replaceClassName( Constants.NonePackage + "/" + obfInnerClassName, obfClassEntry.getName() );
123 } 125 }
124 } 126 }
125} 127}
diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java
index dbfcba83..faa9b7b1 100644
--- a/src/cuchaz/enigma/gui/Gui.java
+++ b/src/cuchaz/enigma/gui/Gui.java
@@ -1124,7 +1124,7 @@ public class Gui
1124 { 1124 {
1125 // init the text box 1125 // init the text box
1126 final JTextField text = new JTextField(); 1126 final JTextField text = new JTextField();
1127 text.setText( m_reference.getNameableEntry().getName() ); 1127 text.setText( m_reference.getNamableName() );
1128 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) ); 1128 text.setPreferredSize( new Dimension( 360, text.getPreferredSize().height ) );
1129 text.addKeyListener( new KeyAdapter( ) 1129 text.addKeyListener( new KeyAdapter( )
1130 { 1130 {
@@ -1175,7 +1175,7 @@ public class Gui
1175 // abort the rename 1175 // abort the rename
1176 JPanel panel = (JPanel)m_infoPanel.getComponent( 0 ); 1176 JPanel panel = (JPanel)m_infoPanel.getComponent( 0 );
1177 panel.remove( panel.getComponentCount() - 1 ); 1177 panel.remove( panel.getComponentCount() - 1 );
1178 panel.add( GuiTricks.unboldLabel( new JLabel( m_reference.getNameableEntry().getName(), JLabel.LEFT ) ) ); 1178 panel.add( GuiTricks.unboldLabel( new JLabel( m_reference.getNamableName(), JLabel.LEFT ) ) );
1179 1179
1180 m_editor.grabFocus(); 1180 m_editor.grabFocus();
1181 1181
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java
index 88106dfa..ee02781e 100644
--- a/src/cuchaz/enigma/mapping/ClassMapping.java
+++ b/src/cuchaz/enigma/mapping/ClassMapping.java
@@ -37,7 +37,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
37 public ClassMapping( String obfName, String deobfName ) 37 public ClassMapping( String obfName, String deobfName )
38 { 38 {
39 m_obfName = obfName; 39 m_obfName = obfName;
40 m_deobfName = NameValidator.validateClassName( deobfName ); 40 m_deobfName = NameValidator.validateClassName( deobfName, false );
41 m_innerClassesByObf = Maps.newHashMap(); 41 m_innerClassesByObf = Maps.newHashMap();
42 m_innerClassesByDeobf = Maps.newHashMap(); 42 m_innerClassesByDeobf = Maps.newHashMap();
43 m_fieldsByObf = Maps.newHashMap(); 43 m_fieldsByObf = Maps.newHashMap();
@@ -57,7 +57,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
57 } 57 }
58 public void setDeobfName( String val ) 58 public void setDeobfName( String val )
59 { 59 {
60 m_deobfName = NameValidator.validateClassName( val ); 60 m_deobfName = NameValidator.validateClassName( val, false );
61 } 61 }
62 62
63 //// INNER CLASSES //////// 63 //// INNER CLASSES ////////
@@ -70,10 +70,12 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
70 70
71 public void addInnerClassMapping( ClassMapping classMapping ) 71 public void addInnerClassMapping( ClassMapping classMapping )
72 { 72 {
73 assert( isSimpleClassName( classMapping.getObfName() ) );
73 boolean obfWasAdded = m_innerClassesByObf.put( classMapping.getObfName(), classMapping ) == null; 74 boolean obfWasAdded = m_innerClassesByObf.put( classMapping.getObfName(), classMapping ) == null;
74 assert( obfWasAdded ); 75 assert( obfWasAdded );
75 if( classMapping.getDeobfName() != null ) 76 if( classMapping.getDeobfName() != null )
76 { 77 {
78 assert( isSimpleClassName( classMapping.getDeobfName() ) );
77 boolean deobfWasAdded = m_innerClassesByDeobf.put( classMapping.getDeobfName(), classMapping ) == null; 79 boolean deobfWasAdded = m_innerClassesByDeobf.put( classMapping.getDeobfName(), classMapping ) == null;
78 assert( deobfWasAdded ); 80 assert( deobfWasAdded );
79 } 81 }
@@ -92,6 +94,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
92 94
93 public ClassMapping getOrCreateInnerClass( String obfName ) 95 public ClassMapping getOrCreateInnerClass( String obfName )
94 { 96 {
97 assert( isSimpleClassName( obfName ) );
95 ClassMapping classMapping = m_innerClassesByObf.get( obfName ); 98 ClassMapping classMapping = m_innerClassesByObf.get( obfName );
96 if( classMapping == null ) 99 if( classMapping == null )
97 { 100 {
@@ -104,16 +107,19 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
104 107
105 public ClassMapping getInnerClassByObf( String obfName ) 108 public ClassMapping getInnerClassByObf( String obfName )
106 { 109 {
110 assert( isSimpleClassName( obfName ) );
107 return m_innerClassesByObf.get( obfName ); 111 return m_innerClassesByObf.get( obfName );
108 } 112 }
109 113
110 public ClassMapping getInnerClassByDeobf( String deobfName ) 114 public ClassMapping getInnerClassByDeobf( String deobfName )
111 { 115 {
116 assert( isSimpleClassName( deobfName ) );
112 return m_innerClassesByDeobf.get( deobfName ); 117 return m_innerClassesByDeobf.get( deobfName );
113 } 118 }
114 119
115 public String getObfInnerClassName( String deobfName ) 120 public String getObfInnerClassName( String deobfName )
116 { 121 {
122 assert( isSimpleClassName( deobfName ) );
117 ClassMapping classMapping = m_innerClassesByDeobf.get( deobfName ); 123 ClassMapping classMapping = m_innerClassesByDeobf.get( deobfName );
118 if( classMapping != null ) 124 if( classMapping != null )
119 { 125 {
@@ -124,6 +130,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
124 130
125 public String getDeobfInnerClassName( String obfName ) 131 public String getDeobfInnerClassName( String obfName )
126 { 132 {
133 assert( isSimpleClassName( obfName ) );
127 ClassMapping classMapping = m_innerClassesByObf.get( obfName ); 134 ClassMapping classMapping = m_innerClassesByObf.get( obfName );
128 if( classMapping != null ) 135 if( classMapping != null )
129 { 136 {
@@ -134,6 +141,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
134 141
135 public void setInnerClassName( String obfName, String deobfName ) 142 public void setInnerClassName( String obfName, String deobfName )
136 { 143 {
144 assert( isSimpleClassName( obfName ) );
137 ClassMapping classMapping = getOrCreateInnerClass( obfName ); 145 ClassMapping classMapping = getOrCreateInnerClass( obfName );
138 if( classMapping.getDeobfName() != null ) 146 if( classMapping.getDeobfName() != null )
139 { 147 {
@@ -143,6 +151,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
143 classMapping.setDeobfName( deobfName ); 151 classMapping.setDeobfName( deobfName );
144 if( deobfName != null ) 152 if( deobfName != null )
145 { 153 {
154 assert( isSimpleClassName( deobfName ) );
146 boolean wasAdded = m_innerClassesByDeobf.put( deobfName, classMapping ) == null; 155 boolean wasAdded = m_innerClassesByDeobf.put( deobfName, classMapping ) == null;
147 assert( wasAdded ); 156 assert( wasAdded );
148 } 157 }
@@ -442,4 +451,9 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping>
442 } 451 }
443 return false; 452 return false;
444 } 453 }
454
455 public static boolean isSimpleClassName( String name )
456 {
457 return name.indexOf( '/' ) < 0 && name.indexOf( '$' ) < 0;
458 }
445} 459}
diff --git a/src/cuchaz/enigma/mapping/MappingsReader.java b/src/cuchaz/enigma/mapping/MappingsReader.java
index 5cbad59c..4bd9f121 100644
--- a/src/cuchaz/enigma/mapping/MappingsReader.java
+++ b/src/cuchaz/enigma/mapping/MappingsReader.java
@@ -78,10 +78,11 @@ public class MappingsReader
78 78
79 if( token.equalsIgnoreCase( "CLASS" ) ) 79 if( token.equalsIgnoreCase( "CLASS" ) )
80 { 80 {
81 ClassMapping classMapping = readClass( parts ); 81 ClassMapping classMapping;
82 if( indent == 0 ) 82 if( indent == 0 )
83 { 83 {
84 // outer class 84 // outer class
85 classMapping = readClass( parts, false );
85 mappings.addClassMapping( classMapping ); 86 mappings.addClassMapping( classMapping );
86 } 87 }
87 else if( indent == 1 ) 88 else if( indent == 1 )
@@ -91,11 +92,13 @@ public class MappingsReader
91 { 92 {
92 throw new MappingParseException( lineNumber, "Unexpected CLASS entry here!" ); 93 throw new MappingParseException( lineNumber, "Unexpected CLASS entry here!" );
93 } 94 }
95
96 classMapping = readClass( parts, true );
94 ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping( classMapping ); 97 ((ClassMapping)mappingStack.getFirst()).addInnerClassMapping( classMapping );
95 } 98 }
96 else 99 else
97 { 100 {
98 throw new MappingParseException( lineNumber, "Unexpected CLASS entry here!" ); 101 throw new MappingParseException( lineNumber, "Unexpected CLASS entry nesting!" );
99 } 102 }
100 mappingStack.push( classMapping ); 103 mappingStack.push( classMapping );
101 } 104 }
@@ -140,28 +143,30 @@ public class MappingsReader
140 return new ArgumentMapping( Integer.parseInt( parts[1] ), parts[2] ); 143 return new ArgumentMapping( Integer.parseInt( parts[1] ), parts[2] );
141 } 144 }
142 145
143 private ClassMapping readClass( String[] parts ) 146 private ClassMapping readClass( String[] parts, boolean makeSimple )
144 { 147 {
145 if( parts.length == 2 ) 148 if( parts.length == 2 )
146 { 149 {
147 String obfName = parts[1]; 150 String obfName = processName( parts[1], makeSimple );
148 return new ClassMapping( moveClassOutOfDefaultPackage( obfName, Constants.NonePackage ) ); 151 return new ClassMapping( obfName );
149 } 152 }
150 else 153 else
151 { 154 {
152 String obfName = parts[1]; 155 String obfName = processName( parts[1], makeSimple );
153 String deobfName = parts[2]; 156 String deobfName = processName( parts[2], makeSimple );
154 if( obfName.equals( deobfName ) ) 157 return new ClassMapping( obfName, deobfName );
155 { 158 }
156 return new ClassMapping( moveClassOutOfDefaultPackage( obfName, Constants.NonePackage ) ); 159 }
157 } 160
158 else 161 private String processName( String name, boolean makeSimple )
159 { 162 {
160 return new ClassMapping( 163 if( makeSimple )
161 moveClassOutOfDefaultPackage( parts[1], Constants.NonePackage ), 164 {
162 moveClassOutOfDefaultPackage( parts[2], Constants.NonePackage ) 165 return new ClassEntry( name ).getSimpleName();
163 ); 166 }
164 } 167 else
168 {
169 return moveClassOutOfDefaultPackage( name, Constants.NonePackage );
165 } 170 }
166 } 171 }
167 172
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java
index 957b6d68..24ec7318 100644
--- a/src/cuchaz/enigma/mapping/MappingsRenamer.java
+++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java
@@ -16,6 +16,7 @@ import java.io.OutputStream;
16import java.util.Set; 16import java.util.Set;
17import java.util.zip.GZIPOutputStream; 17import java.util.zip.GZIPOutputStream;
18 18
19import cuchaz.enigma.Constants;
19import cuchaz.enigma.analysis.JarIndex; 20import cuchaz.enigma.analysis.JarIndex;
20 21
21public class MappingsRenamer 22public class MappingsRenamer
@@ -31,7 +32,7 @@ public class MappingsRenamer
31 32
32 public void setClassName( ClassEntry obf, String deobfName ) 33 public void setClassName( ClassEntry obf, String deobfName )
33 { 34 {
34 deobfName = NameValidator.validateClassName( deobfName ); 35 deobfName = NameValidator.validateClassName( deobfName, !obf.isInnerClass() );
35 ClassEntry targetEntry = new ClassEntry( deobfName ); 36 ClassEntry targetEntry = new ClassEntry( deobfName );
36 if( m_mappings.containsDeobfClass( deobfName ) || m_index.containsObfClass( targetEntry ) ) 37 if( m_mappings.containsDeobfClass( deobfName ) || m_index.containsObfClass( targetEntry ) )
37 { 38 {
@@ -77,7 +78,8 @@ public class MappingsRenamer
77 ClassMapping classMapping = getOrCreateClassMapping( obf ); 78 ClassMapping classMapping = getOrCreateClassMapping( obf );
78 if( obf.isInnerClass() ) 79 if( obf.isInnerClass() )
79 { 80 {
80 classMapping.setInnerClassName( obf.getName(), obf.getName() ); 81 String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName();
82 classMapping.setInnerClassName( innerClassName, innerClassName );
81 } 83 }
82 else 84 else
83 { 85 {
diff --git a/src/cuchaz/enigma/mapping/NameValidator.java b/src/cuchaz/enigma/mapping/NameValidator.java
index 9adf1ac1..c6ae5969 100644
--- a/src/cuchaz/enigma/mapping/NameValidator.java
+++ b/src/cuchaz/enigma/mapping/NameValidator.java
@@ -55,7 +55,7 @@ public class NameValidator
55 ClassPattern = Pattern.compile( String.format( "^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex ) ); 55 ClassPattern = Pattern.compile( String.format( "^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex ) );
56 } 56 }
57 57
58 public static String validateClassName( String name ) 58 public static String validateClassName( String name, boolean packageRequired )
59 { 59 {
60 if( name == null ) 60 if( name == null )
61 { 61 {
@@ -65,9 +65,9 @@ public class NameValidator
65 { 65 {
66 throw new IllegalNameException( name, "This doesn't look like a legal class name" ); 66 throw new IllegalNameException( name, "This doesn't look like a legal class name" );
67 } 67 }
68 if( new ClassEntry( name ).getPackageName() == null ) 68 if( packageRequired && new ClassEntry( name ).getPackageName() == null )
69 { 69 {
70 throw new IllegalNameException( name, "Classes must be in a package" ); 70 throw new IllegalNameException( name, "Class must be in a package" );
71 } 71 }
72 return Descriptor.toJvmName( name ); 72 return Descriptor.toJvmName( name );
73 } 73 }
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java
index 7904ef53..1c69b2f4 100644
--- a/src/cuchaz/enigma/mapping/Translator.java
+++ b/src/cuchaz/enigma/mapping/Translator.java
@@ -80,19 +80,26 @@ public class Translator
80 { 80 {
81 if( in.isInnerClass() ) 81 if( in.isInnerClass() )
82 { 82 {
83 // look for the inner class 83 // translate the inner class
84 String translatedInnerClassName = m_direction.choose( 84 String translatedInnerClassName = m_direction.choose(
85 classMapping.getDeobfInnerClassName( in.getInnerClassName() ), 85 classMapping.getDeobfInnerClassName( in.getInnerClassName() ),
86 classMapping.getObfInnerClassName( in.getInnerClassName() ) 86 classMapping.getObfInnerClassName( in.getInnerClassName() )
87 ); 87 );
88 if( translatedInnerClassName != null ) 88 if( translatedInnerClassName != null )
89 { 89 {
90 // return outer$inner 90 // try to translate the outer name
91 String translatedOuterClassName = m_direction.choose( 91 String translatedOuterClassName = m_direction.choose(
92 classMapping.getDeobfName(), 92 classMapping.getDeobfName(),
93 classMapping.getObfName() 93 classMapping.getObfName()
94 ); 94 );
95 return translatedOuterClassName + "$" + translatedInnerClassName; 95 if( translatedOuterClassName != null )
96 {
97 return translatedOuterClassName + "$" + translatedInnerClassName;
98 }
99 else
100 {
101 return in.getOuterClassName() + "$" + translatedInnerClassName;
102 }
96 } 103 }
97 } 104 }
98 else 105 else
@@ -109,6 +116,7 @@ public class Translator
109 116
110 public ClassEntry translateEntry( ClassEntry in ) 117 public ClassEntry translateEntry( ClassEntry in )
111 { 118 {
119 // can we translate the inner class?
112 String name = translate( in ); 120 String name = translate( in );
113 if( name != null ) 121 if( name != null )
114 { 122 {
@@ -117,13 +125,14 @@ public class Translator
117 125
118 if( in.isInnerClass() ) 126 if( in.isInnerClass() )
119 { 127 {
120 // just translate the outer class name 128 // guess not. just translate the outer class name then
121 String outerClassName = translate( in.getOuterClassEntry() ); 129 String outerClassName = translate( in.getOuterClassEntry() );
122 if( outerClassName != null ) 130 if( outerClassName != null )
123 { 131 {
124 return new ClassEntry( outerClassName + "$" + in.getInnerClassName() ); 132 return new ClassEntry( outerClassName + "$" + in.getInnerClassName() );
125 } 133 }
126 } 134 }
135
127 return in; 136 return in;
128 } 137 }
129 138