Improved BCV Error Handling

This commit is contained in:
Konloch 2021-07-14 04:09:46 -07:00
parent 35561fa5ca
commit 434d5cd58f
13 changed files with 73 additions and 57 deletions

View file

@ -313,7 +313,7 @@ public class BytecodeViewer
*/ */
public static ClassNode getCurrentlyOpenedClassNode() public static ClassNode getCurrentlyOpenedClassNode()
{ {
return getActiveResource().cn; return getActiveResource().viewerClassNode;
} }
/** /**

View file

@ -134,7 +134,6 @@ public class GlobalHotKeys
Configuration.lastHotKeyExecuted = System.currentTimeMillis(); Configuration.lastHotKeyExecuted = System.currentTimeMillis();
String recentFile = Settings.getRecentFile(); String recentFile = Settings.getRecentFile();
System.out.println("Opening..." + recentFile);
if(!BytecodeViewer.hasResources() && recentFile != null) if(!BytecodeViewer.hasResources() && recentFile != null)
{ {

View file

@ -166,9 +166,8 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
if (!container.resourceClasses.isEmpty()) 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("/"); final String[] spl = name.split("/");
if (spl.length < 2) if (spl.length < 2)
{ {
@ -304,9 +303,10 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
} }
String name = nameBuffer.toString(); String name = nameBuffer.toString();
if (name.endsWith(".class")) if (name.endsWith(".class"))
{ {
final ClassNode cn = Objects.requireNonNull(container).getClassNode( final ClassNode cn = container.getClassNode(
name.substring(0, name.length() - ".class".length())); name.substring(0, name.length() - ".class".length()));
if (cn != null) if (cn != null)

View file

@ -188,7 +188,7 @@ public class SearchBoxPane extends TranslatedVisibleComponent
final ResourceViewer cv = BytecodeViewer.getActiveResource(); final ResourceViewer cv = BytecodeViewer.getActiveResource();
if (cv != null) if (cv != null)
searchType.details.search(cv.container, cv.cn, srn, exact.isSelected()); searchType.details.search(cv.container, cv.viewerClassNode, srn, exact.isSelected());
} }
} }

View file

@ -1,7 +1,6 @@
package the.bytecode.club.bytecodeviewer.gui.resourceviewer; package the.bytecode.club.bytecodeviewer.gui.resourceviewer;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.compilers.Compiler; import the.bytecode.club.bytecodeviewer.compilers.Compiler;
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler; import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
@ -59,9 +58,9 @@ public class ResourceViewPanel
panel.removeAll(); panel.removeAll();
textArea = null; 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; return true;
SystemConsole errConsole = new SystemConsole("Java Compile Issues"); 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 + "Keep in mind most decompilers cannot produce compilable classes" +
nl + nl + TranslatedStrings.SUGGESTED_FIX_COMPILER_ERROR + nl + nl + TranslatedStrings.SUGGESTED_FIX_COMPILER_ERROR +
nl + nl); nl + nl);
@ -84,12 +83,12 @@ public class ResourceViewPanel
try try
{ {
String text = textArea.getText(); 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) if (compiledClass != null)
{ {
ClassNode newNode = JarUtils.getNode(compiledClass); ClassNode newNode = JarUtils.getNode(compiledClass);
viewer.container.updateNode(viewer.cn, newNode); viewer.container.updateNode(viewer.viewerClassNode, newNode);
errConsole.finished(); errConsole.finished();
return true; return true;
} }

View file

@ -1,22 +1,15 @@
package the.bytecode.club.bytecodeviewer.gui.resourceviewer; package the.bytecode.club.bytecodeviewer.gui.resourceviewer;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.objectweb.asm.ClassWriter; import org.objectweb.asm.ClassWriter;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; 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.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor; import the.bytecode.club.bytecodeviewer.gui.hexviewer.JHexEditor;
import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer; import the.bytecode.club.bytecodeviewer.gui.resourceviewer.viewer.ClassViewer;
import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread; import the.bytecode.club.bytecodeviewer.gui.util.PaneUpdaterThread;
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.EDITABLE;
/*************************************************************************** /***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite * * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com * * Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
@ -46,7 +39,6 @@ public class ResourceViewProcessing extends PaneUpdaterThread
{ {
private final ResourceViewPanel resourceViewPanel; private final ResourceViewPanel resourceViewPanel;
private final byte[] b; private final byte[] b;
private final boolean isPanelEditable;
private final JButton button; private final JButton button;
public boolean waitingFor; public boolean waitingFor;
@ -73,7 +65,7 @@ public class ResourceViewProcessing extends PaneUpdaterThread
if (resourceViewPanel.decompiler == Decompiler.HEXCODE_VIEWER) if (resourceViewPanel.decompiler == Decompiler.HEXCODE_VIEWER)
{ {
final ClassWriter cw = new ClassWriter(0); final ClassWriter cw = new ClassWriter(0);
viewer.cn.accept(cw); viewer.viewerClassNode.accept(cw);
SwingUtilities.invokeLater(() -> SwingUtilities.invokeLater(() ->
{ {
@ -88,34 +80,12 @@ public class ResourceViewProcessing extends PaneUpdaterThread
final Decompiler decompiler = resourceViewPanel.decompiler; final Decompiler decompiler = resourceViewPanel.decompiler;
//perform decompiling inside of this thread //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 //set the swing components on the swing thread
SwingUtilities.invokeLater(() -> SwingUtilities.invokeLater(() ->
{ {
updateUpdaterTextArea = new SearchableRSyntaxTextArea(); buildTextArea(decompiler, decompiledSource);
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()));
waitingFor = false; waitingFor = false;
}); });

View file

@ -72,7 +72,7 @@ public class ClassViewer extends ResourceViewer
this.container = container; this.container = container;
this.name = name; this.name = name;
this.cn = cn; this.viewerClassNode = cn;
this.setName(name); this.setName(name);
this.setLayout(new BorderLayout()); this.setLayout(new BorderLayout());
@ -91,7 +91,7 @@ public class ClassViewer extends ResourceViewer
@Override @Override
public void refresh(final JButton button) public void refresh(final JButton button)
{ {
this.cn = container.getClassNode(cn.name); //update the classnode this.viewerClassNode = container.getClassNode(name); //update the classnode
setPanes(); setPanes();
refreshTitle(); refreshTitle();
@ -113,7 +113,7 @@ public class ClassViewer extends ResourceViewer
System.err.println("TODO: Update it to use the FileContainerImporter"); System.err.println("TODO: Update it to use the FileContainerImporter");
} }
classBytes = ASMUtil.nodeToBytes(cn); classBytes = ASMUtil.nodeToBytes(viewerClassNode);
} }
resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable()); resourceViewPanel1.updatePane(this, classBytes, button, isPanel1Editable());

View file

@ -34,7 +34,7 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
public abstract class ResourceViewer extends JPanel public abstract class ResourceViewer extends JPanel
{ {
public ClassNode cn; public ClassNode viewerClassNode;
public String name; public String name;
public String workingName; public String workingName;
public ResourceContainer container; public ResourceContainer container;

View file

@ -11,8 +11,11 @@ import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rtextarea.RTextScrollPane; import org.fife.ui.rtextarea.RTextScrollPane;
import the.bytecode.club.bytecodeviewer.BytecodeViewer; 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.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.gui.components.MethodsRenderer; import the.bytecode.club.bytecodeviewer.gui.components.MethodsRenderer;
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea; 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 the.bytecode.club.bytecodeviewer.util.MethodParser;
import static the.bytecode.club.bytecodeviewer.gui.resourceviewer.TabbedPane.BLANK_COLOR; 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 * * Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
@ -54,6 +58,7 @@ public abstract class PaneUpdaterThread implements Runnable
public final ResourceViewPanel resourceViewPanel; public final ResourceViewPanel resourceViewPanel;
public SearchableRSyntaxTextArea updateUpdaterTextArea; public SearchableRSyntaxTextArea updateUpdaterTextArea;
public JComboBox<Integer> methodsList; public JComboBox<Integer> methodsList;
public boolean isPanelEditable;
private Thread thread; private Thread thread;
public PaneUpdaterThread(ClassViewer viewer, ResourceViewPanel resourceViewPanel) public PaneUpdaterThread(ClassViewer viewer, ResourceViewPanel resourceViewPanel)
@ -77,7 +82,17 @@ public abstract class PaneUpdaterThread implements Runnable
return; return;
processDisplay(); 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 //this still freezes the swing UI
synchronizePane(); 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()));
}
} }

View file

@ -3,6 +3,7 @@ package the.bytecode.club.bytecodeviewer.resources;
import java.io.File; import java.io.File;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import org.apache.commons.io.FilenameUtils;
import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.api.ASMUtil; import the.bytecode.club.bytecodeviewer.api.ASMUtil;
import the.bytecode.club.bytecodeviewer.util.LazyNameUtil; import the.bytecode.club.bytecodeviewer.util.LazyNameUtil;
@ -58,6 +59,10 @@ public class ResourceContainer
*/ */
public ClassNode getClassNode(String resourceName) 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); return resourceClasses.get(resourceName);
} }

View file

@ -30,7 +30,8 @@ public enum Import
{ {
DIRECTORY(new DirectoryResourceImporter()), DIRECTORY(new DirectoryResourceImporter()),
FILE(new FileResourceImporter()), 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"), ZIP(new ZipResourceImporter(), "zip", "jar", "war", "ear"),
CLASS(new ClassResourceImporter(), "class"), CLASS(new ClassResourceImporter(), "class"),
XAPK(new XAPKResourceImporter(), "xapk"), XAPK(new XAPKResourceImporter(), "xapk"),

View file

@ -41,6 +41,7 @@ public class ImportResource implements Runnable
for (final File file : files) for (final File file : files)
{ {
final String fn = file.getName(); final String fn = file.getName();
System.out.println("Opening..." + fn);
//check if file exists //check if file exists
if (!file.exists()) if (!file.exists())

View file

@ -60,12 +60,7 @@ public class DirectoryResourceImporter implements Importer
.replaceAll("\\\\", "\\/"); .replaceAll("\\\\", "\\/");
final String fileName = child.getName(); final String fileName = child.getName();
//attempt to import archives automatically if (fileName.endsWith(".class"))
if(ImportResource.importKnownFile(file))
{
//let import resource handle it
}
else if (fileName.endsWith(".class"))
{ {
byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath())); byte[] bytes = Files.readAllBytes(Paths.get(child.getAbsolutePath()));
if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe")) if (MiscUtils.getFileHeaderMagicNumber(bytes).equalsIgnoreCase("cafebabe"))
@ -74,6 +69,11 @@ public class DirectoryResourceImporter implements Importer
allDirectoryClasses.put(FilenameUtils.removeExtension(trimmedPath), cn); 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 else //pack files into a single container
{ {
allDirectoryFiles.put(trimmedPath, Files.readAllBytes(Paths.get(child.getAbsolutePath()))); allDirectoryFiles.put(trimmedPath, Files.readAllBytes(Paths.get(child.getAbsolutePath())));