diff options
24 files changed, 310 insertions, 347 deletions
diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java index 59eb1b66..6c8caa43 100644 --- a/src/main/java/cuchaz/enigma/CommandMain.java +++ b/src/main/java/cuchaz/enigma/CommandMain.java | |||
| @@ -28,10 +28,6 @@ public class CommandMain { | |||
| 28 | deobfuscate(args); | 28 | deobfuscate(args); |
| 29 | } else if (command.equalsIgnoreCase("decompile")) { | 29 | } else if (command.equalsIgnoreCase("decompile")) { |
| 30 | decompile(args); | 30 | decompile(args); |
| 31 | } else if (command.equalsIgnoreCase("protectify")) { | ||
| 32 | protectify(args); | ||
| 33 | } else if (command.equalsIgnoreCase("publify")) { | ||
| 34 | publify(args); | ||
| 35 | } else if (command.equalsIgnoreCase("convertmappings")) { | 31 | } else if (command.equalsIgnoreCase("convertmappings")) { |
| 36 | convertMappings(args); | 32 | convertMappings(args); |
| 37 | } else { | 33 | } else { |
| @@ -50,8 +46,6 @@ public class CommandMain { | |||
| 50 | System.out.println("\twhere <command> is one of:"); | 46 | System.out.println("\twhere <command> is one of:"); |
| 51 | System.out.println("\t\tdeobfuscate <in jar> <out jar> [<mappings file>]"); | 47 | System.out.println("\t\tdeobfuscate <in jar> <out jar> [<mappings file>]"); |
| 52 | System.out.println("\t\tdecompile <in jar> <out folder> [<mappings file>]"); | 48 | System.out.println("\t\tdecompile <in jar> <out folder> [<mappings file>]"); |
| 53 | System.out.println("\t\tprotectify <in jar> <out jar>"); | ||
| 54 | System.out.println("\t\tpublify <in jar> <out jar>"); | ||
| 55 | System.out.println("\t\tconvertmappings <enigma mappings> <converted mappings> <ENIGMA_FILE|ENIGMA_DIRECTORY|SRG_FILE>"); | 49 | System.out.println("\t\tconvertmappings <enigma mappings> <converted mappings> <ENIGMA_FILE|ENIGMA_DIRECTORY|SRG_FILE>"); |
| 56 | } | 50 | } |
| 57 | 51 | ||
| @@ -71,20 +65,6 @@ public class CommandMain { | |||
| 71 | deobfuscator.writeJar(fileJarOut, new ConsoleProgressListener()); | 65 | deobfuscator.writeJar(fileJarOut, new ConsoleProgressListener()); |
| 72 | } | 66 | } |
| 73 | 67 | ||
| 74 | private static void protectify(String[] args) throws Exception { | ||
| 75 | File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true)); | ||
| 76 | File fileJarOut = getWritableFile(getArg(args, 2, "out jar", true)); | ||
| 77 | Deobfuscator deobfuscator = getDeobfuscator(null, new JarFile(fileJarIn)); | ||
| 78 | deobfuscator.protectifyJar(fileJarOut, new ConsoleProgressListener()); | ||
| 79 | } | ||
| 80 | |||
| 81 | private static void publify(String[] args) throws Exception { | ||
| 82 | File fileJarIn = getReadableFile(getArg(args, 1, "in jar", true)); | ||
| 83 | File fileJarOut = getWritableFile(getArg(args, 2, "out jar", true)); | ||
| 84 | Deobfuscator deobfuscator = getDeobfuscator(null, new JarFile(fileJarIn)); | ||
| 85 | deobfuscator.publifyJar(fileJarOut, new ConsoleProgressListener()); | ||
| 86 | } | ||
| 87 | |||
| 88 | private static Deobfuscator getDeobfuscator(File fileMappings, JarFile jar) throws Exception { | 68 | private static Deobfuscator getDeobfuscator(File fileMappings, JarFile jar) throws Exception { |
| 89 | System.out.println("Reading jar..."); | 69 | System.out.println("Reading jar..."); |
| 90 | Deobfuscator deobfuscator = new Deobfuscator(jar); | 70 | Deobfuscator deobfuscator = new Deobfuscator(jar); |
diff --git a/src/main/java/cuchaz/enigma/Deobfuscator.java b/src/main/java/cuchaz/enigma/Deobfuscator.java index 465c1ec3..c1992259 100644 --- a/src/main/java/cuchaz/enigma/Deobfuscator.java +++ b/src/main/java/cuchaz/enigma/Deobfuscator.java | |||
| @@ -28,8 +28,7 @@ import com.strobel.decompiler.languages.java.ast.CompilationUnit; | |||
| 28 | import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; | 28 | import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; |
| 29 | import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; | 29 | import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; |
| 30 | import cuchaz.enigma.analysis.*; | 30 | import cuchaz.enigma.analysis.*; |
| 31 | import cuchaz.enigma.bytecode.ClassProtectifier; | 31 | import cuchaz.enigma.api.EnigmaPlugin; |
| 32 | import cuchaz.enigma.bytecode.ClassPublifier; | ||
| 33 | import cuchaz.enigma.mapping.*; | 32 | import cuchaz.enigma.mapping.*; |
| 34 | import cuchaz.enigma.mapping.entry.*; | 33 | import cuchaz.enigma.mapping.entry.*; |
| 35 | import cuchaz.enigma.throwables.IllegalNameException; | 34 | import cuchaz.enigma.throwables.IllegalNameException; |
| @@ -40,19 +39,20 @@ import oml.ast.transformers.ObfuscatedEnumSwitchRewriterTransform; | |||
| 40 | import oml.ast.transformers.RemoveObjectCasts; | 39 | import oml.ast.transformers.RemoveObjectCasts; |
| 41 | import oml.ast.transformers.VarargsFixer; | 40 | import oml.ast.transformers.VarargsFixer; |
| 42 | import org.objectweb.asm.ClassWriter; | 41 | import org.objectweb.asm.ClassWriter; |
| 43 | import org.objectweb.asm.Opcodes; | ||
| 44 | import org.objectweb.asm.tree.ClassNode; | 42 | import org.objectweb.asm.tree.ClassNode; |
| 45 | 43 | ||
| 46 | import java.io.*; | 44 | import java.io.*; |
| 47 | import java.util.*; | 45 | import java.util.*; |
| 48 | import java.util.concurrent.ConcurrentHashMap; | 46 | import java.util.concurrent.ConcurrentHashMap; |
| 49 | import java.util.concurrent.atomic.AtomicInteger; | 47 | import java.util.concurrent.atomic.AtomicInteger; |
| 48 | import java.util.function.Consumer; | ||
| 50 | import java.util.jar.JarEntry; | 49 | import java.util.jar.JarEntry; |
| 51 | import java.util.jar.JarFile; | 50 | import java.util.jar.JarFile; |
| 52 | import java.util.jar.JarOutputStream; | 51 | import java.util.jar.JarOutputStream; |
| 53 | 52 | ||
| 54 | public class Deobfuscator { | 53 | public class Deobfuscator { |
| 55 | 54 | ||
| 55 | private final ServiceLoader<EnigmaPlugin> plugins = ServiceLoader.load(EnigmaPlugin.class); | ||
| 56 | private final ReferencedEntryPool entryPool = new ReferencedEntryPool(); | 56 | private final ReferencedEntryPool entryPool = new ReferencedEntryPool(); |
| 57 | private final ParsedJar parsedJar; | 57 | private final ParsedJar parsedJar; |
| 58 | private final DecompilerSettings settings; | 58 | private final DecompilerSettings settings; |
| @@ -61,13 +61,20 @@ public class Deobfuscator { | |||
| 61 | private final Map<TranslationDirection, Translator> translatorCache; | 61 | private final Map<TranslationDirection, Translator> translatorCache; |
| 62 | private Mappings mappings; | 62 | private Mappings mappings; |
| 63 | 63 | ||
| 64 | public Deobfuscator(ParsedJar jar) { | 64 | public Deobfuscator(ParsedJar jar, Consumer<String> listener) { |
| 65 | this.parsedJar = jar; | 65 | this.parsedJar = jar; |
| 66 | 66 | ||
| 67 | // build the jar index | 67 | // build the jar index |
| 68 | listener.accept("Indexing JAR..."); | ||
| 68 | this.jarIndex = new JarIndex(entryPool); | 69 | this.jarIndex = new JarIndex(entryPool); |
| 69 | this.jarIndex.indexJar(this.parsedJar, true); | 70 | this.jarIndex.indexJar(this.parsedJar, true); |
| 70 | 71 | ||
| 72 | listener.accept("Initializing plugins..."); | ||
| 73 | for (EnigmaPlugin plugin : getPlugins()) { | ||
| 74 | plugin.onClassesLoaded(parsedJar.getClassDataMap(), parsedJar::getClassNode); | ||
| 75 | } | ||
| 76 | |||
| 77 | listener.accept("Preparing..."); | ||
| 71 | // config the decompiler | 78 | // config the decompiler |
| 72 | this.settings = DecompilerSettings.javaDefaults(); | 79 | this.settings = DecompilerSettings.javaDefaults(); |
| 73 | this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); | 80 | this.settings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); |
| @@ -85,8 +92,20 @@ public class Deobfuscator { | |||
| 85 | setMappings(new Mappings()); | 92 | setMappings(new Mappings()); |
| 86 | } | 93 | } |
| 87 | 94 | ||
| 88 | public Deobfuscator(JarFile jar) throws IOException { | 95 | public Deobfuscator(JarFile jar, Consumer<String> listener) throws IOException { |
| 89 | this(new ParsedJar(jar)); | 96 | this(new ParsedJar(jar), listener); |
| 97 | } | ||
| 98 | |||
| 99 | public Deobfuscator(ParsedJar jar) throws IOException { | ||
| 100 | this(jar, (msg) -> {}); | ||
| 101 | } | ||
| 102 | |||
| 103 | public Deobfuscator(JarFile jar) throws IOException { | ||
| 104 | this(jar, (msg) -> {}); | ||
| 105 | } | ||
| 106 | |||
| 107 | public ServiceLoader<EnigmaPlugin> getPlugins() { | ||
| 108 | return plugins; | ||
| 90 | } | 109 | } |
| 91 | 110 | ||
| 92 | public ParsedJar getJar() { | 111 | public ParsedJar getJar() { |
| @@ -442,20 +461,6 @@ public class Deobfuscator { | |||
| 442 | transformJar(out, progress, createTypeLoader()::transformInto); | 461 | transformJar(out, progress, createTypeLoader()::transformInto); |
| 443 | } | 462 | } |
| 444 | 463 | ||
| 445 | public void protectifyJar(File out, ProgressListener progress) { | ||
| 446 | transformJar(out, progress, (node, writer) -> { | ||
| 447 | node.accept(new ClassProtectifier(Opcodes.ASM5, writer)); | ||
| 448 | return node.name; | ||
| 449 | }); | ||
| 450 | } | ||
| 451 | |||
| 452 | public void publifyJar(File out, ProgressListener progress) { | ||
| 453 | transformJar(out, progress, (node, writer) -> { | ||
| 454 | node.accept(new ClassPublifier(Opcodes.ASM5, writer)); | ||
| 455 | return node.name; | ||
| 456 | }); | ||
| 457 | } | ||
| 458 | |||
| 459 | public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { | 464 | public void transformJar(File out, ProgressListener progress, ClassTransformer transformer) { |
| 460 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { | 465 | try (JarOutputStream outJar = new JarOutputStream(new FileOutputStream(out))) { |
| 461 | if (progress != null) { | 466 | if (progress != null) { |
| @@ -463,7 +468,7 @@ public class Deobfuscator { | |||
| 463 | } | 468 | } |
| 464 | 469 | ||
| 465 | AtomicInteger i = new AtomicInteger(); | 470 | AtomicInteger i = new AtomicInteger(); |
| 466 | parsedJar.visit(node -> { | 471 | parsedJar.visitNode(node -> { |
| 467 | if (progress != null) { | 472 | if (progress != null) { |
| 468 | progress.onProgress(i.getAndIncrement(), node.name); | 473 | progress.onProgress(i.getAndIncrement(), node.name); |
| 469 | } | 474 | } |
| @@ -524,13 +529,7 @@ public class Deobfuscator { | |||
| 524 | } | 529 | } |
| 525 | 530 | ||
| 526 | public boolean isObfuscatedIdentifier(Entry obfEntry) { | 531 | public boolean isObfuscatedIdentifier(Entry obfEntry) { |
| 527 | return isObfuscatedIdentifier(obfEntry, false); | ||
| 528 | } | ||
| 529 | |||
| 530 | public boolean isObfuscatedIdentifier(Entry obfEntry, boolean hack) { | ||
| 531 | |||
| 532 | if (obfEntry instanceof MethodEntry) { | 532 | if (obfEntry instanceof MethodEntry) { |
| 533 | |||
| 534 | // HACKHACK: Object methods are not obfuscated identifiers | 533 | // HACKHACK: Object methods are not obfuscated identifiers |
| 535 | MethodEntry obfMethodEntry = (MethodEntry) obfEntry; | 534 | MethodEntry obfMethodEntry = (MethodEntry) obfEntry; |
| 536 | String name = obfMethodEntry.getName(); | 535 | String name = obfMethodEntry.getName(); |
| @@ -558,21 +557,13 @@ public class Deobfuscator { | |||
| 558 | } else if (name.equals("wait") && sig.equals("(JI)V")) { | 557 | } else if (name.equals("wait") && sig.equals("(JI)V")) { |
| 559 | return false; | 558 | return false; |
| 560 | } | 559 | } |
| 561 | |||
| 562 | // FIXME: HACK EVEN MORE HACK! | ||
| 563 | if (hack && this.jarIndex.containsObfEntry(obfEntry.getOwnerClassEntry())) | ||
| 564 | return true; | ||
| 565 | } | 560 | } |
| 566 | 561 | ||
| 567 | return this.jarIndex.containsObfEntry(obfEntry); | 562 | return this.jarIndex.containsObfEntry(obfEntry); |
| 568 | } | 563 | } |
| 569 | 564 | ||
| 570 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference, boolean activeHack) { | ||
| 571 | return obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry(), activeHack); | ||
| 572 | } | ||
| 573 | |||
| 574 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { | 565 | public boolean isRenameable(EntryReference<Entry, Entry> obfReference) { |
| 575 | return isRenameable(obfReference, false); | 566 | return obfReference.isNamed() && isObfuscatedIdentifier(obfReference.getNameableEntry()); |
| 576 | } | 567 | } |
| 577 | 568 | ||
| 578 | public boolean hasDeobfuscatedName(Entry obfEntry) { | 569 | public boolean hasDeobfuscatedName(Entry obfEntry) { |
diff --git a/src/main/java/cuchaz/enigma/analysis/EntryReference.java b/src/main/java/cuchaz/enigma/analysis/EntryReference.java index 101729d8..df36c236 100644 --- a/src/main/java/cuchaz/enigma/analysis/EntryReference.java +++ b/src/main/java/cuchaz/enigma/analysis/EntryReference.java | |||
| @@ -70,7 +70,7 @@ public class EntryReference<E extends Entry, C extends Entry> { | |||
| 70 | return entry; | 70 | return entry; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | public String getNamableName() { | 73 | public String getNameableName() { |
| 74 | if (getNameableEntry() instanceof ClassEntry) { | 74 | if (getNameableEntry() instanceof ClassEntry) { |
| 75 | ClassEntry classEntry = (ClassEntry) getNameableEntry(); | 75 | ClassEntry classEntry = (ClassEntry) getNameableEntry(); |
| 76 | if (classEntry.isInnerClass()) { | 76 | if (classEntry.isInnerClass()) { |
diff --git a/src/main/java/cuchaz/enigma/analysis/IndexClassVisitor.java b/src/main/java/cuchaz/enigma/analysis/IndexClassVisitor.java index 69fe54fc..4d5e8037 100644 --- a/src/main/java/cuchaz/enigma/analysis/IndexClassVisitor.java +++ b/src/main/java/cuchaz/enigma/analysis/IndexClassVisitor.java | |||
| @@ -14,6 +14,11 @@ public class IndexClassVisitor extends ClassVisitor { | |||
| 14 | this.index = index; | 14 | this.index = index; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | public IndexClassVisitor(JarIndex index, int api, ClassVisitor cv) { | ||
| 18 | super(api, cv); | ||
| 19 | this.index = index; | ||
| 20 | } | ||
| 21 | |||
| 17 | @Override | 22 | @Override |
| 18 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { | 23 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { |
| 19 | this.classEntry = this.index.indexClass(access, name, signature, superName, interfaces); | 24 | this.classEntry = this.index.indexClass(access, name, signature, superName, interfaces); |
diff --git a/src/main/java/cuchaz/enigma/analysis/IndexInnerClassVisitor.java b/src/main/java/cuchaz/enigma/analysis/IndexInnerClassVisitor.java index 04742278..b6ab2d5b 100644 --- a/src/main/java/cuchaz/enigma/analysis/IndexInnerClassVisitor.java +++ b/src/main/java/cuchaz/enigma/analysis/IndexInnerClassVisitor.java | |||
| @@ -11,6 +11,11 @@ public class IndexInnerClassVisitor extends ClassVisitor { | |||
| 11 | this.index = index; | 11 | this.index = index; |
| 12 | } | 12 | } |
| 13 | 13 | ||
| 14 | public IndexInnerClassVisitor(JarIndex index, int api, ClassVisitor cv) { | ||
| 15 | super(api, cv); | ||
| 16 | this.index = index; | ||
| 17 | } | ||
| 18 | |||
| 14 | @Override | 19 | @Override |
| 15 | public void visitInnerClass(String name, String outerName, String innerName, int access) { | 20 | public void visitInnerClass(String name, String outerName, String innerName, int access) { |
| 16 | ClassEntry entry = new ClassEntry(name); | 21 | ClassEntry entry = new ClassEntry(name); |
| @@ -19,5 +24,6 @@ public class IndexInnerClassVisitor extends ClassVisitor { | |||
| 19 | ClassEntry outerEntry = new ClassEntry(outerName); | 24 | ClassEntry outerEntry = new ClassEntry(outerName); |
| 20 | index.indexInnerClass(entry, outerEntry); | 25 | index.indexInnerClass(entry, outerEntry); |
| 21 | } | 26 | } |
| 27 | super.visitInnerClass(name, outerName, innerName, access); | ||
| 22 | } | 28 | } |
| 23 | } | 29 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/JarIndex.java index 158df4b5..e8bda8ef 100644 --- a/src/main/java/cuchaz/enigma/analysis/JarIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/JarIndex.java | |||
| @@ -15,6 +15,8 @@ import com.google.common.collect.*; | |||
| 15 | import cuchaz.enigma.bytecode.AccessFlags; | 15 | import cuchaz.enigma.bytecode.AccessFlags; |
| 16 | import cuchaz.enigma.mapping.*; | 16 | import cuchaz.enigma.mapping.*; |
| 17 | import cuchaz.enigma.mapping.entry.*; | 17 | import cuchaz.enigma.mapping.entry.*; |
| 18 | import org.objectweb.asm.ClassReader; | ||
| 19 | import org.objectweb.asm.ClassVisitor; | ||
| 18 | import org.objectweb.asm.Opcodes; | 20 | import org.objectweb.asm.Opcodes; |
| 19 | 21 | ||
| 20 | import java.util.*; | 22 | import java.util.*; |
| @@ -62,10 +64,15 @@ public class JarIndex { | |||
| 62 | obfClassEntries.addAll(jar.getClassEntries()); | 64 | obfClassEntries.addAll(jar.getClassEntries()); |
| 63 | 65 | ||
| 64 | // step 2: index classes, fields, methods, interfaces | 66 | // step 2: index classes, fields, methods, interfaces |
| 65 | jar.visit(node -> node.accept(new IndexClassVisitor(this, Opcodes.ASM5))); | 67 | if (buildInnerClasses) { |
| 68 | // + step 5: index inner classes | ||
| 69 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5, new IndexInnerClassVisitor(this, Opcodes.ASM5)), ClassReader.SKIP_CODE); | ||
| 70 | } else { | ||
| 71 | jar.visitReader(name -> new IndexClassVisitor(this, Opcodes.ASM5), ClassReader.SKIP_CODE); | ||
| 72 | } | ||
| 66 | 73 | ||
| 67 | // step 3: index field, method, constructor references | 74 | // step 3: index field, method, constructor references |
| 68 | jar.visit(node -> node.accept(new IndexReferenceVisitor(this, Opcodes.ASM5))); | 75 | jar.visitReader(name -> new IndexReferenceVisitor(this, Opcodes.ASM5), ClassReader.SKIP_FRAMES); |
| 69 | 76 | ||
| 70 | // step 4: index access and bridged methods | 77 | // step 4: index access and bridged methods |
| 71 | for (MethodDefEntry methodEntry : methods.values()) { | 78 | for (MethodDefEntry methodEntry : methods.values()) { |
| @@ -79,9 +86,6 @@ public class JarIndex { | |||
| 79 | } | 86 | } |
| 80 | 87 | ||
| 81 | if (buildInnerClasses) { | 88 | if (buildInnerClasses) { |
| 82 | // step 5: index inner classes and anonymous classes | ||
| 83 | jar.visit(node -> node.accept(new IndexInnerClassVisitor(this, Opcodes.ASM5))); | ||
| 84 | |||
| 85 | // step 6: update other indices with inner class info | 89 | // step 6: update other indices with inner class info |
| 86 | Map<String, String> renames = Maps.newHashMap(); | 90 | Map<String, String> renames = Maps.newHashMap(); |
| 87 | for (ClassEntry innerClassEntry : this.innerClassesByOuter.values()) { | 91 | for (ClassEntry innerClassEntry : this.innerClassesByOuter.values()) { |
diff --git a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java index 55f2141b..86655d09 100644 --- a/src/main/java/cuchaz/enigma/analysis/ParsedJar.java +++ b/src/main/java/cuchaz/enigma/analysis/ParsedJar.java | |||
| @@ -11,8 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | package cuchaz.enigma.analysis; | 12 | package cuchaz.enigma.analysis; |
| 13 | 13 | ||
| 14 | import com.google.common.io.ByteStreams; | ||
| 14 | import cuchaz.enigma.mapping.entry.ClassEntry; | 15 | import cuchaz.enigma.mapping.entry.ClassEntry; |
| 15 | import org.objectweb.asm.ClassReader; | 16 | import org.objectweb.asm.ClassReader; |
| 17 | import org.objectweb.asm.ClassVisitor; | ||
| 16 | import org.objectweb.asm.tree.ClassNode; | 18 | import org.objectweb.asm.tree.ClassNode; |
| 17 | 19 | ||
| 18 | import java.io.BufferedInputStream; | 20 | import java.io.BufferedInputStream; |
| @@ -20,14 +22,17 @@ import java.io.IOException; | |||
| 20 | import java.io.InputStream; | 22 | import java.io.InputStream; |
| 21 | import java.util.*; | 23 | import java.util.*; |
| 22 | import java.util.function.Consumer; | 24 | import java.util.function.Consumer; |
| 25 | import java.util.function.Function; | ||
| 23 | import java.util.jar.JarEntry; | 26 | import java.util.jar.JarEntry; |
| 24 | import java.util.jar.JarFile; | 27 | import java.util.jar.JarFile; |
| 25 | import java.util.jar.JarInputStream; | 28 | import java.util.jar.JarInputStream; |
| 26 | 29 | ||
| 27 | public class ParsedJar { | 30 | public class ParsedJar { |
| 28 | private final Map<String, ClassNode> nodes = new LinkedHashMap<>(); | 31 | private final Map<String, byte[]> classBytes; |
| 32 | private final Map<String, ClassNode> nodeCache = new HashMap<>(); | ||
| 29 | 33 | ||
| 30 | public ParsedJar(JarFile jar) throws IOException { | 34 | public ParsedJar(JarFile jar) throws IOException { |
| 35 | Map<String, byte[]> uClassBytes = new LinkedHashMap<>();; | ||
| 31 | try { | 36 | try { |
| 32 | // get the jar entries that correspond to classes | 37 | // get the jar entries that correspond to classes |
| 33 | Enumeration<JarEntry> entries = jar.entries(); | 38 | Enumeration<JarEntry> entries = jar.entries(); |
| @@ -36,60 +41,75 @@ public class ParsedJar { | |||
| 36 | // is this a class file? | 41 | // is this a class file? |
| 37 | if (entry.getName().endsWith(".class")) { | 42 | if (entry.getName().endsWith(".class")) { |
| 38 | try (InputStream input = new BufferedInputStream(jar.getInputStream(entry))) { | 43 | try (InputStream input = new BufferedInputStream(jar.getInputStream(entry))) { |
| 39 | // read the ClassNode from the jar | ||
| 40 | ClassReader reader = new ClassReader(input); | ||
| 41 | ClassNode node = new ClassNode(); | ||
| 42 | reader.accept(node, 0); | ||
| 43 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); | 44 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); |
| 44 | nodes.put(path, node); | 45 | uClassBytes.put(path, ByteStreams.toByteArray(input)); |
| 45 | } | 46 | } |
| 46 | } | 47 | } |
| 47 | } | 48 | } |
| 48 | } finally { | 49 | } finally { |
| 49 | jar.close(); | 50 | jar.close(); |
| 51 | classBytes = Collections.unmodifiableMap(uClassBytes); | ||
| 50 | } | 52 | } |
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | public ParsedJar(JarInputStream jar) throws IOException { | 55 | public ParsedJar(JarInputStream jar) throws IOException { |
| 56 | Map<String, byte[]> uClassBytes = new LinkedHashMap<>(); | ||
| 54 | try { | 57 | try { |
| 55 | // get the jar entries that correspond to classes | 58 | // get the jar entries that correspond to classes |
| 56 | JarEntry entry; | 59 | JarEntry entry; |
| 57 | while ((entry = jar.getNextJarEntry()) != null) { | 60 | while ((entry = jar.getNextJarEntry()) != null) { |
| 58 | // is this a class file? | 61 | // is this a class file? |
| 59 | if (entry.getName().endsWith(".class")) { | 62 | if (entry.getName().endsWith(".class")) { |
| 60 | // read the ClassNode from the jar | ||
| 61 | ClassReader reader = new ClassReader(jar); | ||
| 62 | ClassNode node = new ClassNode(); | ||
| 63 | reader.accept(node, 0); | ||
| 64 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); | 63 | String path = entry.getName().substring(0, entry.getName().length() - ".class".length()); |
| 65 | nodes.put(path, node); | 64 | uClassBytes.put(path, ByteStreams.toByteArray(jar)); |
| 66 | jar.closeEntry(); | 65 | jar.closeEntry(); |
| 67 | } | 66 | } |
| 68 | } | 67 | } |
| 69 | } finally { | 68 | } finally { |
| 70 | jar.close(); | 69 | jar.close(); |
| 70 | classBytes = Collections.unmodifiableMap(uClassBytes); | ||
| 71 | } | 71 | } |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | public void visit(Consumer<ClassNode> visitor) { | 74 | public void visitReader(Function<String, ClassVisitor> visitorFunction, int options) { |
| 75 | for (ClassNode node : nodes.values()) { | 75 | for (String s : classBytes.keySet()) { |
| 76 | visitor.accept(node); | 76 | ClassNode nodeCached = nodeCache.get(s); |
| 77 | if (nodeCached != null) { | ||
| 78 | nodeCached.accept(visitorFunction.apply(s)); | ||
| 79 | } else { | ||
| 80 | new ClassReader(classBytes.get(s)).accept(visitorFunction.apply(s), options); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | public void visitNode(Consumer<ClassNode> consumer) { | ||
| 86 | for (String s : classBytes.keySet()) { | ||
| 87 | consumer.accept(getClassNode(s)); | ||
| 77 | } | 88 | } |
| 78 | } | 89 | } |
| 79 | 90 | ||
| 80 | public int getClassCount() { | 91 | public int getClassCount() { |
| 81 | return nodes.size(); | 92 | return classBytes.size(); |
| 82 | } | 93 | } |
| 83 | 94 | ||
| 84 | public List<ClassEntry> getClassEntries() { | 95 | public List<ClassEntry> getClassEntries() { |
| 85 | List<ClassEntry> entries = new ArrayList<>(nodes.size()); | 96 | List<ClassEntry> entries = new ArrayList<>(classBytes.size()); |
| 86 | for (ClassNode node : nodes.values()) { | 97 | for (String s : classBytes.keySet()) { |
| 87 | entries.add(new ClassEntry(node.name)); | 98 | entries.add(new ClassEntry(s)); |
| 88 | } | 99 | } |
| 89 | return entries; | 100 | return entries; |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 92 | public ClassNode getClassNode(String name) { | 103 | public ClassNode getClassNode(String name) { |
| 93 | return nodes.get(name); | 104 | return nodeCache.computeIfAbsent(name, (n) -> { |
| 105 | ClassReader reader = new ClassReader(classBytes.get(name)); | ||
| 106 | ClassNode node = new ClassNode(); | ||
| 107 | reader.accept(node, 0); | ||
| 108 | return node; | ||
| 109 | }); | ||
| 94 | } | 110 | } |
| 111 | |||
| 112 | public Map<String, byte[]> getClassDataMap() { | ||
| 113 | return classBytes; | ||
| 114 | } | ||
| 95 | } | 115 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java index 78195cb7..4c84e69d 100644 --- a/src/main/java/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/main/java/cuchaz/enigma/analysis/SourceIndex.java | |||
| @@ -22,10 +22,7 @@ import com.strobel.decompiler.languages.java.ast.Identifier; | |||
| 22 | import com.strobel.decompiler.languages.java.ast.TypeDeclaration; | 22 | import com.strobel.decompiler.languages.java.ast.TypeDeclaration; |
| 23 | import cuchaz.enigma.mapping.entry.Entry; | 23 | import cuchaz.enigma.mapping.entry.Entry; |
| 24 | 24 | ||
| 25 | import java.util.Collection; | 25 | import java.util.*; |
| 26 | import java.util.List; | ||
| 27 | import java.util.Map; | ||
| 28 | import java.util.TreeMap; | ||
| 29 | import java.util.regex.Pattern; | 26 | import java.util.regex.Pattern; |
| 30 | 27 | ||
| 31 | public class SourceIndex { | 28 | public class SourceIndex { |
| @@ -48,9 +45,12 @@ public class SourceIndex { | |||
| 48 | this.tokenToReference = Maps.newTreeMap(); | 45 | this.tokenToReference = Maps.newTreeMap(); |
| 49 | this.referenceToTokens = HashMultimap.create(); | 46 | this.referenceToTokens = HashMultimap.create(); |
| 50 | this.declarationToToken = Maps.newHashMap(); | 47 | this.declarationToToken = Maps.newHashMap(); |
| 51 | this.lineOffsets = Lists.newArrayList(); | 48 | calculateLineOffsets(); |
| 49 | } | ||
| 52 | 50 | ||
| 51 | private void calculateLineOffsets() { | ||
| 53 | // count the lines | 52 | // count the lines |
| 53 | this.lineOffsets = Lists.newArrayList(); | ||
| 54 | this.lineOffsets.add(0); | 54 | this.lineOffsets.add(0); |
| 55 | for (int i = 0; i < source.length(); i++) { | 55 | for (int i = 0; i < source.length(); i++) { |
| 56 | if (source.charAt(i) == '\n') { | 56 | if (source.charAt(i) == '\n') { |
| @@ -59,6 +59,32 @@ public class SourceIndex { | |||
| 59 | } | 59 | } |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | public void remap(String source, Map<Token, Token> tokenMap) { | ||
| 63 | this.source = source; | ||
| 64 | calculateLineOffsets(); | ||
| 65 | |||
| 66 | for (Entry entry : Lists.newArrayList(declarationToToken.keySet())) { | ||
| 67 | Token token = declarationToToken.get(entry); | ||
| 68 | declarationToToken.put(entry, tokenMap.getOrDefault(token, token)); | ||
| 69 | } | ||
| 70 | |||
| 71 | for (Token token : Lists.newArrayList(tokenToReference.keySet())) { | ||
| 72 | EntryReference<Entry, Entry> e = tokenToReference.remove(token); | ||
| 73 | tokenToReference.put(tokenMap.getOrDefault(token, token), e); | ||
| 74 | } | ||
| 75 | |||
| 76 | for (EntryReference<Entry, Entry> ref : Lists.newArrayList(referenceToTokens.keySet())) { | ||
| 77 | List<Token> newTokens = new ArrayList<>(); | ||
| 78 | |||
| 79 | for (Token token : referenceToTokens.get(ref)) { | ||
| 80 | newTokens.add(tokenMap.getOrDefault(token, token)); | ||
| 81 | } | ||
| 82 | |||
| 83 | referenceToTokens.removeAll(ref); | ||
| 84 | referenceToTokens.putAll(ref, newTokens); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 62 | public String getSource() { | 88 | public String getSource() { |
| 63 | return this.source; | 89 | return this.source; |
| 64 | } | 90 | } |
diff --git a/src/main/java/cuchaz/enigma/analysis/Token.java b/src/main/java/cuchaz/enigma/analysis/Token.java index 266d2027..14fa7ca4 100644 --- a/src/main/java/cuchaz/enigma/analysis/Token.java +++ b/src/main/java/cuchaz/enigma/analysis/Token.java | |||
| @@ -25,6 +25,25 @@ public class Token implements Comparable<Token> { | |||
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | public int getRenameOffset(String to) { | ||
| 29 | int length = this.end - this.start; | ||
| 30 | return to.length() - length; | ||
| 31 | } | ||
| 32 | |||
| 33 | public String rename(String source, String to) { | ||
| 34 | int oldEnd = this.end; | ||
| 35 | this.text = to; | ||
| 36 | this.end = this.start + to.length(); | ||
| 37 | |||
| 38 | return source.substring(0, this.start) + to + source.substring(oldEnd); | ||
| 39 | } | ||
| 40 | |||
| 41 | public Token move(int offset) { | ||
| 42 | Token token = new Token(this.start + offset, this.end + offset, null); | ||
| 43 | token.text = text; | ||
| 44 | return token; | ||
| 45 | } | ||
| 46 | |||
| 28 | public boolean contains(int pos) { | 47 | public boolean contains(int pos) { |
| 29 | return pos >= start && pos <= end; | 48 | return pos >= start && pos <= end; |
| 30 | } | 49 | } |
| @@ -41,7 +60,7 @@ public class Token implements Comparable<Token> { | |||
| 41 | 60 | ||
| 42 | @Override | 61 | @Override |
| 43 | public int hashCode() { | 62 | public int hashCode() { |
| 44 | return Integer.hashCode(start) + Integer.hashCode(end) + (text != null ? text.hashCode() : 0); | 63 | return start * 37 + end; |
| 45 | } | 64 | } |
| 46 | 65 | ||
| 47 | public boolean equals(Token other) { | 66 | public boolean equals(Token other) { |
diff --git a/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java b/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java new file mode 100644 index 00000000..3efe0dc5 --- /dev/null +++ b/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | package cuchaz.enigma.api; | ||
| 2 | |||
| 3 | import org.objectweb.asm.tree.ClassNode; | ||
| 4 | |||
| 5 | import javax.annotation.Nullable; | ||
| 6 | import java.util.Map; | ||
| 7 | import java.util.function.Function; | ||
| 8 | |||
| 9 | public abstract class EnigmaPlugin { | ||
| 10 | public void onClassesLoaded(Map<String, byte[]> classData, Function<String, ClassNode> classNodeGetter) { | ||
| 11 | |||
| 12 | } | ||
| 13 | |||
| 14 | @Nullable | ||
| 15 | public String proposeFieldName(String owner, String name, String desc) { | ||
| 16 | return null; | ||
| 17 | } | ||
| 18 | } | ||
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java b/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java deleted file mode 100644 index 9ed6db9f..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/ClassProtectifier.java +++ /dev/null | |||
| @@ -1,49 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.bytecode; | ||
| 13 | |||
| 14 | import org.objectweb.asm.ClassVisitor; | ||
| 15 | import org.objectweb.asm.FieldVisitor; | ||
| 16 | import org.objectweb.asm.MethodVisitor; | ||
| 17 | |||
| 18 | public class ClassProtectifier extends ClassVisitor { | ||
| 19 | |||
| 20 | public ClassProtectifier(int api, ClassVisitor cv) { | ||
| 21 | super(api, cv); | ||
| 22 | } | ||
| 23 | |||
| 24 | @Override | ||
| 25 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { | ||
| 26 | access = protectify(access); | ||
| 27 | return super.visitMethod(access, name, desc, signature, exceptions); | ||
| 28 | } | ||
| 29 | |||
| 30 | @Override | ||
| 31 | public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { | ||
| 32 | access = protectify(access); | ||
| 33 | return super.visitField(access, name, desc, signature, value); | ||
| 34 | } | ||
| 35 | |||
| 36 | @Override | ||
| 37 | public void visitInnerClass(String name, String outerName, String innerName, int access) { | ||
| 38 | access = protectify(access); | ||
| 39 | super.visitInnerClass(name, outerName, innerName, access); | ||
| 40 | } | ||
| 41 | |||
| 42 | private static int protectify(int access) { | ||
| 43 | AccessFlags accessFlags = new AccessFlags(access); | ||
| 44 | if (accessFlags.isPrivate()) { | ||
| 45 | accessFlags.setProtected(); | ||
| 46 | } | ||
| 47 | return accessFlags.getFlags(); | ||
| 48 | } | ||
| 49 | } | ||
diff --git a/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java b/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java deleted file mode 100644 index 64de788f..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/ClassPublifier.java +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.bytecode; | ||
| 13 | |||
| 14 | import org.objectweb.asm.ClassVisitor; | ||
| 15 | import org.objectweb.asm.FieldVisitor; | ||
| 16 | import org.objectweb.asm.MethodVisitor; | ||
| 17 | |||
| 18 | public class ClassPublifier extends ClassVisitor { | ||
| 19 | |||
| 20 | public ClassPublifier(int api, ClassVisitor cv) { | ||
| 21 | super(api, cv); | ||
| 22 | } | ||
| 23 | |||
| 24 | @Override | ||
| 25 | public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { | ||
| 26 | access = publify(access); | ||
| 27 | super.visit(version, access, name, signature, superName, interfaces); | ||
| 28 | } | ||
| 29 | |||
| 30 | @Override | ||
| 31 | public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { | ||
| 32 | access = publify(access); | ||
| 33 | return super.visitField(access, name, desc, signature, value); | ||
| 34 | } | ||
| 35 | |||
| 36 | @Override | ||
| 37 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { | ||
| 38 | access = publify(access); | ||
| 39 | return super.visitMethod(access, name, desc, signature, exceptions); | ||
| 40 | } | ||
| 41 | |||
| 42 | @Override | ||
| 43 | public void visitInnerClass(String name, String outerName, String innerName, int access) { | ||
| 44 | access = publify(access); | ||
| 45 | super.visitInnerClass(name, outerName, innerName, access); | ||
| 46 | } | ||
| 47 | |||
| 48 | private static int publify(int access) { | ||
| 49 | AccessFlags accessFlags = new AccessFlags(access); | ||
| 50 | if (!accessFlags.isPublic()) { | ||
| 51 | accessFlags.setPublic(); | ||
| 52 | } | ||
| 53 | return accessFlags.getFlags(); | ||
| 54 | } | ||
| 55 | } | ||
diff --git a/src/main/java/cuchaz/enigma/config/Config.java b/src/main/java/cuchaz/enigma/config/Config.java index 8c16c47b..47bd0a7f 100644 --- a/src/main/java/cuchaz/enigma/config/Config.java +++ b/src/main/java/cuchaz/enigma/config/Config.java | |||
| @@ -6,12 +6,32 @@ import com.google.gson.*; | |||
| 6 | 6 | ||
| 7 | import javax.swing.*; | 7 | import javax.swing.*; |
| 8 | import javax.swing.plaf.metal.MetalLookAndFeel; | 8 | import javax.swing.plaf.metal.MetalLookAndFeel; |
| 9 | import java.awt.*; | ||
| 9 | import java.io.File; | 10 | import java.io.File; |
| 10 | import java.io.IOException; | 11 | import java.io.IOException; |
| 11 | import java.lang.reflect.Type; | 12 | import java.lang.reflect.Type; |
| 12 | import java.nio.charset.Charset; | 13 | import java.nio.charset.Charset; |
| 13 | 14 | ||
| 14 | public class Config { | 15 | public class Config { |
| 16 | public static class AlphaColorEntry { | ||
| 17 | public Integer rgb; | ||
| 18 | public float alpha = 1.0f; | ||
| 19 | |||
| 20 | public AlphaColorEntry(Integer rgb, float alpha) { | ||
| 21 | this.rgb = rgb; | ||
| 22 | this.alpha = alpha; | ||
| 23 | } | ||
| 24 | |||
| 25 | public Color get() { | ||
| 26 | if (rgb == null) { | ||
| 27 | return new Color(0, 0, 0, 0); | ||
| 28 | } | ||
| 29 | |||
| 30 | Color baseColor = new Color(rgb); | ||
| 31 | return new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), (int)(255 * alpha)); | ||
| 32 | } | ||
| 33 | } | ||
| 34 | |||
| 15 | public enum LookAndFeel { | 35 | public enum LookAndFeel { |
| 16 | DEFAULT("Default"), | 36 | DEFAULT("Default"), |
| 17 | DARCULA("Dank"); | 37 | DARCULA("Dank"); |
| @@ -47,16 +67,13 @@ public class Config { | |||
| 47 | config.lineNumbersForeground = 0x333300; | 67 | config.lineNumbersForeground = 0x333300; |
| 48 | config.lineNumbersBackground = 0xEEEEFF; | 68 | config.lineNumbersBackground = 0xEEEEFF; |
| 49 | config.lineNumbersSelected = 0xCCCCEE; | 69 | config.lineNumbersSelected = 0xCCCCEE; |
| 50 | config.obfuscatedColor = 0xFFDCDC; | 70 | config.obfuscatedColor = new AlphaColorEntry(0xFFDCDC, 1.0f); |
| 51 | config.obfuscatedHiglightAlpha = 1.0F; | 71 | config.obfuscatedColorOutline = new AlphaColorEntry(0xA05050, 1.0f); |
| 52 | config.obfuscatedColorOutline = 0xA05050; | 72 | config.proposedColor = new AlphaColorEntry(0x000000, 0.075f); |
| 53 | config.obfuscatedOutlineAlpha = 1.0F; | 73 | config.proposedColorOutline = new AlphaColorEntry(0x000000, 0.15f); |
| 54 | config.deobfuscatedColor = 0xDCFFDC; | 74 | config.deobfuscatedColor = new AlphaColorEntry(0xDCFFDC, 1.0f); |
| 55 | config.deobfuscatedHiglightAlpha = 1.0F; | 75 | config.deobfuscatedColorOutline = new AlphaColorEntry(0x50A050, 1.0f); |
| 56 | config.deobfuscatedColorOutline = 0x50A050; | 76 | config.otherColorOutline = new AlphaColorEntry(0xB4B4B4, 1.0f); |
| 57 | config.deobfuscatedOutlineAlpha = 1.0F; | ||
| 58 | config.otherColorOutline = 0xB4B4B4; | ||
| 59 | config.otherOutlineAlpha = 1.0F; | ||
| 60 | config.editorBackground = 0xFFFFFF; | 77 | config.editorBackground = 0xFFFFFF; |
| 61 | config.highlightColor = 0x3333EE; | 78 | config.highlightColor = 0x3333EE; |
| 62 | config.stringColor = 0xCC6600; | 79 | config.stringColor = 0xCC6600; |
| @@ -72,16 +89,13 @@ public class Config { | |||
| 72 | config.lineNumbersForeground = 0xA4A4A3; | 89 | config.lineNumbersForeground = 0xA4A4A3; |
| 73 | config.lineNumbersBackground = 0x313335; | 90 | config.lineNumbersBackground = 0x313335; |
| 74 | config.lineNumbersSelected = 0x606366; | 91 | config.lineNumbersSelected = 0x606366; |
| 75 | config.obfuscatedColor = 0xFF5555; | 92 | config.obfuscatedColor = new AlphaColorEntry(0xFF5555, 0.3f); |
| 76 | config.obfuscatedHiglightAlpha = 0.3F; | 93 | config.obfuscatedColorOutline = new AlphaColorEntry(0xFF5555, 0.5f); |
| 77 | config.obfuscatedColorOutline = 0xFF5555; | 94 | config.deobfuscatedColor = new AlphaColorEntry(0x50FA7B, 0.3f); |
| 78 | config.obfuscatedOutlineAlpha = 0.5F; | 95 | config.deobfuscatedColorOutline = new AlphaColorEntry(0x50FA7B, 0.5f); |
| 79 | config.deobfuscatedColor = 0x50FA7B; | 96 | config.proposedColor = new AlphaColorEntry(0x606366, 0.3f); |
| 80 | config.deobfuscatedHiglightAlpha = 0.3F; | 97 | config.proposedColorOutline = new AlphaColorEntry(0x606366, 0.5f); |
| 81 | config.deobfuscatedColorOutline = 0x50FA7B; | 98 | config.otherColorOutline = new AlphaColorEntry(0xB4B4B4, 0.0f); |
| 82 | config.deobfuscatedOutlineAlpha = 0.5F; | ||
| 83 | config.otherColorOutline = 0xB4B4B4; | ||
| 84 | config.otherOutlineAlpha = 0.0F; | ||
| 85 | config.editorBackground = 0x282A36; | 99 | config.editorBackground = 0x282A36; |
| 86 | config.highlightColor = 0xFF79C6; | 100 | config.highlightColor = 0xFF79C6; |
| 87 | config.stringColor = 0xF1FA8C; | 101 | config.stringColor = 0xF1FA8C; |
| @@ -103,16 +117,13 @@ public class Config { | |||
| 103 | 117 | ||
| 104 | private final transient Gson gson; // transient to exclude it from being exposed | 118 | private final transient Gson gson; // transient to exclude it from being exposed |
| 105 | 119 | ||
| 106 | public Integer obfuscatedColor; | 120 | public AlphaColorEntry obfuscatedColor; |
| 107 | public float obfuscatedHiglightAlpha; | 121 | public AlphaColorEntry obfuscatedColorOutline; |
| 108 | public Integer obfuscatedColorOutline; | 122 | public AlphaColorEntry proposedColor; |
| 109 | public float obfuscatedOutlineAlpha; | 123 | public AlphaColorEntry proposedColorOutline; |
| 110 | public Integer deobfuscatedColor; | 124 | public AlphaColorEntry deobfuscatedColor; |
| 111 | public float deobfuscatedHiglightAlpha; | 125 | public AlphaColorEntry deobfuscatedColorOutline; |
| 112 | public Integer deobfuscatedColorOutline; | 126 | public AlphaColorEntry otherColorOutline; |
| 113 | public float deobfuscatedOutlineAlpha; | ||
| 114 | public Integer otherColorOutline; | ||
| 115 | public float otherOutlineAlpha; | ||
| 116 | 127 | ||
| 117 | //Defaults found here: https://github.com/Sciss/SyntaxPane/blob/122da367ff7a5d31627a70c62a48a9f0f4f85a0a/src/main/resources/de/sciss/syntaxpane/defaultsyntaxkit/config.properties#L139 | 128 | //Defaults found here: https://github.com/Sciss/SyntaxPane/blob/122da367ff7a5d31627a70c62a48a9f0f4f85a0a/src/main/resources/de/sciss/syntaxpane/defaultsyntaxkit/config.properties#L139 |
| 118 | public Integer editorBackground; | 129 | public Integer editorBackground; |
| @@ -152,8 +163,18 @@ public class Config { | |||
| 152 | public void loadConfig() throws IOException { | 163 | public void loadConfig() throws IOException { |
| 153 | if (!ENIGMA_DIR.exists()) ENIGMA_DIR.mkdirs(); | 164 | if (!ENIGMA_DIR.exists()) ENIGMA_DIR.mkdirs(); |
| 154 | File configFile = new File(ENIGMA_DIR, "config.json"); | 165 | File configFile = new File(ENIGMA_DIR, "config.json"); |
| 155 | if (configFile.exists()) gson.fromJson(Files.asCharSource(configFile, Charset.defaultCharset()).read(), Config.class); | 166 | boolean loaded = false; |
| 156 | else { | 167 | |
| 168 | if (configFile.exists()) { | ||
| 169 | try { | ||
| 170 | gson.fromJson(Files.asCharSource(configFile, Charset.defaultCharset()).read(), Config.class); | ||
| 171 | loaded = true; | ||
| 172 | } catch (Exception e) { | ||
| 173 | e.printStackTrace(); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | if (!loaded) { | ||
| 157 | this.reset(); | 178 | this.reset(); |
| 158 | Files.touch(configFile); | 179 | Files.touch(configFile); |
| 159 | } | 180 | } |
diff --git a/src/main/java/cuchaz/enigma/config/Themes.java b/src/main/java/cuchaz/enigma/config/Themes.java index 8a4c3417..00324f47 100644 --- a/src/main/java/cuchaz/enigma/config/Themes.java +++ b/src/main/java/cuchaz/enigma/config/Themes.java | |||
| @@ -1,15 +1,12 @@ | |||
| 1 | package cuchaz.enigma.config; | 1 | package cuchaz.enigma.config; |
| 2 | 2 | ||
| 3 | import com.bulenkov.darcula.DarculaLaf; | 3 | import com.google.common.collect.ImmutableMap; |
| 4 | import cuchaz.enigma.gui.Gui; | 4 | import cuchaz.enigma.gui.Gui; |
| 5 | import cuchaz.enigma.gui.MinecraftSyntaxKit; | 5 | import cuchaz.enigma.gui.EnigmaSyntaxKit; |
| 6 | import cuchaz.enigma.gui.highlight.DeobfuscatedHighlightPainter; | 6 | import cuchaz.enigma.gui.highlight.BoxHighlightPainter; |
| 7 | import cuchaz.enigma.gui.highlight.ObfuscatedHighlightPainter; | ||
| 8 | import cuchaz.enigma.gui.highlight.OtherHighlightPainter; | ||
| 9 | import de.sciss.syntaxpane.DefaultSyntaxKit; | 7 | import de.sciss.syntaxpane.DefaultSyntaxKit; |
| 10 | 8 | ||
| 11 | import javax.swing.*; | 9 | import javax.swing.*; |
| 12 | import java.awt.*; | ||
| 13 | import java.io.IOException; | 10 | import java.io.IOException; |
| 14 | 11 | ||
| 15 | public class Themes { | 12 | public class Themes { |
| @@ -27,12 +24,15 @@ public class Themes { | |||
| 27 | } catch (IOException e) { | 24 | } catch (IOException e) { |
| 28 | e.printStackTrace(); | 25 | e.printStackTrace(); |
| 29 | } | 26 | } |
| 30 | MinecraftSyntaxKit.invalidate(); | 27 | EnigmaSyntaxKit.invalidate(); |
| 31 | DefaultSyntaxKit.initKit(); | 28 | DefaultSyntaxKit.initKit(); |
| 32 | DefaultSyntaxKit.registerContentType("text/minecraft", MinecraftSyntaxKit.class.getName()); | 29 | DefaultSyntaxKit.registerContentType("text/enigma-sources", EnigmaSyntaxKit.class.getName()); |
| 33 | gui.obfuscatedHighlightPainter = new ObfuscatedHighlightPainter(); | 30 | gui.boxHighlightPainters = ImmutableMap.of( |
| 34 | gui.deobfuscatedHighlightPainter = new DeobfuscatedHighlightPainter(); | 31 | "obfuscated", BoxHighlightPainter.create(Config.getInstance().obfuscatedColor, Config.getInstance().obfuscatedColorOutline), |
| 35 | gui.otherHighlightPainter = new OtherHighlightPainter(); | 32 | "proposed", BoxHighlightPainter.create(Config.getInstance().proposedColor, Config.getInstance().proposedColorOutline), |
| 33 | "deobfuscated", BoxHighlightPainter.create(Config.getInstance().deobfuscatedColor, Config.getInstance().deobfuscatedColorOutline), | ||
| 34 | "other", BoxHighlightPainter.create(null, Config.getInstance().otherColorOutline) | ||
| 35 | ); | ||
| 36 | gui.setEditorTheme(Config.getInstance().lookAndFeel); | 36 | gui.setEditorTheme(Config.getInstance().lookAndFeel); |
| 37 | SwingUtilities.updateComponentTreeUI(gui.getFrame()); | 37 | SwingUtilities.updateComponentTreeUI(gui.getFrame()); |
| 38 | } | 38 | } |
diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java index ac45b4a7..137c7303 100644 --- a/src/main/java/cuchaz/enigma/gui/CodeReader.java +++ b/src/main/java/cuchaz/enigma/gui/CodeReader.java | |||
| @@ -143,6 +143,7 @@ public class CodeReader extends JEditorPane { | |||
| 143 | { | 143 | { |
| 144 | 144 | ||
| 145 | // decompile it | 145 | // decompile it |
| 146 | |||
| 146 | CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName()); | 147 | CompilationUnit sourceTree = deobfuscator.getSourceTree(classEntry.getOutermostClassName()); |
| 147 | String source = deobfuscator.getSource(sourceTree); | 148 | String source = deobfuscator.getSource(sourceTree); |
| 148 | setCode(source); | 149 | setCode(source); |
diff --git a/src/main/java/cuchaz/enigma/gui/MinecraftSyntaxKit.java b/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java index d9fcee53..5ea0bc20 100644 --- a/src/main/java/cuchaz/enigma/gui/MinecraftSyntaxKit.java +++ b/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java | |||
| @@ -5,7 +5,7 @@ import de.sciss.syntaxpane.components.LineNumbersRuler; | |||
| 5 | import de.sciss.syntaxpane.syntaxkits.JavaSyntaxKit; | 5 | import de.sciss.syntaxpane.syntaxkits.JavaSyntaxKit; |
| 6 | import de.sciss.syntaxpane.util.Configuration; | 6 | import de.sciss.syntaxpane.util.Configuration; |
| 7 | 7 | ||
| 8 | public class MinecraftSyntaxKit extends JavaSyntaxKit { | 8 | public class EnigmaSyntaxKit extends JavaSyntaxKit { |
| 9 | private static Configuration configuration = null; | 9 | private static Configuration configuration = null; |
| 10 | 10 | ||
| 11 | @Override | 11 | @Override |
diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java index 06e78420..8ec58f9e 100644 --- a/src/main/java/cuchaz/enigma/gui/Gui.java +++ b/src/main/java/cuchaz/enigma/gui/Gui.java | |||
| @@ -22,9 +22,7 @@ import cuchaz.enigma.gui.elements.MenuBar; | |||
| 22 | import cuchaz.enigma.gui.elements.PopupMenuBar; | 22 | import cuchaz.enigma.gui.elements.PopupMenuBar; |
| 23 | import cuchaz.enigma.gui.filechooser.FileChooserAny; | 23 | import cuchaz.enigma.gui.filechooser.FileChooserAny; |
| 24 | import cuchaz.enigma.gui.filechooser.FileChooserFolder; | 24 | import cuchaz.enigma.gui.filechooser.FileChooserFolder; |
| 25 | import cuchaz.enigma.gui.highlight.DeobfuscatedHighlightPainter; | 25 | import cuchaz.enigma.gui.highlight.BoxHighlightPainter; |
| 26 | import cuchaz.enigma.gui.highlight.ObfuscatedHighlightPainter; | ||
| 27 | import cuchaz.enigma.gui.highlight.OtherHighlightPainter; | ||
| 28 | import cuchaz.enigma.gui.highlight.SelectionHighlightPainter; | 26 | import cuchaz.enigma.gui.highlight.SelectionHighlightPainter; |
| 29 | import cuchaz.enigma.gui.node.ClassSelectorPackageNode; | 27 | import cuchaz.enigma.gui.node.ClassSelectorPackageNode; |
| 30 | import cuchaz.enigma.gui.panels.PanelDeobf; | 28 | import cuchaz.enigma.gui.panels.PanelDeobf; |
| @@ -48,10 +46,8 @@ import java.awt.*; | |||
| 48 | import java.awt.event.*; | 46 | import java.awt.event.*; |
| 49 | import java.io.File; | 47 | import java.io.File; |
| 50 | import java.io.IOException; | 48 | import java.io.IOException; |
| 51 | import java.util.Collection; | 49 | import java.util.*; |
| 52 | import java.util.Collections; | ||
| 53 | import java.util.List; | 50 | import java.util.List; |
| 54 | import java.util.Vector; | ||
| 55 | import java.util.function.Function; | 51 | import java.util.function.Function; |
| 56 | 52 | ||
| 57 | public class Gui { | 53 | public class Gui { |
| @@ -75,9 +71,7 @@ public class Gui { | |||
| 75 | private JPanel classesPanel; | 71 | private JPanel classesPanel; |
| 76 | private JSplitPane splitClasses; | 72 | private JSplitPane splitClasses; |
| 77 | private PanelIdentifier infoPanel; | 73 | private PanelIdentifier infoPanel; |
| 78 | public ObfuscatedHighlightPainter obfuscatedHighlightPainter; | 74 | public Map<String, BoxHighlightPainter> boxHighlightPainters; |
| 79 | public DeobfuscatedHighlightPainter deobfuscatedHighlightPainter; | ||
| 80 | public OtherHighlightPainter otherHighlightPainter; | ||
| 81 | private SelectionHighlightPainter selectionHighlightPainter; | 75 | private SelectionHighlightPainter selectionHighlightPainter; |
| 82 | private JTree inheritanceTree; | 76 | private JTree inheritanceTree; |
| 83 | private JTree implementationsTree; | 77 | private JTree implementationsTree; |
| @@ -145,7 +139,7 @@ public class Gui { | |||
| 145 | selectionHighlightPainter = new SelectionHighlightPainter(); | 139 | selectionHighlightPainter = new SelectionHighlightPainter(); |
| 146 | this.editor = new PanelEditor(this); | 140 | this.editor = new PanelEditor(this); |
| 147 | JScrollPane sourceScroller = new JScrollPane(this.editor); | 141 | JScrollPane sourceScroller = new JScrollPane(this.editor); |
| 148 | this.editor.setContentType("text/minecraft"); | 142 | this.editor.setContentType("text/enigma-sources"); |
| 149 | this.editor.setBackground(new Color(Config.getInstance().editorBackground)); | 143 | this.editor.setBackground(new Color(Config.getInstance().editorBackground)); |
| 150 | DefaultSyntaxKit kit = (DefaultSyntaxKit) this.editor.getEditorKit(); | 144 | DefaultSyntaxKit kit = (DefaultSyntaxKit) this.editor.getEditorKit(); |
| 151 | kit.toggleComponent(this.editor, "de.sciss.syntaxpane.components.TokenMarker"); | 145 | kit.toggleComponent(this.editor, "de.sciss.syntaxpane.components.TokenMarker"); |
| @@ -311,11 +305,11 @@ public class Gui { | |||
| 311 | return this.controller; | 305 | return this.controller; |
| 312 | } | 306 | } |
| 313 | 307 | ||
| 314 | public void onStartOpenJar() { | 308 | public void onStartOpenJar(String message) { |
| 315 | this.classesPanel.removeAll(); | 309 | this.classesPanel.removeAll(); |
| 316 | JPanel panel = new JPanel(); | 310 | JPanel panel = new JPanel(); |
| 317 | panel.setLayout(new FlowLayout()); | 311 | panel.setLayout(new FlowLayout()); |
| 318 | panel.add(new JLabel("Loading...")); | 312 | panel.add(new JLabel(message)); |
| 319 | this.classesPanel.add(panel); | 313 | this.classesPanel.add(panel); |
| 320 | 314 | ||
| 321 | redraw(); | 315 | redraw(); |
| @@ -407,20 +401,17 @@ public class Gui { | |||
| 407 | showToken(sortedTokens.get(0)); | 401 | showToken(sortedTokens.get(0)); |
| 408 | } | 402 | } |
| 409 | 403 | ||
| 410 | public void setHighlightedTokens(Iterable<Token> obfuscatedTokens, Iterable<Token> deobfuscatedTokens, Iterable<Token> otherTokens) { | 404 | public void setHighlightedTokens(Map<String, Iterable<Token>> tokens) { |
| 411 | |||
| 412 | // remove any old highlighters | 405 | // remove any old highlighters |
| 413 | this.editor.getHighlighter().removeAllHighlights(); | 406 | this.editor.getHighlighter().removeAllHighlights(); |
| 414 | 407 | ||
| 415 | // color things based on the index | 408 | if (boxHighlightPainters != null) { |
| 416 | if (obfuscatedTokens != null) { | 409 | for (String s : tokens.keySet()) { |
| 417 | setHighlightedTokens(obfuscatedTokens, obfuscatedHighlightPainter); | 410 | BoxHighlightPainter painter = boxHighlightPainters.get(s); |
| 418 | } | 411 | if (painter != null) { |
| 419 | if (deobfuscatedTokens != null) { | 412 | setHighlightedTokens(tokens.get(s), painter); |
| 420 | setHighlightedTokens(deobfuscatedTokens, deobfuscatedHighlightPainter); | 413 | } |
| 421 | } | 414 | } |
| 422 | if (otherTokens != null) { | ||
| 423 | setHighlightedTokens(otherTokens, otherHighlightPainter); | ||
| 424 | } | 415 | } |
| 425 | 416 | ||
| 426 | redraw(); | 417 | redraw(); |
| @@ -582,7 +573,7 @@ public class Gui { | |||
| 582 | 573 | ||
| 583 | // init the text box | 574 | // init the text box |
| 584 | final JTextField text = new JTextField(); | 575 | final JTextField text = new JTextField(); |
| 585 | text.setText(reference.getNamableName()); | 576 | text.setText(reference.getNameableName()); |
| 586 | text.setPreferredSize(new Dimension(360, text.getPreferredSize().height)); | 577 | text.setPreferredSize(new Dimension(360, text.getPreferredSize().height)); |
| 587 | text.addKeyListener(new KeyAdapter() { | 578 | text.addKeyListener(new KeyAdapter() { |
| 588 | @Override | 579 | @Override |
| @@ -633,7 +624,7 @@ public class Gui { | |||
| 633 | // abort the rename | 624 | // abort the rename |
| 634 | JPanel panel = (JPanel) infoPanel.getComponent(0); | 625 | JPanel panel = (JPanel) infoPanel.getComponent(0); |
| 635 | panel.remove(panel.getComponentCount() - 1); | 626 | panel.remove(panel.getComponentCount() - 1); |
| 636 | panel.add(Utils.unboldLabel(new JLabel(reference.getNamableName(), JLabel.LEFT))); | 627 | panel.add(Utils.unboldLabel(new JLabel(reference.getNameableName(), JLabel.LEFT))); |
| 637 | 628 | ||
| 638 | this.editor.grabFocus(); | 629 | this.editor.grabFocus(); |
| 639 | 630 | ||
diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java index 6e15bb02..e2f332d0 100644 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ b/src/main/java/cuchaz/enigma/gui/GuiController.java | |||
| @@ -11,13 +11,14 @@ | |||
| 11 | 11 | ||
| 12 | package cuchaz.enigma.gui; | 12 | package cuchaz.enigma.gui; |
| 13 | 13 | ||
| 14 | import com.google.common.collect.ImmutableMap; | ||
| 14 | import com.google.common.collect.Lists; | 15 | import com.google.common.collect.Lists; |
| 15 | import com.google.common.collect.Queues; | 16 | import com.google.common.collect.Queues; |
| 16 | import com.strobel.decompiler.languages.java.ast.CompilationUnit; | 17 | import com.strobel.decompiler.languages.java.ast.CompilationUnit; |
| 17 | import cuchaz.enigma.Deobfuscator; | 18 | import cuchaz.enigma.Deobfuscator; |
| 18 | import cuchaz.enigma.analysis.*; | 19 | import cuchaz.enigma.analysis.*; |
| 20 | import cuchaz.enigma.api.EnigmaPlugin; | ||
| 19 | import cuchaz.enigma.config.Config; | 21 | import cuchaz.enigma.config.Config; |
| 20 | import cuchaz.enigma.config.Themes; | ||
| 21 | import cuchaz.enigma.gui.dialog.ProgressDialog; | 22 | import cuchaz.enigma.gui.dialog.ProgressDialog; |
| 22 | import cuchaz.enigma.mapping.*; | 23 | import cuchaz.enigma.mapping.*; |
| 23 | import cuchaz.enigma.mapping.entry.ClassEntry; | 24 | import cuchaz.enigma.mapping.entry.ClassEntry; |
| @@ -30,9 +31,7 @@ import cuchaz.enigma.utils.ReadableToken; | |||
| 30 | import java.awt.event.ItemEvent; | 31 | import java.awt.event.ItemEvent; |
| 31 | import java.io.File; | 32 | import java.io.File; |
| 32 | import java.io.IOException; | 33 | import java.io.IOException; |
| 33 | import java.util.Collection; | 34 | import java.util.*; |
| 34 | import java.util.Deque; | ||
| 35 | import java.util.List; | ||
| 36 | import java.util.jar.JarFile; | 35 | import java.util.jar.JarFile; |
| 37 | 36 | ||
| 38 | public class GuiController { | 37 | public class GuiController { |
| @@ -58,8 +57,10 @@ public class GuiController { | |||
| 58 | } | 57 | } |
| 59 | 58 | ||
| 60 | public void openJar(final JarFile jar) throws IOException { | 59 | public void openJar(final JarFile jar) throws IOException { |
| 61 | this.gui.onStartOpenJar(); | 60 | this.gui.onStartOpenJar("Loading JAR..."); |
| 62 | this.deobfuscator = new Deobfuscator(jar); | 61 | this.deobfuscator = new Deobfuscator(jar, (msg) -> { |
| 62 | this.gui.onStartOpenJar(msg); | ||
| 63 | }); | ||
| 63 | this.gui.onFinishOpenJar(jar.getName()); | 64 | this.gui.onFinishOpenJar(jar.getName()); |
| 64 | refreshClasses(); | 65 | refreshClasses(); |
| 65 | } | 66 | } |
| @@ -162,7 +163,7 @@ public class GuiController { | |||
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | public boolean referenceIsRenameable(EntryReference<Entry, Entry> deobfReference) { | 165 | public boolean referenceIsRenameable(EntryReference<Entry, Entry> deobfReference) { |
| 165 | return this.deobfuscator.isRenameable(this.deobfuscator.obfuscateReference(deobfReference), true); | 166 | return this.deobfuscator.isRenameable(this.deobfuscator.obfuscateReference(deobfReference)); |
| 166 | } | 167 | } |
| 167 | 168 | ||
| 168 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) { | 169 | public ClassInheritanceTreeNode getClassInheritance(ClassEntry deobfClassEntry) { |
| @@ -334,29 +335,73 @@ public class GuiController { | |||
| 334 | } | 335 | } |
| 335 | String source = deobfuscator.getSource(sourceTree); | 336 | String source = deobfuscator.getSource(sourceTree); |
| 336 | index = deobfuscator.getSourceIndex(sourceTree, source); | 337 | index = deobfuscator.getSourceIndex(sourceTree, source); |
| 337 | gui.setSource(index.getSource()); | 338 | |
| 338 | if (obfReference != null) { | 339 | String sourceString = index.getSource(); |
| 339 | showReference(obfReference); | ||
| 340 | } | ||
| 341 | 340 | ||
| 342 | // set the highlighted tokens | 341 | // set the highlighted tokens |
| 343 | List<Token> obfuscatedTokens = Lists.newArrayList(); | 342 | List<Token> obfuscatedTokens = Lists.newArrayList(); |
| 343 | List<Token> proposedTokens = Lists.newArrayList(); | ||
| 344 | List<Token> deobfuscatedTokens = Lists.newArrayList(); | 344 | List<Token> deobfuscatedTokens = Lists.newArrayList(); |
| 345 | List<Token> otherTokens = Lists.newArrayList(); | 345 | List<Token> otherTokens = Lists.newArrayList(); |
| 346 | for (Token token : index.referenceTokens()) { | 346 | |
| 347 | EntryReference<Entry, Entry> reference = index.getDeobfReference(token); | 347 | int offset = 0; |
| 348 | Map<Token, Token> tokenRemap = new IdentityHashMap<>(); | ||
| 349 | boolean remapped = false; | ||
| 350 | |||
| 351 | for (Token inToken : index.referenceTokens()) { | ||
| 352 | EntryReference<Entry, Entry> reference = index.getDeobfReference(inToken); | ||
| 353 | Token token = inToken.move(offset); | ||
| 354 | |||
| 348 | if (referenceIsRenameable(reference)) { | 355 | if (referenceIsRenameable(reference)) { |
| 349 | if (entryHasDeobfuscatedName(reference.getNameableEntry())) { | 356 | boolean renamed = false; |
| 350 | deobfuscatedTokens.add(token); | 357 | |
| 351 | } else { | 358 | if (!entryHasDeobfuscatedName(reference.getNameableEntry())) { |
| 352 | obfuscatedTokens.add(token); | 359 | Entry obfEntry = deobfuscator.obfuscateEntry(reference.getNameableEntry()); |
| 360 | if (obfEntry instanceof FieldEntry) { | ||
| 361 | for (EnigmaPlugin plugin : deobfuscator.getPlugins()) { | ||
| 362 | String proposal = plugin.proposeFieldName(obfEntry.getClassName(), obfEntry.getName(), ((FieldEntry) obfEntry).getDesc().toString()); | ||
| 363 | if (proposal != null) { | ||
| 364 | proposedTokens.add(token); | ||
| 365 | offset += token.getRenameOffset(proposal); | ||
| 366 | sourceString = token.rename(sourceString, proposal); | ||
| 367 | renamed = true; | ||
| 368 | remapped = true; | ||
| 369 | break; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | } | ||
| 373 | } | ||
| 374 | |||
| 375 | if (!renamed) { | ||
| 376 | if (entryHasDeobfuscatedName(reference.getNameableEntry())) { | ||
| 377 | deobfuscatedTokens.add(token); | ||
| 378 | } else { | ||
| 379 | obfuscatedTokens.add(token); | ||
| 380 | } | ||
| 353 | } | 381 | } |
| 354 | } else { | 382 | } else { |
| 355 | otherTokens.add(token); | 383 | otherTokens.add(token); |
| 356 | } | 384 | } |
| 385 | |||
| 386 | tokenRemap.put(inToken, token); | ||
| 387 | } | ||
| 388 | |||
| 389 | if (remapped) { | ||
| 390 | index.remap(sourceString, tokenRemap); | ||
| 391 | } | ||
| 392 | |||
| 393 | gui.setSource(sourceString); | ||
| 394 | if (obfReference != null) { | ||
| 395 | showReference(obfReference); | ||
| 357 | } | 396 | } |
| 397 | |||
| 358 | gui.setEditorTheme(Config.getInstance().lookAndFeel); | 398 | gui.setEditorTheme(Config.getInstance().lookAndFeel); |
| 359 | gui.setHighlightedTokens(obfuscatedTokens, deobfuscatedTokens, otherTokens); | 399 | gui.setHighlightedTokens(ImmutableMap.of( |
| 400 | "obfuscated", obfuscatedTokens, | ||
| 401 | "proposed", proposedTokens, | ||
| 402 | "deobfuscated", deobfuscatedTokens, | ||
| 403 | "other", otherTokens | ||
| 404 | )); | ||
| 360 | }).start(); | 405 | }).start(); |
| 361 | } | 406 | } |
| 362 | 407 | ||
diff --git a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java index 976c215e..10366ced 100644 --- a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java +++ b/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java | |||
| @@ -11,13 +11,14 @@ | |||
| 11 | 11 | ||
| 12 | package cuchaz.enigma.gui.highlight; | 12 | package cuchaz.enigma.gui.highlight; |
| 13 | 13 | ||
| 14 | import cuchaz.enigma.config.Config; | ||
| 15 | |||
| 14 | import javax.swing.text.BadLocationException; | 16 | import javax.swing.text.BadLocationException; |
| 15 | import javax.swing.text.Highlighter; | 17 | import javax.swing.text.Highlighter; |
| 16 | import javax.swing.text.JTextComponent; | 18 | import javax.swing.text.JTextComponent; |
| 17 | import java.awt.*; | 19 | import java.awt.*; |
| 18 | 20 | ||
| 19 | public abstract class BoxHighlightPainter implements Highlighter.HighlightPainter { | 21 | public class BoxHighlightPainter implements Highlighter.HighlightPainter { |
| 20 | |||
| 21 | private Color fillColor; | 22 | private Color fillColor; |
| 22 | private Color borderColor; | 23 | private Color borderColor; |
| 23 | 24 | ||
| @@ -26,6 +27,10 @@ public abstract class BoxHighlightPainter implements Highlighter.HighlightPainte | |||
| 26 | this.borderColor = borderColor; | 27 | this.borderColor = borderColor; |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 30 | public static BoxHighlightPainter create(Config.AlphaColorEntry entry, Config.AlphaColorEntry entryOutline) { | ||
| 31 | return new BoxHighlightPainter(entry != null ? entry.get() : null, entryOutline != null ? entryOutline.get() : null); | ||
| 32 | } | ||
| 33 | |||
| 29 | public static Rectangle getBounds(JTextComponent text, int start, int end) { | 34 | public static Rectangle getBounds(JTextComponent text, int start, int end) { |
| 30 | try { | 35 | try { |
| 31 | // determine the bounds of the text | 36 | // determine the bounds of the text |
| @@ -59,8 +64,4 @@ public abstract class BoxHighlightPainter implements Highlighter.HighlightPainte | |||
| 59 | g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); | 64 | g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); |
| 60 | } | 65 | } |
| 61 | 66 | ||
| 62 | protected static Color getColor(int rgb, float alpha){ | ||
| 63 | Color baseColor = new Color(rgb); | ||
| 64 | return new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), (int)(255 * alpha)); | ||
| 65 | } | ||
| 66 | } | 67 | } |
diff --git a/src/main/java/cuchaz/enigma/gui/highlight/DeobfuscatedHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/DeobfuscatedHighlightPainter.java deleted file mode 100644 index 41aa97f8..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/DeobfuscatedHighlightPainter.java +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.gui.highlight; | ||
| 13 | |||
| 14 | import cuchaz.enigma.config.Config; | ||
| 15 | |||
| 16 | public class DeobfuscatedHighlightPainter extends BoxHighlightPainter { | ||
| 17 | |||
| 18 | public DeobfuscatedHighlightPainter() { | ||
| 19 | super(getColor(Config.getInstance().deobfuscatedColor, Config.getInstance().deobfuscatedHiglightAlpha), getColor(Config.getInstance().deobfuscatedColorOutline, Config.getInstance().deobfuscatedOutlineAlpha)); | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/src/main/java/cuchaz/enigma/gui/highlight/ObfuscatedHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/ObfuscatedHighlightPainter.java deleted file mode 100644 index d7358743..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/ObfuscatedHighlightPainter.java +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.gui.highlight; | ||
| 13 | |||
| 14 | import cuchaz.enigma.config.Config; | ||
| 15 | |||
| 16 | public class ObfuscatedHighlightPainter extends BoxHighlightPainter { | ||
| 17 | |||
| 18 | public ObfuscatedHighlightPainter() { | ||
| 19 | super(getColor(Config.getInstance().obfuscatedColor, Config.getInstance().obfuscatedHiglightAlpha), getColor(Config.getInstance().obfuscatedColorOutline, Config.getInstance().obfuscatedOutlineAlpha)); | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/src/main/java/cuchaz/enigma/gui/highlight/OtherHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/OtherHighlightPainter.java deleted file mode 100644 index f4ae235a..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/OtherHighlightPainter.java +++ /dev/null | |||
| @@ -1,21 +0,0 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2015 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Lesser General Public | ||
| 5 | * License v3.0 which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/lgpl.html | ||
| 7 | * <p> | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | |||
| 12 | package cuchaz.enigma.gui.highlight; | ||
| 13 | |||
| 14 | import cuchaz.enigma.config.Config; | ||
| 15 | |||
| 16 | public class OtherHighlightPainter extends BoxHighlightPainter { | ||
| 17 | |||
| 18 | public OtherHighlightPainter() { | ||
| 19 | super(null, getColor(Config.getInstance().otherColorOutline, Config.getInstance().otherOutlineAlpha)); | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java index 99a63154..10fb9215 100644 --- a/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java +++ b/src/main/java/cuchaz/enigma/mapping/DirectionalTranslator.java | |||
| @@ -20,6 +20,7 @@ import cuchaz.enigma.mapping.entry.*; | |||
| 20 | import java.util.ArrayList; | 20 | import java.util.ArrayList; |
| 21 | import java.util.List; | 21 | import java.util.List; |
| 22 | import java.util.Map; | 22 | import java.util.Map; |
| 23 | import java.util.ServiceLoader; | ||
| 23 | 24 | ||
| 24 | public class DirectionalTranslator implements Translator { | 25 | public class DirectionalTranslator implements Translator { |
| 25 | private final TranslationDirection direction; | 26 | private final TranslationDirection direction; |
diff --git a/src/main/java/cuchaz/enigma/mapping/Mappings.java b/src/main/java/cuchaz/enigma/mapping/Mappings.java index 3ef1be52..c8650795 100644 --- a/src/main/java/cuchaz/enigma/mapping/Mappings.java +++ b/src/main/java/cuchaz/enigma/mapping/Mappings.java | |||
| @@ -15,6 +15,7 @@ import com.google.common.collect.Lists; | |||
| 15 | import com.google.common.collect.Maps; | 15 | import com.google.common.collect.Maps; |
| 16 | import com.google.common.collect.Sets; | 16 | import com.google.common.collect.Sets; |
| 17 | import cuchaz.enigma.analysis.TranslationIndex; | 17 | import cuchaz.enigma.analysis.TranslationIndex; |
| 18 | import cuchaz.enigma.api.EnigmaPlugin; | ||
| 18 | import cuchaz.enigma.bytecode.AccessFlags; | 19 | import cuchaz.enigma.bytecode.AccessFlags; |
| 19 | import cuchaz.enigma.mapping.entry.ClassEntry; | 20 | import cuchaz.enigma.mapping.entry.ClassEntry; |
| 20 | import cuchaz.enigma.mapping.entry.MethodEntry; | 21 | import cuchaz.enigma.mapping.entry.MethodEntry; |