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()
{
return getActiveResource().cn;
return getActiveResource().viewerClassNode;
}
/**

View file

@ -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)
{

View file

@ -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)

View file

@ -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());
}
}

View file

@ -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;
}

View file

@ -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;
});

View file

@ -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());

View file

@ -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;

View file

@ -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<Integer> methodsList;
public boolean isPanelEditable;
private Thread thread;
public PaneUpdaterThread(ClassViewer viewer, ResourceViewPanel resourceViewPanel)
@ -78,6 +83,16 @@ public abstract class PaneUpdaterThread implements Runnable
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()));
}
}

View file

@ -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);
}

View file

@ -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"),

View file

@ -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())

View file

@ -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())));