diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java index c5d022d2..c8989c19 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/BytecodeViewer.java @@ -313,7 +313,7 @@ public class BytecodeViewer */ public static ClassNode getCurrentlyOpenedClassNode() { - return getActiveResource().cn; + return getActiveResource().viewerClassNode; } /** diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/GlobalHotKeys.java b/src/main/java/the/bytecode/club/bytecodeviewer/GlobalHotKeys.java index dd856329..9d2ec8d4 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/GlobalHotKeys.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/GlobalHotKeys.java @@ -134,7 +134,6 @@ public class GlobalHotKeys Configuration.lastHotKeyExecuted = System.currentTimeMillis(); String recentFile = Settings.getRecentFile(); - System.out.println("Opening..." + recentFile); if(!BytecodeViewer.hasResources() && recentFile != null) { diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java index 12995ab3..573fe4c8 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcelist/ResourceListPane.java @@ -166,9 +166,8 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File if (!container.resourceClasses.isEmpty()) { - for (ClassNode c : container.resourceClasses.values()) + for (String name : container.resourceClasses.keySet()) { - String name = c.name; final String[] spl = name.split("/"); if (spl.length < 2) { @@ -304,9 +303,10 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File } String name = nameBuffer.toString(); + if (name.endsWith(".class")) { - final ClassNode cn = Objects.requireNonNull(container).getClassNode( + final ClassNode cn = container.getClassNode( name.substring(0, name.length() - ".class".length())); if (cn != null) diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcesearch/SearchBoxPane.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcesearch/SearchBoxPane.java index 7795d8a7..011a5a50 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcesearch/SearchBoxPane.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourcesearch/SearchBoxPane.java @@ -188,7 +188,7 @@ public class SearchBoxPane extends TranslatedVisibleComponent final ResourceViewer cv = BytecodeViewer.getActiveResource(); if (cv != null) - searchType.details.search(cv.container, cv.cn, srn, exact.isSelected()); + searchType.details.search(cv.container, cv.viewerClassNode, srn, exact.isSelected()); } } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java index f52a5ed6..96893e91 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewPanel.java @@ -1,7 +1,6 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer; import org.objectweb.asm.tree.ClassNode; -import the.bytecode.club.bytecodeviewer.BytecodeViewer; import the.bytecode.club.bytecodeviewer.compilers.Compiler; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; @@ -59,9 +58,9 @@ public class ResourceViewPanel panel.removeAll(); textArea = null; - if(viewer.cn == null) + if(viewer.viewerClassNode == null) { - panel.add(new JLabel("This resource has been removed.")); + panel.add(new JLabel("ERROR: Resource Viewer Corrupt ClassNode")); } } @@ -76,7 +75,7 @@ public class ResourceViewPanel return true; SystemConsole errConsole = new SystemConsole("Java Compile Issues"); - errConsole.setText("Error compiling class: " + viewer.cn.name + + errConsole.setText("Error compiling class: " + viewer.viewerClassNode.name + nl + "Keep in mind most decompilers cannot produce compilable classes" + nl + nl + TranslatedStrings.SUGGESTED_FIX_COMPILER_ERROR + nl + nl); @@ -84,12 +83,12 @@ public class ResourceViewPanel try { String text = textArea.getText(); - byte[] compiledClass = compileMode.getCompiler().compile(text, viewer.cn.name); + byte[] compiledClass = compileMode.getCompiler().compile(text, viewer.viewerClassNode.name); if (compiledClass != null) { ClassNode newNode = JarUtils.getNode(compiledClass); - viewer.container.updateNode(viewer.cn, newNode); + viewer.container.updateNode(viewer.viewerClassNode, newNode); errConsole.finished(); return true; } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java index 351a217e..0b3f1366 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/ResourceViewProcessing.java @@ -1,22 +1,15 @@ package the.bytecode.club.bytecodeviewer.gui.resourceviewer; -import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.objectweb.asm.ClassWriter; import the.bytecode.club.bytecodeviewer.BytecodeViewer; -import the.bytecode.club.bytecodeviewer.Configuration; -import the.bytecode.club.bytecodeviewer.compilers.Compiler; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; -import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread; -import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings; import javax.swing.*; import java.awt.*; -import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.EDITABLE; - /*************************************************************************** * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * @@ -46,7 +39,6 @@ public class ResourceViewProcessing extends PaneUpdaterThread { private final ResourceViewPanel resourceViewPanel; private final byte[] b; - private final boolean isPanelEditable; private final JButton button; public boolean waitingFor; @@ -73,7 +65,7 @@ public class ResourceViewProcessing extends PaneUpdaterThread if (resourceViewPanel.decompiler == Decompiler.HEXCODE_VIEWER) { final ClassWriter cw = new ClassWriter(0); - viewer.cn.accept(cw); + viewer.viewerClassNode.accept(cw); SwingUtilities.invokeLater(() -> { @@ -88,34 +80,12 @@ public class ResourceViewProcessing extends PaneUpdaterThread final Decompiler decompiler = resourceViewPanel.decompiler; //perform decompiling inside of this thread - final String decompiledSource = decompiler.getDecompiler().decompileClassNode(viewer.cn, b); + final String decompiledSource = decompiler.getDecompiler().decompileClassNode(viewer.viewerClassNode, b); //set the swing components on the swing thread SwingUtilities.invokeLater(() -> { - updateUpdaterTextArea = new SearchableRSyntaxTextArea(); - - Configuration.rstaTheme.apply(updateUpdaterTextArea); - resourceViewPanel.panel.add(updateUpdaterTextArea.getScrollPane()); - resourceViewPanel.panel.add(updateUpdaterTextArea.getTitleHeader(), BorderLayout.NORTH); - - resourceViewPanel.textArea = updateUpdaterTextArea; - resourceViewPanel.textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); - resourceViewPanel.textArea.setCodeFoldingEnabled(true); - resourceViewPanel.textArea.setAntiAliasingEnabled(true); - resourceViewPanel.textArea.setText(decompiledSource); - resourceViewPanel.textArea.setCaretPosition(0); - resourceViewPanel.textArea.setEditable(isPanelEditable); - - if(isPanelEditable && decompiler == Decompiler.SMALI_DISASSEMBLER) - resourceViewPanel.compileMode = Compiler.SMALI_ASSEMBLER; - else if(isPanelEditable && decompiler == Decompiler.KRAKATAU_DISASSEMBLER) - resourceViewPanel.compileMode = Compiler.KRAKATAU_ASSEMBLER; - - String editable = isPanelEditable ? " - " + EDITABLE : ""; - resourceViewPanel.textArea.getTitleHeader().setText(decompiler.getDecompilerName() + editable); - resourceViewPanel.textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); - + buildTextArea(decompiler, decompiledSource); waitingFor = false; }); diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java index ba8d335f..75ab6f8c 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ClassViewer.java @@ -72,7 +72,7 @@ public class ClassViewer extends ResourceViewer this.container = container; this.name = name; - this.cn = cn; + this.viewerClassNode = cn; this.setName(name); this.setLayout(new BorderLayout()); @@ -91,7 +91,7 @@ public class ClassViewer extends ResourceViewer @Override public void refresh(final JButton button) { - this.cn = container.getClassNode(cn.name); //update the classnode + this.viewerClassNode = container.getClassNode(name); //update the classnode setPanes(); refreshTitle(); @@ -113,7 +113,7 @@ public class ClassViewer extends ResourceViewer System.err.println("TODO: Update it to use the FileContainerImporter"); } - classBytes = ASMUtil.nodeToBytes(cn); + classBytes = ASMUtil.nodeToBytes(viewerClassNode); } resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable()); diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ResourceViewer.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ResourceViewer.java index 8bab3513..5249f483 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ResourceViewer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/resourceviewer/viewer/ResourceViewer.java @@ -34,7 +34,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils; public abstract class ResourceViewer extends JPanel { - public ClassNode cn; + public ClassNode viewerClassNode; public String name; public String workingName; public ResourceContainer container; diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java b/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java index 7fa00885..1b29263f 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/gui/util/PaneUpdaterThread.java @@ -11,8 +11,11 @@ import javax.swing.event.CaretListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; import org.fife.ui.rtextarea.RTextScrollPane; import the.bytecode.club.bytecodeviewer.BytecodeViewer; +import the.bytecode.club.bytecodeviewer.Configuration; +import the.bytecode.club.bytecodeviewer.compilers.Compiler; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.gui.components.MethodsRenderer; import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; @@ -21,6 +24,7 @@ import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; import the.bytecode.club.bytecodeviewer.util.MethodParser; import static the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane.BLANK_COLOR; +import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.EDITABLE; /*************************************************************************** * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * @@ -54,6 +58,7 @@ public abstract class PaneUpdaterThread implements Runnable public final ResourceViewPanel resourceViewPanel; public SearchableRSyntaxTextArea updateUpdaterTextArea; public JComboBox methodsList; + public boolean isPanelEditable; private Thread thread; public PaneUpdaterThread(ClassViewer viewer, ResourceViewPanel resourceViewPanel) @@ -77,7 +82,17 @@ public abstract class PaneUpdaterThread implements Runnable return; processDisplay(); - + + //nullcheck broken pane + if(updateUpdaterTextArea == null || updateUpdaterTextArea.getScrollPane() == null + || updateUpdaterTextArea.getScrollPane().getViewport() == null) + { + //build an error message + SwingUtilities.invokeLater(() -> + buildTextArea(resourceViewPanel.decompiler, "Critical BCV Error")); + return; + } + //this still freezes the swing UI synchronizePane(); @@ -284,4 +299,30 @@ public abstract class PaneUpdaterThread implements Runnable } } } + + public void buildTextArea(Decompiler decompiler, String decompiledSource) + { + updateUpdaterTextArea = new SearchableRSyntaxTextArea(); + + Configuration.rstaTheme.apply(updateUpdaterTextArea); + resourceViewPanel.panel.add(updateUpdaterTextArea.getScrollPane()); + resourceViewPanel.panel.add(updateUpdaterTextArea.getTitleHeader(), BorderLayout.NORTH); + + resourceViewPanel.textArea = updateUpdaterTextArea; + resourceViewPanel.textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA); + resourceViewPanel.textArea.setCodeFoldingEnabled(true); + resourceViewPanel.textArea.setAntiAliasingEnabled(true); + resourceViewPanel.textArea.setText(decompiledSource); + resourceViewPanel.textArea.setCaretPosition(0); + resourceViewPanel.textArea.setEditable(isPanelEditable); + + if(isPanelEditable && decompiler == Decompiler.SMALI_DISASSEMBLER) + resourceViewPanel.compileMode = Compiler.SMALI_ASSEMBLER; + else if(isPanelEditable && decompiler == Decompiler.KRAKATAU_DISASSEMBLER) + resourceViewPanel.compileMode = Compiler.KRAKATAU_ASSEMBLER; + + String editable = isPanelEditable ? " - " + EDITABLE : ""; + resourceViewPanel.textArea.getTitleHeader().setText(decompiler.getDecompilerName() + editable); + resourceViewPanel.textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, (int) BytecodeViewer.viewer.fontSpinner.getValue())); + } } \ No newline at end of file diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java index e787f71d..bc699c1f 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/ResourceContainer.java @@ -3,6 +3,7 @@ package the.bytecode.club.bytecodeviewer.resources; import java.io.File; import java.util.LinkedHashMap; +import org.apache.commons.io.FilenameUtils; import org.objectweb.asm.tree.ClassNode; import the.bytecode.club.bytecodeviewer.api.ASMUtil; import the.bytecode.club.bytecodeviewer.util.LazyNameUtil; @@ -58,6 +59,10 @@ public class ResourceContainer */ public ClassNode getClassNode(String resourceName) { + //fallback incase the resource contains the file extension + if(resourceClassBytes.containsKey(resourceName)) + return resourceClasses.get(FilenameUtils.removeExtension(resourceName)); + return resourceClasses.get(resourceName); } diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/Import.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/Import.java index 0c06d0c8..1d5ff0f4 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/Import.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/Import.java @@ -30,7 +30,8 @@ public enum Import { DIRECTORY(new DirectoryResourceImporter()), FILE(new FileResourceImporter()), - //TODO ear needs to work the same as XAPK + //TODO ear needs to import the same as XAPK + //TODO war needs to add the /libs correctly similar to XAPK ZIP(new ZipResourceImporter(), "zip", "jar", "war", "ear"), CLASS(new ClassResourceImporter(), "class"), XAPK(new XAPKResourceImporter(), "xapk"), diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/ImportResource.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/ImportResource.java index 8f0b6ac2..8746aa5d 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/ImportResource.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/ImportResource.java @@ -41,6 +41,7 @@ public class ImportResource implements Runnable for (final File file : files) { final String fn = file.getName(); + System.out.println("Opening..." + fn); //check if file exists if (!file.exists()) diff --git a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/DirectoryResourceImporter.java b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/DirectoryResourceImporter.java index 6479d720..85b7e6ff 100644 --- a/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/DirectoryResourceImporter.java +++ b/src/main/java/the/bytecode/club/bytecodeviewer/resources/importing/impl/DirectoryResourceImporter.java @@ -60,12 +60,7 @@ public class DirectoryResourceImporter implements Importer .replaceAll("\\\\", "\\/"); final String fileName = child.getName(); - //attempt to import archives automatically - if(ImportResource.importKnownFile(file)) - { - //let import resource handle it - } - else if (fileName.endsWith(".class")) + if (fileName.endsWith(".class")) { byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath())); if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe")) @@ -74,6 +69,11 @@ public class DirectoryResourceImporter implements Importer allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn); } } + //attempt to import archives automatically + else if(ImportResource.importKnownFile(file)) + { + //let import resource handle it + } else //pack files into a single container { allDirectoryFiles.put(trimmedPath, Files.readAllBytes(Paths.get(child.getAbsolutePath())));