diff options
| author | 2014-09-30 00:25:36 -0400 | |
|---|---|---|
| committer | 2014-09-30 00:25:36 -0400 | |
| commit | a83bbfd5c510367a194073b1db132022cacf65ed (patch) | |
| tree | abfd7520b79ef1e64b7430bd81e75a30353b7f14 | |
| parent | fixed recognition of static initializer tokens (diff) | |
| download | enigma-fork-a83bbfd5c510367a194073b1db132022cacf65ed.tar.gz enigma-fork-a83bbfd5c510367a194073b1db132022cacf65ed.tar.xz enigma-fork-a83bbfd5c510367a194073b1db132022cacf65ed.zip | |
fixed nasty issue with renaming inner classes, but alas, more bugs remain
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 3 | ||||
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 10 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/EntryReference.java | 15 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 7 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/SourceIndex.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/ClassRenamer.java | 31 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/ClassTranslator.java | 6 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/InnerClassWriter.java | 20 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/Gui.java | 4 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ClassMapping.java | 18 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MappingsReader.java | 41 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MappingsRenamer.java | 6 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/NameValidator.java | 6 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Translator.java | 17 |
14 files changed, 108 insertions, 78 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index bd4345e..d45ffb4 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -45,7 +45,6 @@ import cuchaz.enigma.analysis.JarIndex; | |||
| 45 | import cuchaz.enigma.analysis.SourceIndex; | 45 | import cuchaz.enigma.analysis.SourceIndex; |
| 46 | import cuchaz.enigma.analysis.SourceIndexVisitor; | 46 | import cuchaz.enigma.analysis.SourceIndexVisitor; |
| 47 | import cuchaz.enigma.analysis.Token; | 47 | import cuchaz.enigma.analysis.Token; |
| 48 | import cuchaz.enigma.analysis.TreeDumpVisitor; | ||
| 49 | import cuchaz.enigma.mapping.ArgumentEntry; | 48 | import cuchaz.enigma.mapping.ArgumentEntry; |
| 50 | import cuchaz.enigma.mapping.BehaviorEntry; | 49 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 51 | import cuchaz.enigma.mapping.BehaviorEntryFactory; | 50 | import 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 6179879..86e52a3 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -13,6 +13,7 @@ package cuchaz.enigma; | |||
| 13 | import java.io.ByteArrayOutputStream; | 13 | import java.io.ByteArrayOutputStream; |
| 14 | import java.io.IOException; | 14 | import java.io.IOException; |
| 15 | import java.io.InputStream; | 15 | import java.io.InputStream; |
| 16 | import java.util.Arrays; | ||
| 16 | import java.util.Map; | 17 | import java.util.Map; |
| 17 | import java.util.jar.JarEntry; | 18 | import java.util.jar.JarEntry; |
| 18 | import java.util.jar.JarFile; | 19 | import 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 4da2f58..0cde875 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 604e485..ba08206 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 faae1a1..21a499e 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 9f0845d..849a323 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 db28f21..181fadb 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 a061792..5e59307 100644 --- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java | |||
| @@ -18,6 +18,7 @@ import javassist.bytecode.ConstPool; | |||
| 18 | import javassist.bytecode.Descriptor; | 18 | import javassist.bytecode.Descriptor; |
| 19 | import javassist.bytecode.EnclosingMethodAttribute; | 19 | import javassist.bytecode.EnclosingMethodAttribute; |
| 20 | import javassist.bytecode.InnerClassesAttribute; | 20 | import javassist.bytecode.InnerClassesAttribute; |
| 21 | import cuchaz.enigma.Constants; | ||
| 21 | import cuchaz.enigma.analysis.JarIndex; | 22 | import cuchaz.enigma.analysis.JarIndex; |
| 22 | import cuchaz.enigma.mapping.BehaviorEntry; | 23 | import cuchaz.enigma.mapping.BehaviorEntry; |
| 23 | import cuchaz.enigma.mapping.ClassEntry; | 24 | import 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 dbfcba8..faa9b7b 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 88106df..ee02781 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 5cbad59..4bd9f12 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 957b6d6..24ec731 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java | |||
| @@ -16,6 +16,7 @@ import java.io.OutputStream; | |||
| 16 | import java.util.Set; | 16 | import java.util.Set; |
| 17 | import java.util.zip.GZIPOutputStream; | 17 | import java.util.zip.GZIPOutputStream; |
| 18 | 18 | ||
| 19 | import cuchaz.enigma.Constants; | ||
| 19 | import cuchaz.enigma.analysis.JarIndex; | 20 | import cuchaz.enigma.analysis.JarIndex; |
| 20 | 21 | ||
| 21 | public class MappingsRenamer | 22 | public 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 9adf1ac..c6ae596 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 7904ef5..1c69b2f 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 | ||