diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/FernFlowerDecompiler.java b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/FernFlowerDecompiler.java index b16b9c95d..3c2398eac 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/FernFlowerDecompiler.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/FernFlowerDecompiler.java @@ -22,17 +22,23 @@ import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler; import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InnerClassNode; import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.Constants; +import the.bytecode.club.bytecodeviewer.api.ASMUtil; import the.bytecode.club.bytecodeviewer.api.ExceptionUI; import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler; import the.bytecode.club.bytecodeviewer.resources.ExternalResources; +import the.bytecode.club.bytecodeviewer.resources.ResourceContainer; import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; import the.bytecode.club.bytecodeviewer.util.ExceptionUtils; import the.bytecode.club.bytecodeviewer.util.ProcessUtils; import the.bytecode.club.bytecodeviewer.util.TempFile; import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import static the.bytecode.club.bytecodeviewer.Constants.*; import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*; @@ -51,12 +57,61 @@ public FernFlowerDecompiler() super("FernFlower Decompiler", "fernflower"); } + private String[] inners; + private final List innerFiles = new ArrayList<>(); @Override public String decompileClassNode(ClassNode cn, byte[] bytes) { TempFile tempFile = null; String exception; + List innerClasses = cn.innerClasses; + List innerTempFiles = new ArrayList<>(); + AtomicReference innerTempFile = new AtomicReference<>(); + if (BytecodeViewer.viewer.din.isSelected()) + { + inners = new String[innerClasses.size()]; + for (int i = 0; i < innerClasses.size(); i++) + { + if (innerClasses.get(i).outerName != null && innerClasses.get(i).outerName.equals(cn.name)) + { + inners[i] = innerClasses.get(i).name; + } + else if (innerClasses.get(i).outerName == null) + { + String name = innerClasses.get(i).name; + name = name.substring(name.lastIndexOf('/') + 1); + if (name.contains(cn.name.substring(cn.name.lastIndexOf('/') + 1))) + { + inners[i] = innerClasses.get(i).name; + } + } + } + + for (ResourceContainer container :BytecodeViewer.resourceContainers.values()) { + container.resourceClasses.forEach((s, classNode) -> { + for (String innerClassName : inners) { + if (s.equals(innerClassName)) { + innerTempFile.set(TempFile.createTemporaryFile(true, ".class")); + File tempInputClassFile2 = innerTempFile.get().getFile(); + try (FileOutputStream fos = new FileOutputStream(tempInputClassFile2)) { + fos.write(ASMUtil.nodeToBytes(classNode)); + } + catch (IOException e) + { + throw new RuntimeException(e); + } finally + { + innerFiles.add(tempInputClassFile2); + innerTempFile.get().markAsCreatedFile(tempInputClassFile2); + innerTempFiles.add(innerTempFile.get()); + } + } + } + }); + } + } + try { //create the temporary files @@ -80,12 +135,17 @@ public String decompileClassNode(ClassNode cn, byte[] bytes) { ExternalResources.getSingleton().getJavaCommand(true), "-jar", ExternalResources.getSingleton().findLibrary("fernflower") - }, generateMainMethod(tempInputClassFile.getAbsolutePath(), tempFile.getParent().getAbsolutePath()) + }, generateMainMethod(tempInputClassFile.getAbsolutePath(), "", tempFile.getParent().getAbsolutePath()) ), false); } else { - org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempInputClassFile.getAbsolutePath(), new File(TEMP_DIRECTORY).getAbsolutePath())); + List strings = generate(tempInputClassFile.getAbsolutePath(), + new File(TEMP_DIRECTORY).getAbsolutePath()); + + String[] args = strings.toArray(new String[0]); + + org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(args); } //if rename is enabled the file name will be the actual class name @@ -112,6 +172,21 @@ public String decompileClassNode(ClassNode cn, byte[] bytes) //cleanup temp files if(tempFile != null) tempFile.cleanup(); + + if (innerTempFile.get() != null) + innerTempFile.get().cleanup(); + + for (TempFile file : innerTempFiles) + { + file.cleanup(); + File file1 = new File(TEMP_DIRECTORY + file.getUniqueName() + ".java"); + if (file1.exists()) + { + file1.delete(); + } + } + + innerFiles.clear(); } return FERNFLOWER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL @@ -127,7 +202,7 @@ public void decompileToZip(String sourceJar, String zipName) try { - ConsoleDecompiler.main(generateMainMethod(tempInputJarFile.getAbsolutePath(), TEMP_DIRECTORY + "./temp/")); + ConsoleDecompiler.main(generateMainMethod(tempInputJarFile.getAbsolutePath(), "", TEMP_DIRECTORY + "./temp/")); } catch (StackOverflowError | Exception ignored) { @@ -140,7 +215,40 @@ public void decompileToZip(String sourceJar, String zipName) } - private String[] generateMainMethod(String className, String folder) + private List generate(String className, String folder) + { + List strings = new ArrayList<>(); + strings.add("-rbr=" + ffOnValue(BytecodeViewer.viewer.rbr.isSelected())); + strings.add("-rsy=" + ffOnValue(BytecodeViewer.viewer.rsy.isSelected())); + strings.add("-din=" + ffOnValue(BytecodeViewer.viewer.din.isSelected())); + strings.add("-dc4=" + ffOnValue(BytecodeViewer.viewer.dc4.isSelected())); + strings.add("-das=" + ffOnValue(BytecodeViewer.viewer.das.isSelected())); + strings.add("-hes=" + ffOnValue(BytecodeViewer.viewer.hes.isSelected())); + strings.add("-hdc=" + ffOnValue(BytecodeViewer.viewer.hdc.isSelected())); + strings.add("-dgs=" + ffOnValue(BytecodeViewer.viewer.dgs.isSelected())); + strings.add("-ner=" + ffOnValue(BytecodeViewer.viewer.ner.isSelected())); + strings.add("-den=" + ffOnValue(BytecodeViewer.viewer.den.isSelected())); + strings.add("-rgn=" + ffOnValue(BytecodeViewer.viewer.rgn.isSelected())); + strings.add("-bto=" + ffOnValue(BytecodeViewer.viewer.bto.isSelected())); + strings.add("-nns=" + ffOnValue(BytecodeViewer.viewer.nns.isSelected())); + strings.add("-uto=" + ffOnValue(BytecodeViewer.viewer.uto.isSelected())); + strings.add("-udv=" + ffOnValue(BytecodeViewer.viewer.udv.isSelected())); + strings.add("-rer=" + ffOnValue(BytecodeViewer.viewer.rer.isSelected())); + strings.add("-fdi=" + ffOnValue(BytecodeViewer.viewer.fdi.isSelected())); + strings.add("-asc=" + ffOnValue(BytecodeViewer.viewer.asc.isSelected())); + strings.add("-ren=" + ffOnValue(BytecodeViewer.viewer.ren.isSelected())); + strings.add(className); + if (BytecodeViewer.viewer.din.isSelected()) + { + for (File file : innerFiles) + strings.add(file.getAbsolutePath()); + } + + strings.add(folder); + return strings; + } + + private String[] generateMainMethod(String className, String test, String folder) { return new String[] { @@ -163,7 +271,7 @@ private String[] generateMainMethod(String className, String folder) "-fdi=" + ffOnValue(BytecodeViewer.viewer.fdi.isSelected()), "-asc=" + ffOnValue(BytecodeViewer.viewer.asc.isSelected()), "-ren=" + ffOnValue(BytecodeViewer.viewer.ren.isSelected()), - className, folder + className, test, folder }; }