diff options
| author | 2015-03-16 12:29:17 -0400 | |
|---|---|---|
| committer | 2015-03-16 12:29:17 -0400 | |
| commit | c133e05b786ff5357931842581571c046f958c74 (patch) | |
| tree | 9fc998ac7b85828f3b57f04600244c6a79b2b2e8 /src | |
| parent | Added tag v0.9 beta for changeset 856528c00d1c (diff) | |
| download | enigma-fork-c133e05b786ff5357931842581571c046f958c74.tar.gz enigma-fork-c133e05b786ff5357931842581571c046f958c74.tar.xz enigma-fork-c133e05b786ff5357931842581571c046f958c74.zip | |
fix a zillion issues with inner classes
Diffstat (limited to 'src')
| -rw-r--r-- | src/cuchaz/enigma/Deobfuscator.java | 8 | ||||
| -rw-r--r-- | src/cuchaz/enigma/TranslatingTypeLoader.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/EntryReference.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/analysis/JarIndex.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/ClassRenamer.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/ClassTranslator.java | 17 | ||||
| -rw-r--r-- | src/cuchaz/enigma/bytecode/InnerClassWriter.java | 4 | ||||
| -rw-r--r-- | src/cuchaz/enigma/convert/ClassIdentity.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/convert/MappingsConverter.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/CodeReader.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/gui/GuiController.java | 2 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ClassEntry.java | 31 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/ClassMapping.java | 79 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Mappings.java | 28 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/MappingsRenamer.java | 128 | ||||
| -rw-r--r-- | src/cuchaz/enigma/mapping/Translator.java | 73 |
16 files changed, 198 insertions, 186 deletions
diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index f5012bd..5a23ce5 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java | |||
| @@ -438,7 +438,13 @@ public class Deobfuscator { | |||
| 438 | public boolean hasDeobfuscatedName(Entry obfEntry) { | 438 | public boolean hasDeobfuscatedName(Entry obfEntry) { |
| 439 | Translator translator = getTranslator(TranslationDirection.Deobfuscating); | 439 | Translator translator = getTranslator(TranslationDirection.Deobfuscating); |
| 440 | if (obfEntry instanceof ClassEntry) { | 440 | if (obfEntry instanceof ClassEntry) { |
| 441 | return translator.translate((ClassEntry)obfEntry) != null; | 441 | ClassEntry obfClass = (ClassEntry)obfEntry; |
| 442 | ClassEntry translated = translator.translateEntry(obfClass); | ||
| 443 | if (obfClass.isInnerClass()) { | ||
| 444 | return !obfClass.getInnermostClassName().equals(translated.getInnermostClassName()); | ||
| 445 | } else { | ||
| 446 | return !obfClass.equals(translated); | ||
| 447 | } | ||
| 442 | } else if (obfEntry instanceof FieldEntry) { | 448 | } else if (obfEntry instanceof FieldEntry) { |
| 443 | return translator.translate((FieldEntry)obfEntry) != null; | 449 | return translator.translate((FieldEntry)obfEntry) != null; |
| 444 | } else if (obfEntry instanceof MethodEntry) { | 450 | } else if (obfEntry instanceof MethodEntry) { |
diff --git a/src/cuchaz/enigma/TranslatingTypeLoader.java b/src/cuchaz/enigma/TranslatingTypeLoader.java index 7b57cfa..ecd7d64 100644 --- a/src/cuchaz/enigma/TranslatingTypeLoader.java +++ b/src/cuchaz/enigma/TranslatingTypeLoader.java | |||
| @@ -205,7 +205,7 @@ public class TranslatingTypeLoader implements ITypeLoader { | |||
| 205 | } | 205 | } |
| 206 | if (obfClassEntry.isInnerClass()) { | 206 | if (obfClassEntry.isInnerClass()) { |
| 207 | // try just the inner class name | 207 | // try just the inner class name |
| 208 | classNamesToTry.add(obfClassEntry.getInnerClassName()); | 208 | classNamesToTry.add(obfClassEntry.getInnermostClassName()); |
| 209 | } | 209 | } |
| 210 | return classNamesToTry; | 210 | return classNamesToTry; |
| 211 | } | 211 | } |
diff --git a/src/cuchaz/enigma/analysis/EntryReference.java b/src/cuchaz/enigma/analysis/EntryReference.java index bb611df..d0a5c6a 100644 --- a/src/cuchaz/enigma/analysis/EntryReference.java +++ b/src/cuchaz/enigma/analysis/EntryReference.java | |||
| @@ -74,7 +74,7 @@ public class EntryReference<E extends Entry,C extends Entry> { | |||
| 74 | ClassEntry classEntry = (ClassEntry)getNameableEntry(); | 74 | ClassEntry classEntry = (ClassEntry)getNameableEntry(); |
| 75 | if (classEntry.isInnerClass()) { | 75 | if (classEntry.isInnerClass()) { |
| 76 | // make sure we only rename the inner class name | 76 | // make sure we only rename the inner class name |
| 77 | return classEntry.getInnerClassName(); | 77 | return classEntry.getInnermostClassName(); |
| 78 | } | 78 | } |
| 79 | } | 79 | } |
| 80 | 80 | ||
diff --git a/src/cuchaz/enigma/analysis/JarIndex.java b/src/cuchaz/enigma/analysis/JarIndex.java index 7ebbd97..a4a3abb 100644 --- a/src/cuchaz/enigma/analysis/JarIndex.java +++ b/src/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -312,7 +312,7 @@ public class JarIndex { | |||
| 312 | 312 | ||
| 313 | // does this class already have an outer class? | 313 | // does this class already have an outer class? |
| 314 | if (classEntry.isInnerClass()) { | 314 | if (classEntry.isInnerClass()) { |
| 315 | return classEntry.getOuterClassEntry(); | 315 | return classEntry.getOutermostClassEntry(); |
| 316 | } | 316 | } |
| 317 | InnerClassesAttribute innerClassesAttribute = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag); | 317 | InnerClassesAttribute innerClassesAttribute = (InnerClassesAttribute)c.getClassFile().getAttribute(InnerClassesAttribute.tag); |
| 318 | if (innerClassesAttribute != null) { | 318 | if (innerClassesAttribute != null) { |
diff --git a/src/cuchaz/enigma/bytecode/ClassRenamer.java b/src/cuchaz/enigma/bytecode/ClassRenamer.java index a5fea92..e9cdea3 100644 --- a/src/cuchaz/enigma/bytecode/ClassRenamer.java +++ b/src/cuchaz/enigma/bytecode/ClassRenamer.java | |||
| @@ -43,7 +43,7 @@ public class ClassRenamer { | |||
| 43 | for (int i = 0; i < attr.tableLength(); i++) { | 43 | for (int i = 0; i < attr.tableLength(); i++) { |
| 44 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); | 44 | ClassEntry classEntry = new ClassEntry(Descriptor.toJvmName(attr.innerClass(i))); |
| 45 | if (attr.innerNameIndex(i) != 0) { | 45 | if (attr.innerNameIndex(i) != 0) { |
| 46 | attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnerClassName())); | 46 | attr.setInnerNameIndex(i, constants.addUtf8Info(classEntry.getInnermostClassName())); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /* DEBUG | 49 | /* DEBUG |
diff --git a/src/cuchaz/enigma/bytecode/ClassTranslator.java b/src/cuchaz/enigma/bytecode/ClassTranslator.java index 4167731..94ab2c4 100644 --- a/src/cuchaz/enigma/bytecode/ClassTranslator.java +++ b/src/cuchaz/enigma/bytecode/ClassTranslator.java | |||
| @@ -26,7 +26,6 @@ import cuchaz.enigma.mapping.BehaviorEntry; | |||
| 26 | import cuchaz.enigma.mapping.ClassEntry; | 26 | import cuchaz.enigma.mapping.ClassEntry; |
| 27 | import cuchaz.enigma.mapping.EntryFactory; | 27 | import cuchaz.enigma.mapping.EntryFactory; |
| 28 | import cuchaz.enigma.mapping.FieldEntry; | 28 | import cuchaz.enigma.mapping.FieldEntry; |
| 29 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 30 | import cuchaz.enigma.mapping.Signature; | 29 | import cuchaz.enigma.mapping.Signature; |
| 31 | import cuchaz.enigma.mapping.Translator; | 30 | import cuchaz.enigma.mapping.Translator; |
| 32 | import cuchaz.enigma.mapping.Type; | 31 | import cuchaz.enigma.mapping.Type; |
| @@ -101,26 +100,30 @@ public class ClassTranslator { | |||
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | // translate the type | 102 | // translate the type |
| 104 | Type translatedType = m_translator.translateType(new Type(field.getFieldInfo().getDescriptor())); | 103 | Type translatedType = m_translator.translateType(entry.getType()); |
| 105 | field.getFieldInfo().setDescriptor(translatedType.toString()); | 104 | field.getFieldInfo().setDescriptor(translatedType.toString()); |
| 106 | } | 105 | } |
| 107 | 106 | ||
| 108 | // translate all the methods and constructors | 107 | // translate all the methods and constructors |
| 109 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { | 108 | for (CtBehavior behavior : c.getDeclaredBehaviors()) { |
| 109 | |||
| 110 | BehaviorEntry entry = EntryFactory.getBehaviorEntry(behavior); | ||
| 111 | |||
| 110 | if (behavior instanceof CtMethod) { | 112 | if (behavior instanceof CtMethod) { |
| 111 | CtMethod method = (CtMethod)behavior; | 113 | CtMethod method = (CtMethod)behavior; |
| 112 | 114 | ||
| 113 | // translate the name | 115 | // translate the name |
| 114 | MethodEntry entry = EntryFactory.getMethodEntry(method); | ||
| 115 | String translatedName = m_translator.translate(entry); | 116 | String translatedName = m_translator.translate(entry); |
| 116 | if (translatedName != null) { | 117 | if (translatedName != null) { |
| 117 | method.setName(translatedName); | 118 | method.setName(translatedName); |
| 118 | } | 119 | } |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | // translate the type | 122 | if (entry.getSignature() != null) { |
| 122 | Signature translatedSignature = m_translator.translateSignature(new Signature(behavior.getMethodInfo().getDescriptor())); | 123 | // translate the type |
| 123 | behavior.getMethodInfo().setDescriptor(translatedSignature.toString()); | 124 | Signature translatedSignature = m_translator.translateSignature(entry.getSignature()); |
| 125 | behavior.getMethodInfo().setDescriptor(translatedSignature.toString()); | ||
| 126 | } | ||
| 124 | } | 127 | } |
| 125 | 128 | ||
| 126 | // translate all the class names referenced in the code | 129 | // translate all the class names referenced in the code |
| @@ -137,7 +140,7 @@ public class ClassTranslator { | |||
| 137 | // translate the source file attribute too | 140 | // translate the source file attribute too |
| 138 | ClassEntry deobfClassEntry = map.get(classEntry); | 141 | ClassEntry deobfClassEntry = map.get(classEntry); |
| 139 | if (deobfClassEntry != null) { | 142 | if (deobfClassEntry != null) { |
| 140 | String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOuterClassName()) + ".java"; | 143 | String sourceFile = Descriptor.toJvmName(deobfClassEntry.getOutermostClassName()) + ".java"; |
| 141 | c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); | 144 | c.getClassFile().addAttribute(new SourceFileAttribute(constants, sourceFile)); |
| 142 | } | 145 | } |
| 143 | } | 146 | } |
diff --git a/src/cuchaz/enigma/bytecode/InnerClassWriter.java b/src/cuchaz/enigma/bytecode/InnerClassWriter.java index dd21a78..976028d 100644 --- a/src/cuchaz/enigma/bytecode/InnerClassWriter.java +++ b/src/cuchaz/enigma/bytecode/InnerClassWriter.java | |||
| @@ -93,7 +93,7 @@ public class InnerClassWriter { | |||
| 93 | 93 | ||
| 94 | // get the new inner class name | 94 | // get the new inner class name |
| 95 | ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); | 95 | ClassEntry obfInnerClassEntry = obfClassEntry.buildClassEntry(obfClassChain); |
| 96 | ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOuterClassEntry(); | 96 | ClassEntry obfOuterClassEntry = obfInnerClassEntry.getOutermostClassEntry(); |
| 97 | 97 | ||
| 98 | // here's what the JVM spec says about the InnerClasses attribute | 98 | // here's what the JVM spec says about the InnerClasses attribute |
| 99 | // append(inner, parent, 0 if anonymous else simple name, flags); | 99 | // append(inner, parent, 0 if anonymous else simple name, flags); |
| @@ -105,7 +105,7 @@ public class InnerClassWriter { | |||
| 105 | int innerClassNameIndex = 0; | 105 | int innerClassNameIndex = 0; |
| 106 | int accessFlags = 0; | 106 | int accessFlags = 0; |
| 107 | if (!m_index.isAnonymousClass(obfClassEntry)) { | 107 | if (!m_index.isAnonymousClass(obfClassEntry)) { |
| 108 | innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnerClassName()); | 108 | innerClassNameIndex = constPool.addUtf8Info(obfInnerClassEntry.getInnermostClassName()); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); | 111 | attr.append(innerClassIndex, parentClassIndex, innerClassNameIndex, accessFlags); |
diff --git a/src/cuchaz/enigma/convert/ClassIdentity.java b/src/cuchaz/enigma/convert/ClassIdentity.java index 35667b0..d76cd63 100644 --- a/src/cuchaz/enigma/convert/ClassIdentity.java +++ b/src/cuchaz/enigma/convert/ClassIdentity.java | |||
| @@ -180,7 +180,7 @@ public class ClassIdentity { | |||
| 180 | } | 180 | } |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | m_outer = EntryFactory.getClassEntry(c).getOuterClassName(); | 183 | m_outer = EntryFactory.getClassEntry(c).getOutermostClassName(); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | private void addReference(EntryReference<? extends Entry,BehaviorEntry> reference) { | 186 | private void addReference(EntryReference<? extends Entry,BehaviorEntry> reference) { |
diff --git a/src/cuchaz/enigma/convert/MappingsConverter.java b/src/cuchaz/enigma/convert/MappingsConverter.java index ddd3a53..2afa120 100644 --- a/src/cuchaz/enigma/convert/MappingsConverter.java +++ b/src/cuchaz/enigma/convert/MappingsConverter.java | |||
| @@ -169,7 +169,7 @@ public class MappingsConverter { | |||
| 169 | newMappings.addClassMapping(destMapping); | 169 | newMappings.addClassMapping(destMapping); |
| 170 | } | 170 | } |
| 171 | } else { | 171 | } else { |
| 172 | destMapping = destMapping.getInnerClassByObf(destChainClassEntry.getInnerClassName()); | 172 | destMapping = destMapping.getInnerClassByObfSimple(destChainClassEntry.getInnermostClassName()); |
| 173 | if (destMapping == null) { | 173 | if (destMapping == null) { |
| 174 | destMapping = new ClassMapping(destChainClassEntry.getName()); | 174 | destMapping = new ClassMapping(destChainClassEntry.getName()); |
| 175 | destMapping.addInnerClassMapping(destMapping); | 175 | destMapping.addInnerClassMapping(destMapping); |
diff --git a/src/cuchaz/enigma/gui/CodeReader.java b/src/cuchaz/enigma/gui/CodeReader.java index 743ef2e..fb8e082 100644 --- a/src/cuchaz/enigma/gui/CodeReader.java +++ b/src/cuchaz/enigma/gui/CodeReader.java | |||
| @@ -106,7 +106,7 @@ public class CodeReader extends JEditorPane { | |||
| 106 | // get the outermost class | 106 | // get the outermost class |
| 107 | ClassEntry outermostClassEntry = classEntry; | 107 | ClassEntry outermostClassEntry = classEntry; |
| 108 | while (outermostClassEntry.isInnerClass()) { | 108 | while (outermostClassEntry.isInnerClass()) { |
| 109 | outermostClassEntry = outermostClassEntry.getOuterClassEntry(); | 109 | outermostClassEntry = outermostClassEntry.getOutermostClassEntry(); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | // decompile it | 112 | // decompile it |
diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index 9fa633e..552ee47 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java | |||
| @@ -257,7 +257,7 @@ public class GuiController { | |||
| 257 | 257 | ||
| 258 | // get the reference target class | 258 | // get the reference target class |
| 259 | EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference(deobfReference); | 259 | EntryReference<Entry,Entry> obfReference = m_deobfuscator.obfuscateReference(deobfReference); |
| 260 | ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOuterClassEntry(); | 260 | ClassEntry obfClassEntry = obfReference.getLocationClassEntry().getOutermostClassEntry(); |
| 261 | if (!m_deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { | 261 | if (!m_deobfuscator.isObfuscatedIdentifier(obfClassEntry)) { |
| 262 | throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); | 262 | throw new IllegalArgumentException("Obfuscated class " + obfClassEntry + " was not found in the jar!"); |
| 263 | } | 263 | } |
diff --git a/src/cuchaz/enigma/mapping/ClassEntry.java b/src/cuchaz/enigma/mapping/ClassEntry.java index 69e66bc..5f3b5e2 100644 --- a/src/cuchaz/enigma/mapping/ClassEntry.java +++ b/src/cuchaz/enigma/mapping/ClassEntry.java | |||
| @@ -13,6 +13,8 @@ package cuchaz.enigma.mapping; | |||
| 13 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 14 | import java.util.List; | 14 | import java.util.List; |
| 15 | 15 | ||
| 16 | import com.beust.jcommander.internal.Lists; | ||
| 17 | |||
| 16 | public class ClassEntry implements Entry, Serializable { | 18 | public class ClassEntry implements Entry, Serializable { |
| 17 | 19 | ||
| 18 | private static final long serialVersionUID = 4235460580973955811L; | 20 | private static final long serialVersionUID = 4235460580973955811L; |
| @@ -29,7 +31,7 @@ public class ClassEntry implements Entry, Serializable { | |||
| 29 | 31 | ||
| 30 | m_name = className; | 32 | m_name = className; |
| 31 | 33 | ||
| 32 | if (isInnerClass() && getInnerClassName().indexOf('/') >= 0) { | 34 | if (isInnerClass() && getInnermostClassName().indexOf('/') >= 0) { |
| 33 | throw new IllegalArgumentException("Inner class must not have a package: " + className); | 35 | throw new IllegalArgumentException("Inner class must not have a package: " + className); |
| 34 | } | 36 | } |
| 35 | } | 37 | } |
| @@ -84,22 +86,39 @@ public class ClassEntry implements Entry, Serializable { | |||
| 84 | return m_name.lastIndexOf('$') >= 0; | 86 | return m_name.lastIndexOf('$') >= 0; |
| 85 | } | 87 | } |
| 86 | 88 | ||
| 87 | public String getOuterClassName() { | 89 | public List<String> getClassChainNames() { |
| 90 | return Lists.newArrayList(m_name.split("\\$")); | ||
| 91 | } | ||
| 92 | |||
| 93 | public List<ClassEntry> getClassChain() { | ||
| 94 | List<ClassEntry> entries = Lists.newArrayList(); | ||
| 95 | StringBuilder buf = new StringBuilder(); | ||
| 96 | for (String name : getClassChainNames()) { | ||
| 97 | if (buf.length() > 0) { | ||
| 98 | buf.append("$"); | ||
| 99 | } | ||
| 100 | buf.append(name); | ||
| 101 | entries.add(new ClassEntry(buf.toString())); | ||
| 102 | } | ||
| 103 | return entries; | ||
| 104 | } | ||
| 105 | |||
| 106 | public String getOutermostClassName() { | ||
| 88 | if (isInnerClass()) { | 107 | if (isInnerClass()) { |
| 89 | return m_name.substring(0, m_name.lastIndexOf('$')); | 108 | return m_name.substring(0, m_name.lastIndexOf('$')); |
| 90 | } | 109 | } |
| 91 | return m_name; | 110 | return m_name; |
| 92 | } | 111 | } |
| 93 | 112 | ||
| 94 | public String getInnerClassName() { | 113 | public String getInnermostClassName() { |
| 95 | if (!isInnerClass()) { | 114 | if (!isInnerClass()) { |
| 96 | throw new Error("This is not an inner class!"); | 115 | throw new Error("This is not an inner class!"); |
| 97 | } | 116 | } |
| 98 | return m_name.substring(m_name.lastIndexOf('$') + 1); | 117 | return m_name.substring(m_name.lastIndexOf('$') + 1); |
| 99 | } | 118 | } |
| 100 | 119 | ||
| 101 | public ClassEntry getOuterClassEntry() { | 120 | public ClassEntry getOutermostClassEntry() { |
| 102 | return new ClassEntry(getOuterClassName()); | 121 | return new ClassEntry(getOutermostClassName()); |
| 103 | } | 122 | } |
| 104 | 123 | ||
| 105 | public boolean isInDefaultPackage() { | 124 | public boolean isInDefaultPackage() { |
| @@ -130,7 +149,7 @@ public class ClassEntry implements Entry, Serializable { | |||
| 130 | buf.append(chainEntry.getName()); | 149 | buf.append(chainEntry.getName()); |
| 131 | } else { | 150 | } else { |
| 132 | buf.append("$"); | 151 | buf.append("$"); |
| 133 | buf.append(chainEntry.isInnerClass() ? chainEntry.getInnerClassName() : chainEntry.getSimpleName()); | 152 | buf.append(chainEntry.isInnerClass() ? chainEntry.getInnermostClassName() : chainEntry.getSimpleName()); |
| 134 | } | 153 | } |
| 135 | 154 | ||
| 136 | if (chainEntry == this) { | 155 | if (chainEntry == this) { |
diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java index 38cd3d6..6e7fd17 100644 --- a/src/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/cuchaz/enigma/mapping/ClassMapping.java | |||
| @@ -23,22 +23,23 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 23 | private String m_obfFullName; | 23 | private String m_obfFullName; |
| 24 | private String m_obfSimpleName; | 24 | private String m_obfSimpleName; |
| 25 | private String m_deobfName; | 25 | private String m_deobfName; |
| 26 | private Map<String,ClassMapping> m_innerClassesByObf; | 26 | private Map<String,ClassMapping> m_innerClassesByObfSimple; |
| 27 | private Map<String,ClassMapping> m_innerClassesByDeobf; | 27 | private Map<String,ClassMapping> m_innerClassesByDeobf; |
| 28 | private Map<String,FieldMapping> m_fieldsByObf; | 28 | private Map<String,FieldMapping> m_fieldsByObf; |
| 29 | private Map<String,FieldMapping> m_fieldsByDeobf; | 29 | private Map<String,FieldMapping> m_fieldsByDeobf; |
| 30 | private Map<String,MethodMapping> m_methodsByObf; | 30 | private Map<String,MethodMapping> m_methodsByObf; |
| 31 | private Map<String,MethodMapping> m_methodsByDeobf; | 31 | private Map<String,MethodMapping> m_methodsByDeobf; |
| 32 | 32 | ||
| 33 | public ClassMapping(String obfName) { | 33 | public ClassMapping(String obfFullName) { |
| 34 | this(obfName, null); | 34 | this(obfFullName, null); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | public ClassMapping(String obfName, String deobfName) { | 37 | public ClassMapping(String obfFullName, String deobfName) { |
| 38 | m_obfFullName = obfName; | 38 | m_obfFullName = obfFullName; |
| 39 | m_obfSimpleName = new ClassEntry(obfName).getSimpleName(); | 39 | ClassEntry classEntry = new ClassEntry(obfFullName); |
| 40 | m_obfSimpleName = classEntry.isInnerClass() ? classEntry.getInnermostClassName() : classEntry.getSimpleName(); | ||
| 40 | m_deobfName = NameValidator.validateClassName(deobfName, false); | 41 | m_deobfName = NameValidator.validateClassName(deobfName, false); |
| 41 | m_innerClassesByObf = Maps.newHashMap(); | 42 | m_innerClassesByObfSimple = Maps.newHashMap(); |
| 42 | m_innerClassesByDeobf = Maps.newHashMap(); | 43 | m_innerClassesByDeobf = Maps.newHashMap(); |
| 43 | m_fieldsByObf = Maps.newHashMap(); | 44 | m_fieldsByObf = Maps.newHashMap(); |
| 44 | m_fieldsByDeobf = Maps.newHashMap(); | 45 | m_fieldsByDeobf = Maps.newHashMap(); |
| @@ -65,12 +66,12 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 65 | //// INNER CLASSES //////// | 66 | //// INNER CLASSES //////// |
| 66 | 67 | ||
| 67 | public Iterable<ClassMapping> innerClasses() { | 68 | public Iterable<ClassMapping> innerClasses() { |
| 68 | assert (m_innerClassesByObf.size() >= m_innerClassesByDeobf.size()); | 69 | assert (m_innerClassesByObfSimple.size() >= m_innerClassesByDeobf.size()); |
| 69 | return m_innerClassesByObf.values(); | 70 | return m_innerClassesByObfSimple.values(); |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | public void addInnerClassMapping(ClassMapping classMapping) { | 73 | public void addInnerClassMapping(ClassMapping classMapping) { |
| 73 | boolean obfWasAdded = m_innerClassesByObf.put(classMapping.getObfSimpleName(), classMapping) == null; | 74 | boolean obfWasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; |
| 74 | assert (obfWasAdded); | 75 | assert (obfWasAdded); |
| 75 | if (classMapping.getDeobfName() != null) { | 76 | if (classMapping.getDeobfName() != null) { |
| 76 | assert (isSimpleClassName(classMapping.getDeobfName())); | 77 | assert (isSimpleClassName(classMapping.getDeobfName())); |
| @@ -80,7 +81,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | public void removeInnerClassMapping(ClassMapping classMapping) { | 83 | public void removeInnerClassMapping(ClassMapping classMapping) { |
| 83 | boolean obfWasRemoved = m_innerClassesByObf.remove(classMapping.getObfSimpleName()) != null; | 84 | boolean obfWasRemoved = m_innerClassesByObfSimple.remove(classMapping.getObfSimpleName()) != null; |
| 84 | assert (obfWasRemoved); | 85 | assert (obfWasRemoved); |
| 85 | if (classMapping.getDeobfName() != null) { | 86 | if (classMapping.getDeobfName() != null) { |
| 86 | boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; | 87 | boolean deobfWasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; |
| @@ -88,20 +89,19 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 88 | } | 89 | } |
| 89 | } | 90 | } |
| 90 | 91 | ||
| 91 | public ClassMapping getOrCreateInnerClass(String obfName) { | 92 | public ClassMapping getOrCreateInnerClass(ClassEntry obfInnerClass) { |
| 92 | assert (isSimpleClassName(obfName)); | 93 | ClassMapping classMapping = m_innerClassesByObfSimple.get(obfInnerClass.getInnermostClassName()); |
| 93 | ClassMapping classMapping = m_innerClassesByObf.get(obfName); | ||
| 94 | if (classMapping == null) { | 94 | if (classMapping == null) { |
| 95 | classMapping = new ClassMapping(obfName); | 95 | classMapping = new ClassMapping(obfInnerClass.getName()); |
| 96 | boolean wasAdded = m_innerClassesByObf.put(obfName, classMapping) == null; | 96 | boolean wasAdded = m_innerClassesByObfSimple.put(classMapping.getObfSimpleName(), classMapping) == null; |
| 97 | assert (wasAdded); | 97 | assert (wasAdded); |
| 98 | } | 98 | } |
| 99 | return classMapping; | 99 | return classMapping; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | public ClassMapping getInnerClassByObf(String obfName) { | 102 | public ClassMapping getInnerClassByObfSimple(String obfSimpleName) { |
| 103 | assert (isSimpleClassName(obfName)); | 103 | assert (isSimpleClassName(obfSimpleName)); |
| 104 | return m_innerClassesByObf.get(obfName); | 104 | return m_innerClassesByObfSimple.get(obfSimpleName); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | public ClassMapping getInnerClassByDeobf(String deobfName) { | 107 | public ClassMapping getInnerClassByDeobf(String deobfName) { |
| @@ -109,35 +109,25 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 109 | return m_innerClassesByDeobf.get(deobfName); | 109 | return m_innerClassesByDeobf.get(deobfName); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | public ClassMapping getInnerClassByDeobfThenObf(String name) { | 112 | public ClassMapping getInnerClassByDeobfThenObfSimple(String name) { |
| 113 | ClassMapping classMapping = getInnerClassByDeobf(name); | 113 | ClassMapping classMapping = getInnerClassByDeobf(name); |
| 114 | if (classMapping == null) { | 114 | if (classMapping == null) { |
| 115 | classMapping = getInnerClassByObf(name); | 115 | classMapping = getInnerClassByObfSimple(name); |
| 116 | } | 116 | } |
| 117 | return classMapping; | 117 | return classMapping; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | public String getObfInnerClassSimpleName(String deobfName) { | 120 | public String getDeobfInnerClassName(String obfSimpleName) { |
| 121 | assert (isSimpleClassName(deobfName)); | 121 | assert (isSimpleClassName(obfSimpleName)); |
| 122 | ClassMapping classMapping = m_innerClassesByDeobf.get(deobfName); | 122 | ClassMapping classMapping = m_innerClassesByObfSimple.get(obfSimpleName); |
| 123 | if (classMapping != null) { | ||
| 124 | return classMapping.getObfSimpleName(); | ||
| 125 | } | ||
| 126 | return null; | ||
| 127 | } | ||
| 128 | |||
| 129 | public String getDeobfInnerClassName(String obfName) { | ||
| 130 | assert (isSimpleClassName(obfName)); | ||
| 131 | ClassMapping classMapping = m_innerClassesByObf.get(obfName); | ||
| 132 | if (classMapping != null) { | 123 | if (classMapping != null) { |
| 133 | return classMapping.getDeobfName(); | 124 | return classMapping.getDeobfName(); |
| 134 | } | 125 | } |
| 135 | return null; | 126 | return null; |
| 136 | } | 127 | } |
| 137 | 128 | ||
| 138 | public void setInnerClassName(String obfName, String deobfName) { | 129 | public void setInnerClassName(ClassEntry obfInnerClass, String deobfName) { |
| 139 | assert (isSimpleClassName(obfName)); | 130 | ClassMapping classMapping = getOrCreateInnerClass(obfInnerClass); |
| 140 | ClassMapping classMapping = getOrCreateInnerClass(obfName); | ||
| 141 | if (classMapping.getDeobfName() != null) { | 131 | if (classMapping.getDeobfName() != null) { |
| 142 | boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; | 132 | boolean wasRemoved = m_innerClassesByDeobf.remove(classMapping.getDeobfName()) != null; |
| 143 | assert (wasRemoved); | 133 | assert (wasRemoved); |
| @@ -150,6 +140,15 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 150 | } | 140 | } |
| 151 | } | 141 | } |
| 152 | 142 | ||
| 143 | public boolean hasInnerClassByObfSimple(String obfSimpleName) { | ||
| 144 | return m_innerClassesByObfSimple.containsKey(obfSimpleName); | ||
| 145 | } | ||
| 146 | |||
| 147 | public boolean hasInnerClassByDeobf(String deobfName) { | ||
| 148 | return m_innerClassesByDeobf.containsKey(deobfName); | ||
| 149 | } | ||
| 150 | |||
| 151 | |||
| 153 | //// FIELDS //////// | 152 | //// FIELDS //////// |
| 154 | 153 | ||
| 155 | public Iterable<FieldMapping> fields() { | 154 | public Iterable<FieldMapping> fields() { |
| @@ -382,7 +381,7 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 382 | buf.append("\n"); | 381 | buf.append("\n"); |
| 383 | } | 382 | } |
| 384 | buf.append("Inner Classes:\n"); | 383 | buf.append("Inner Classes:\n"); |
| 385 | for (ClassMapping classMapping : m_innerClassesByObf.values()) { | 384 | for (ClassMapping classMapping : m_innerClassesByObfSimple.values()) { |
| 386 | buf.append("\t"); | 385 | buf.append("\t"); |
| 387 | buf.append(classMapping.getObfSimpleName()); | 386 | buf.append(classMapping.getObfSimpleName()); |
| 388 | buf.append(" <-> "); | 387 | buf.append(" <-> "); |
| @@ -404,11 +403,11 @@ public class ClassMapping implements Serializable, Comparable<ClassMapping> { | |||
| 404 | public boolean renameObfClass(String oldObfClassName, String newObfClassName) { | 403 | public boolean renameObfClass(String oldObfClassName, String newObfClassName) { |
| 405 | 404 | ||
| 406 | // rename inner classes | 405 | // rename inner classes |
| 407 | for (ClassMapping innerClassMapping : new ArrayList<ClassMapping>(m_innerClassesByObf.values())) { | 406 | for (ClassMapping innerClassMapping : new ArrayList<ClassMapping>(m_innerClassesByObfSimple.values())) { |
| 408 | if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { | 407 | if (innerClassMapping.renameObfClass(oldObfClassName, newObfClassName)) { |
| 409 | boolean wasRemoved = m_innerClassesByObf.remove(oldObfClassName) != null; | 408 | boolean wasRemoved = m_innerClassesByObfSimple.remove(oldObfClassName) != null; |
| 410 | assert (wasRemoved); | 409 | assert (wasRemoved); |
| 411 | boolean wasAdded = m_innerClassesByObf.put(newObfClassName, innerClassMapping) == null; | 410 | boolean wasAdded = m_innerClassesByObfSimple.put(newObfClassName, innerClassMapping) == null; |
| 412 | assert (wasAdded); | 411 | assert (wasAdded); |
| 413 | } | 412 | } |
| 414 | } | 413 | } |
diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index a85bcbf..659d23a 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java | |||
| @@ -13,9 +13,11 @@ package cuchaz.enigma.mapping; | |||
| 13 | import java.io.Serializable; | 13 | import java.io.Serializable; |
| 14 | import java.util.ArrayList; | 14 | import java.util.ArrayList; |
| 15 | import java.util.Collection; | 15 | import java.util.Collection; |
| 16 | import java.util.List; | ||
| 16 | import java.util.Map; | 17 | import java.util.Map; |
| 17 | import java.util.Set; | 18 | import java.util.Set; |
| 18 | 19 | ||
| 20 | import com.beust.jcommander.internal.Lists; | ||
| 19 | import com.google.common.collect.Maps; | 21 | import com.google.common.collect.Maps; |
| 20 | import com.google.common.collect.Sets; | 22 | import com.google.common.collect.Sets; |
| 21 | 23 | ||
| @@ -89,6 +91,18 @@ public class Mappings implements Serializable { | |||
| 89 | return m_classesByDeobf.get(deobfName); | 91 | return m_classesByDeobf.get(deobfName); |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 94 | public void setClassDeobfName(ClassMapping classMapping, String deobfName) { | ||
| 95 | if (classMapping.getDeobfName() != null) { | ||
| 96 | boolean wasRemoved = m_classesByDeobf.remove(classMapping.getDeobfName()) != null; | ||
| 97 | assert (wasRemoved); | ||
| 98 | } | ||
| 99 | classMapping.setDeobfName(deobfName); | ||
| 100 | if (deobfName != null) { | ||
| 101 | boolean wasAdded = m_classesByDeobf.put(deobfName, classMapping) == null; | ||
| 102 | assert (wasAdded); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 92 | public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { | 106 | public Translator getTranslator(TranslationDirection direction, TranslationIndex index) { |
| 93 | switch (direction) { | 107 | switch (direction) { |
| 94 | case Deobfuscating: | 108 | case Deobfuscating: |
| @@ -185,4 +199,18 @@ public class Mappings implements Serializable { | |||
| 185 | } | 199 | } |
| 186 | return false; | 200 | return false; |
| 187 | } | 201 | } |
| 202 | |||
| 203 | public List<ClassMapping> getClassMappingChain(ClassEntry obfClass) { | ||
| 204 | List<ClassMapping> mappingChain = Lists.newArrayList(); | ||
| 205 | ClassMapping classMapping = null; | ||
| 206 | for (ClassEntry obfClassEntry : obfClass.getClassChain()) { | ||
| 207 | if (mappingChain.isEmpty()) { | ||
| 208 | classMapping = m_classesByObf.get(obfClassEntry.getName()); | ||
| 209 | } else if (classMapping != null) { | ||
| 210 | classMapping = classMapping.getInnerClassByObfSimple(obfClassEntry.getInnermostClassName()); | ||
| 211 | } | ||
| 212 | mappingChain.add(classMapping); | ||
| 213 | } | ||
| 214 | return mappingChain; | ||
| 215 | } | ||
| 188 | } | 216 | } |
diff --git a/src/cuchaz/enigma/mapping/MappingsRenamer.java b/src/cuchaz/enigma/mapping/MappingsRenamer.java index 16f700d..d7766dc 100644 --- a/src/cuchaz/enigma/mapping/MappingsRenamer.java +++ b/src/cuchaz/enigma/mapping/MappingsRenamer.java | |||
| @@ -13,10 +13,10 @@ package cuchaz.enigma.mapping; | |||
| 13 | import java.io.IOException; | 13 | import java.io.IOException; |
| 14 | import java.io.ObjectOutputStream; | 14 | import java.io.ObjectOutputStream; |
| 15 | import java.io.OutputStream; | 15 | import java.io.OutputStream; |
| 16 | import java.util.List; | ||
| 16 | import java.util.Set; | 17 | import java.util.Set; |
| 17 | import java.util.zip.GZIPOutputStream; | 18 | import java.util.zip.GZIPOutputStream; |
| 18 | 19 | ||
| 19 | import cuchaz.enigma.Constants; | ||
| 20 | import cuchaz.enigma.analysis.JarIndex; | 20 | import cuchaz.enigma.analysis.JarIndex; |
| 21 | 21 | ||
| 22 | public class MappingsRenamer { | 22 | public class MappingsRenamer { |
| @@ -30,48 +30,43 @@ public class MappingsRenamer { | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | public void setClassName(ClassEntry obf, String deobfName) { | 32 | public void setClassName(ClassEntry obf, String deobfName) { |
| 33 | deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass()); | ||
| 34 | ClassEntry targetEntry = new ClassEntry(deobfName); | ||
| 35 | if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(targetEntry)) { | ||
| 36 | throw new IllegalNameException(deobfName, "There is already a class with that name"); | ||
| 37 | } | ||
| 38 | 33 | ||
| 39 | ClassMapping classMapping = getOrCreateClassMapping(obf); | 34 | deobfName = NameValidator.validateClassName(deobfName, !obf.isInnerClass()); |
| 40 | 35 | ||
| 41 | if (obf.isInnerClass()) { | 36 | List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obf); |
| 42 | classMapping.setInnerClassName(obf.getInnerClassName(), deobfName); | 37 | if (mappingChain.size() == 1) { |
| 38 | |||
| 39 | if (deobfName != null) { | ||
| 40 | // make sure we don't rename to an existing obf or deobf class | ||
| 41 | if (m_mappings.containsDeobfClass(deobfName) || m_index.containsObfClass(new ClassEntry(deobfName))) { | ||
| 42 | throw new IllegalNameException(deobfName, "There is already a class with that name"); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | |||
| 46 | ClassMapping classMapping = mappingChain.get(0); | ||
| 47 | m_mappings.setClassDeobfName(classMapping, deobfName); | ||
| 48 | |||
| 43 | } else { | 49 | } else { |
| 44 | if (classMapping.getDeobfName() != null) { | 50 | |
| 45 | boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null; | 51 | ClassMapping outerClassMapping = mappingChain.get(mappingChain.size() - 2); |
| 46 | assert (wasRemoved); | 52 | |
| 53 | if (deobfName != null) { | ||
| 54 | // make sure we don't rename to an existing obf or deobf inner class | ||
| 55 | if (outerClassMapping.hasInnerClassByDeobf(deobfName) || outerClassMapping.hasInnerClassByObfSimple(deobfName)) { | ||
| 56 | throw new IllegalNameException(deobfName, "There is already a class with that name"); | ||
| 57 | } | ||
| 47 | } | 58 | } |
| 48 | classMapping.setDeobfName(deobfName); | 59 | |
| 49 | boolean wasAdded = m_mappings.m_classesByDeobf.put(deobfName, classMapping) == null; | 60 | outerClassMapping.setInnerClassName(obf, deobfName); |
| 50 | assert (wasAdded); | ||
| 51 | } | 61 | } |
| 52 | } | 62 | } |
| 53 | 63 | ||
| 54 | public void removeClassMapping(ClassEntry obf) { | 64 | public void removeClassMapping(ClassEntry obf) { |
| 55 | ClassMapping classMapping = getClassMapping(obf); | 65 | setClassName(obf, null); |
| 56 | if (obf.isInnerClass()) { | ||
| 57 | classMapping.setInnerClassName(obf.getName(), null); | ||
| 58 | } else { | ||
| 59 | boolean wasRemoved = m_mappings.m_classesByDeobf.remove(classMapping.getDeobfName()) != null; | ||
| 60 | assert (wasRemoved); | ||
| 61 | classMapping.setDeobfName(null); | ||
| 62 | } | ||
| 63 | } | 66 | } |
| 64 | 67 | ||
| 65 | public void markClassAsDeobfuscated(ClassEntry obf) { | 68 | public void markClassAsDeobfuscated(ClassEntry obf) { |
| 66 | ClassMapping classMapping = getOrCreateClassMapping(obf); | 69 | setClassName(obf, obf.isInnerClass() ? obf.getInnermostClassName() : obf.getSimpleName()); |
| 67 | if (obf.isInnerClass()) { | ||
| 68 | String innerClassName = Constants.NonePackage + "/" + obf.getInnerClassName(); | ||
| 69 | classMapping.setInnerClassName(innerClassName, innerClassName); | ||
| 70 | } else { | ||
| 71 | classMapping.setDeobfName(obf.getName()); | ||
| 72 | boolean wasAdded = m_mappings.m_classesByDeobf.put(obf.getName(), classMapping) == null; | ||
| 73 | assert (wasAdded); | ||
| 74 | } | ||
| 75 | } | 70 | } |
| 76 | 71 | ||
| 77 | public void setFieldName(FieldEntry obf, String deobfName) { | 72 | public void setFieldName(FieldEntry obf, String deobfName) { |
| @@ -81,17 +76,17 @@ public class MappingsRenamer { | |||
| 81 | throw new IllegalNameException(deobfName, "There is already a field with that name"); | 76 | throw new IllegalNameException(deobfName, "There is already a field with that name"); |
| 82 | } | 77 | } |
| 83 | 78 | ||
| 84 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 79 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 85 | classMapping.setFieldName(obf.getName(), obf.getType(), deobfName); | 80 | classMapping.setFieldName(obf.getName(), obf.getType(), deobfName); |
| 86 | } | 81 | } |
| 87 | 82 | ||
| 88 | public void removeFieldMapping(FieldEntry obf) { | 83 | public void removeFieldMapping(FieldEntry obf) { |
| 89 | ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); | 84 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 90 | classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getType())); | 85 | classMapping.removeFieldMapping(classMapping.getFieldByObf(obf.getName(), obf.getType())); |
| 91 | } | 86 | } |
| 92 | 87 | ||
| 93 | public void markFieldAsDeobfuscated(FieldEntry obf) { | 88 | public void markFieldAsDeobfuscated(FieldEntry obf) { |
| 94 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 89 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 95 | classMapping.setFieldName(obf.getName(), obf.getType(), obf.getName()); | 90 | classMapping.setFieldName(obf.getName(), obf.getType(), obf.getName()); |
| 96 | } | 91 | } |
| 97 | 92 | ||
| @@ -121,7 +116,7 @@ public class MappingsRenamer { | |||
| 121 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); | 116 | throw new IllegalNameException(deobfName, "There is already a method with that name and signature in class " + deobfClassName); |
| 122 | } | 117 | } |
| 123 | 118 | ||
| 124 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 119 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 125 | classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName); | 120 | classMapping.setMethodName(obf.getName(), obf.getSignature(), deobfName); |
| 126 | } | 121 | } |
| 127 | 122 | ||
| @@ -132,7 +127,7 @@ public class MappingsRenamer { | |||
| 132 | } | 127 | } |
| 133 | 128 | ||
| 134 | public void removeMethodMapping(MethodEntry obf) { | 129 | public void removeMethodMapping(MethodEntry obf) { |
| 135 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 130 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 136 | classMapping.setMethodName(obf.getName(), obf.getSignature(), null); | 131 | classMapping.setMethodName(obf.getName(), obf.getSignature(), null); |
| 137 | } | 132 | } |
| 138 | 133 | ||
| @@ -143,7 +138,7 @@ public class MappingsRenamer { | |||
| 143 | } | 138 | } |
| 144 | 139 | ||
| 145 | public void markMethodAsDeobfuscated(MethodEntry obf) { | 140 | public void markMethodAsDeobfuscated(MethodEntry obf) { |
| 146 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 141 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 147 | classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName()); | 142 | classMapping.setMethodName(obf.getName(), obf.getSignature(), obf.getName()); |
| 148 | } | 143 | } |
| 149 | 144 | ||
| @@ -154,17 +149,17 @@ public class MappingsRenamer { | |||
| 154 | throw new IllegalNameException(deobfName, "There is already an argument with that name"); | 149 | throw new IllegalNameException(deobfName, "There is already an argument with that name"); |
| 155 | } | 150 | } |
| 156 | 151 | ||
| 157 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 152 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 158 | classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName); | 153 | classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), deobfName); |
| 159 | } | 154 | } |
| 160 | 155 | ||
| 161 | public void removeArgumentMapping(ArgumentEntry obf) { | 156 | public void removeArgumentMapping(ArgumentEntry obf) { |
| 162 | ClassMapping classMapping = getClassMappingOrInnerClassMapping(obf.getClassEntry()); | 157 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 163 | classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex()); | 158 | classMapping.removeArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex()); |
| 164 | } | 159 | } |
| 165 | 160 | ||
| 166 | public void markArgumentAsDeobfuscated(ArgumentEntry obf) { | 161 | public void markArgumentAsDeobfuscated(ArgumentEntry obf) { |
| 167 | ClassMapping classMapping = getOrCreateClassMappingOrInnerClassMapping(obf.getClassEntry()); | 162 | ClassMapping classMapping = getOrCreateClassMapping(obf.getClassEntry()); |
| 168 | classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName()); | 163 | classMapping.setArgumentName(obf.getMethodName(), obf.getMethodSignature(), obf.getIndex(), obf.getName()); |
| 169 | } | 164 | } |
| 170 | 165 | ||
| @@ -204,34 +199,31 @@ public class MappingsRenamer { | |||
| 204 | gzipout.finish(); | 199 | gzipout.finish(); |
| 205 | } | 200 | } |
| 206 | 201 | ||
| 207 | private ClassMapping getClassMapping(ClassEntry obfClassEntry) { | ||
| 208 | return m_mappings.m_classesByObf.get(obfClassEntry.getOuterClassName()); | ||
| 209 | } | ||
| 210 | |||
| 211 | private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) { | 202 | private ClassMapping getOrCreateClassMapping(ClassEntry obfClassEntry) { |
| 212 | String obfClassName = obfClassEntry.getOuterClassName(); | 203 | List<ClassMapping> mappingChain = getOrCreateClassMappingChain(obfClassEntry); |
| 213 | ClassMapping classMapping = m_mappings.m_classesByObf.get(obfClassName); | 204 | return mappingChain.get(mappingChain.size() - 1); |
| 214 | if (classMapping == null) { | 205 | } |
| 215 | classMapping = new ClassMapping(obfClassName); | 206 | |
| 216 | boolean obfWasAdded = m_mappings.m_classesByObf.put(classMapping.getObfFullName(), classMapping) == null; | 207 | private List<ClassMapping> getOrCreateClassMappingChain(ClassEntry obfClassEntry) { |
| 217 | assert (obfWasAdded); | 208 | List<ClassEntry> classChain = obfClassEntry.getClassChain(); |
| 218 | } | 209 | List<ClassMapping> mappingChain = m_mappings.getClassMappingChain(obfClassEntry); |
| 219 | return classMapping; | 210 | for (int i=0; i<classChain.size(); i++) { |
| 220 | } | 211 | ClassEntry classEntry = classChain.get(i); |
| 221 | 212 | ClassMapping classMapping = mappingChain.get(i); | |
| 222 | private ClassMapping getClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { | 213 | if (classMapping == null) { |
| 223 | ClassMapping classMapping = getClassMapping(obfClassEntry); | 214 | |
| 224 | if (obfClassEntry.isInDefaultPackage()) { | 215 | // create it |
| 225 | classMapping = classMapping.getInnerClassByObf(obfClassEntry.getInnerClassName()); | 216 | classMapping = new ClassMapping(classEntry.getName()); |
| 226 | } | 217 | mappingChain.set(i, classMapping); |
| 227 | return classMapping; | 218 | |
| 228 | } | 219 | // add it to the right parent |
| 229 | 220 | if (i == 0) { | |
| 230 | private ClassMapping getOrCreateClassMappingOrInnerClassMapping(ClassEntry obfClassEntry) { | 221 | m_mappings.addClassMapping(classMapping); |
| 231 | ClassMapping classMapping = getOrCreateClassMapping(obfClassEntry); | 222 | } else { |
| 232 | if (obfClassEntry.isInnerClass()) { | 223 | mappingChain.get(i-1).addInnerClassMapping(classMapping); |
| 233 | classMapping = classMapping.getOrCreateInnerClass(obfClassEntry.getInnerClassName()); | 224 | } |
| 225 | } | ||
| 234 | } | 226 | } |
| 235 | return classMapping; | 227 | return mappingChain; |
| 236 | } | 228 | } |
| 237 | } | 229 | } |
diff --git a/src/cuchaz/enigma/mapping/Translator.java b/src/cuchaz/enigma/mapping/Translator.java index d3b6e77..fb187b9 100644 --- a/src/cuchaz/enigma/mapping/Translator.java +++ b/src/cuchaz/enigma/mapping/Translator.java | |||
| @@ -24,6 +24,13 @@ public class Translator { | |||
| 24 | private Map<String,ClassMapping> m_classes; | 24 | private Map<String,ClassMapping> m_classes; |
| 25 | private TranslationIndex m_index; | 25 | private TranslationIndex m_index; |
| 26 | 26 | ||
| 27 | private ClassNameReplacer m_classNameReplacer = new ClassNameReplacer() { | ||
| 28 | @Override | ||
| 29 | public String replace(String className) { | ||
| 30 | return translateEntry(new ClassEntry(className)).getName(); | ||
| 31 | } | ||
| 32 | }; | ||
| 33 | |||
| 27 | public Translator() { | 34 | public Translator() { |
| 28 | m_direction = null; | 35 | m_direction = null; |
| 29 | m_classes = Maps.newHashMap(); | 36 | m_classes = Maps.newHashMap(); |
| @@ -69,48 +76,16 @@ public class Translator { | |||
| 69 | } | 76 | } |
| 70 | } | 77 | } |
| 71 | 78 | ||
| 72 | public String translateClass(String className) { | ||
| 73 | return translate(new ClassEntry(className)); | ||
| 74 | } | ||
| 75 | |||
| 76 | public String translate(ClassEntry in) { | 79 | public String translate(ClassEntry in) { |
| 77 | 80 | ClassEntry translated = translateEntry(in); | |
| 78 | if (in.isInnerClass()) { | 81 | if (translated.equals(in)) { |
| 79 | 82 | return null; | |
| 80 | // translate everything in the class chain, or return null | ||
| 81 | List<ClassMapping> mappingsChain = getClassMappingChain(in); | ||
| 82 | StringBuilder buf = new StringBuilder(); | ||
| 83 | for (ClassMapping classMapping : mappingsChain) { | ||
| 84 | if (classMapping == null) { | ||
| 85 | return null; | ||
| 86 | } | ||
| 87 | boolean isFirstClass = buf.length() == 0; | ||
| 88 | String name = m_direction.choose( | ||
| 89 | classMapping.getDeobfName(), | ||
| 90 | isFirstClass ? classMapping.getObfFullName() : classMapping.getObfSimpleName() | ||
| 91 | ); | ||
| 92 | if (name == null) { | ||
| 93 | return null; | ||
| 94 | } | ||
| 95 | if (!isFirstClass) { | ||
| 96 | buf.append("$"); | ||
| 97 | } | ||
| 98 | buf.append(name); | ||
| 99 | } | ||
| 100 | return buf.toString(); | ||
| 101 | |||
| 102 | } else { | ||
| 103 | |||
| 104 | // normal classes are easier | ||
| 105 | ClassMapping classMapping = m_classes.get(in.getName()); | ||
| 106 | if (classMapping == null) { | ||
| 107 | return null; | ||
| 108 | } | ||
| 109 | return m_direction.choose( | ||
| 110 | classMapping.getDeobfName(), | ||
| 111 | classMapping.getObfFullName() | ||
| 112 | ); | ||
| 113 | } | 83 | } |
| 84 | return translated.getName(); | ||
| 85 | } | ||
| 86 | |||
| 87 | public String translateClass(String className) { | ||
| 88 | return translate(new ClassEntry(className)); | ||
| 114 | } | 89 | } |
| 115 | 90 | ||
| 116 | public ClassEntry translateEntry(ClassEntry in) { | 91 | public ClassEntry translateEntry(ClassEntry in) { |
| @@ -264,21 +239,11 @@ public class Translator { | |||
| 264 | } | 239 | } |
| 265 | 240 | ||
| 266 | public Type translateType(Type type) { | 241 | public Type translateType(Type type) { |
| 267 | return new Type(type, new ClassNameReplacer() { | 242 | return new Type(type, m_classNameReplacer); |
| 268 | @Override | ||
| 269 | public String replace(String className) { | ||
| 270 | return translateClass(className); | ||
| 271 | } | ||
| 272 | }); | ||
| 273 | } | 243 | } |
| 274 | 244 | ||
| 275 | public Signature translateSignature(Signature signature) { | 245 | public Signature translateSignature(Signature signature) { |
| 276 | return new Signature(signature, new ClassNameReplacer() { | 246 | return new Signature(signature, m_classNameReplacer); |
| 277 | @Override | ||
| 278 | public String replace(String className) { | ||
| 279 | return translateClass(className); | ||
| 280 | } | ||
| 281 | }); | ||
| 282 | } | 247 | } |
| 283 | 248 | ||
| 284 | private ClassMapping findClassMapping(ClassEntry in) { | 249 | private ClassMapping findClassMapping(ClassEntry in) { |
| @@ -302,8 +267,8 @@ public class Translator { | |||
| 302 | ClassMapping innerClassMapping = null; | 267 | ClassMapping innerClassMapping = null; |
| 303 | if (outerClassMapping != null) { | 268 | if (outerClassMapping != null) { |
| 304 | innerClassMapping = m_direction.choose( | 269 | innerClassMapping = m_direction.choose( |
| 305 | outerClassMapping.getInnerClassByObf(parts[i]), | 270 | outerClassMapping.getInnerClassByObfSimple(parts[i]), |
| 306 | outerClassMapping.getInnerClassByDeobfThenObf(parts[i]) | 271 | outerClassMapping.getInnerClassByDeobfThenObfSimple(parts[i]) |
| 307 | ); | 272 | ); |
| 308 | } | 273 | } |
| 309 | mappingsChain.add(innerClassMapping); | 274 | mappingsChain.add(innerClassMapping); |