Tabbed Console

A better solution to the plugin console for when you have multiple resources inside of BCV
This commit is contained in:
Konloch 2021-07-14 21:59:18 -07:00
parent 3e82f29b59
commit ced48c76fd
8 changed files with 174 additions and 25 deletions

View file

@ -86,7 +86,6 @@ import static the.bytecode.club.bytecodeviewer.util.MiscUtils.guessLanguage;
* + Fix hook inject for EZ-Injection
*
* TODO FEATURES:
* + Console Plugin needs tabbed consoles instead of creating a new window for each console
* + CLI Headless needs to be supported
* + Add stackmapframes to bytecode decompiler
* + Add JEB decompiler optionally, requires them to add jeb library jar

View file

@ -1,6 +1,7 @@
package the.bytecode.club.bytecodeviewer.api;
import the.bytecode.club.bytecodeviewer.gui.components.SystemConsole;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
@ -28,10 +29,24 @@ import the.bytecode.club.bytecodeviewer.gui.components.SystemConsole;
public class PluginConsole extends SystemConsole
{
private boolean showWindow;
public PluginConsole(String pluginName)
{
super("Bytecode Viewer - Plugin Console - " + pluginName);
PluginManager.addConsole(this);
}
@Override
public void setVisible(boolean b)
{
//do nothing
if(!showWindow)
return;
super.setVisible(b);
}
private static final long serialVersionUID = -6556940545421437508L;
}

View file

@ -1,15 +1,12 @@
package the.bytecode.club.bytecodeviewer.gui.components;
import me.konloch.kontainer.io.DiskWriter;
import the.bytecode.club.bytecodeviewer.Configuration;
import the.bytecode.club.bytecodeviewer.Constants;
import the.bytecode.club.bytecodeviewer.resources.IconResources;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import static the.bytecode.club.bytecodeviewer.Constants.fs;
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
/***************************************************************************
@ -38,14 +35,17 @@ import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
*/
public class JFrameConsole extends JFrame
{
private final SearchableJTextArea textArea = new SearchableJTextArea();
private String containerName;
private int consoleID;
private final SearchableJTextArea textArea;
public JFrameConsole(String title)
{
this.setIconImages(IconResources.iconList);
setIconImages(IconResources.iconList);
setTitle(title);
setSize(new Dimension(542, 316));
textArea = new SearchableJTextArea();
getContentPane().add(textArea.getScrollPane(), BorderLayout.CENTER);
this.setLocationRelativeTo(null);
@ -71,33 +71,78 @@ public class JFrameConsole extends JFrame
*/
public void setText(String t)
{
textArea.setText(trim(t));
textArea.setText(trimConsoleText(t));
textArea.setCaretPosition(0);
}
/**
* Returns the SearchableJTextArea pane
*/
public SearchableJTextArea getTextArea()
{
return textArea;
}
public String trim(String s)
/**
* Returns the console ID
*/
public int getConsoleID()
{
return consoleID;
}
/**
* Returns the current container name
*/
public String getContainerName()
{
return containerName;
}
/**
* Set the console ID
*/
public void setConsoleID(int consoleID)
{
this.consoleID = consoleID;
}
/**
* Set the container name
*/
public void setContainerName(String containerName)
{
this.containerName = containerName;
}
/**
* Trims the console text to prevent killing the swing thread
*/
public String trimConsoleText(final String s)
{
int len = s.length();
int max = 500_000; //TODO this can be increased to 1,000,000 the lower number was chosen to be safe
//TODO this should also be a setting eventually
int max = 500_000;
if(len >= max)
{
//TODO if two consoles are ran at the same time and exceed the maximum this file will be overwritten
//save to disk
File tempFile = new File(tempDirectory+fs+"console.log");
DiskWriter.replaceFile(tempFile.getAbsolutePath(), s, false);
final File tempFile = new File(tempDirectory, "console_" + consoleID + ".log");
new Thread(()->
{
//save to disk
DiskWriter.replaceFile(tempFile.getAbsolutePath(), s, false);
}, "Console Log Saving").start();
//trim
int skipped = len - max;
s = s.substring(0, max);
s = ("Skipping " + skipped + " chars, allowing " + max + "\n\r")
+ "Full log saved to: " + tempFile.getAbsolutePath() + "\n\r"
+ s;
String trimmed = s.substring(0, max);
trimmed = ("WARNING: Skipping " + skipped + " chars, allowing " + max + "\n\r")
+ "Full log saved to: " + tempFile.getAbsolutePath() + "\n\r\n\r"
+ trimmed;
return trimmed;
}
return s;

View file

@ -0,0 +1,51 @@
package the.bytecode.club.bytecodeviewer.gui.components;
import the.bytecode.club.bytecodeviewer.resources.IconResources;
import javax.swing.*;
import java.awt.*;
/***************************************************************************
* Bytecode Viewer (BCV) - Java & Android Reverse Engineering Suite *
* Copyright (C) 2014 Kalen 'Konloch' Kinloch - http://bytecodeviewer.com *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
/**
* @author Konloch
* @since 7/14/2021
*/
public class JFrameConsoleTabbed extends JFrame
{
private final JTabbedPane tabbedPane;
public JFrameConsoleTabbed(String title)
{
setIconImages(IconResources.iconList);
setTitle(title);
setSize(new Dimension(542, 316));
tabbedPane = new JTabbedPane();
getContentPane().add(tabbedPane, BorderLayout.CENTER);
this.setLocationRelativeTo(null);
}
public void addConsole(Component console, String containerName)
{
tabbedPane.add(console, containerName);
}
}

View file

@ -18,8 +18,6 @@ package the.bytecode.club.bytecodeviewer.gui.components;
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
/**
* A simple console GUI.
*

View file

@ -301,7 +301,7 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
if (c.name.equals(cheapHax))
container = c;
}
String name = nameBuffer.toString();
//TODO add file header check
@ -311,13 +311,13 @@ public class ResourceListPane extends TranslatedVisibleComponent implements File
name.substring(0, name.length() - ".class".length()));
if (cn != null)
BytecodeViewer.viewer.workPane.addClassResource(container, nameBuffer.toString());
BytecodeViewer.viewer.workPane.addClassResource(container, name);
else
BytecodeViewer.viewer.workPane.addFileResource(container, nameBuffer.toString());
BytecodeViewer.viewer.workPane.addFileResource(container, name);
}
else
else if(container.resourceFiles.containsKey(name))
{
BytecodeViewer.viewer.workPane.addFileResource(container, nameBuffer.toString());
BytecodeViewer.viewer.workPane.addFileResource(container, name);
}
}

View file

@ -23,6 +23,10 @@ public class TabRemovalEvent implements ContainerListener
public void componentRemoved(ContainerEvent e)
{
final Component c = e.getChild();
if(!(c instanceof ResourceViewer))
return;
String workingName = ((ResourceViewer) c).resource.workingName;
BytecodeViewer.viewer.workPane.openedTabs.remove(workingName);
}

View file

@ -5,6 +5,8 @@ import java.util.*;
import javax.swing.filechooser.FileFilter;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.api.PluginConsole;
import the.bytecode.club.bytecodeviewer.gui.components.JFrameConsoleTabbed;
import the.bytecode.club.bytecodeviewer.plugin.strategies.*;
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
@ -35,11 +37,20 @@ import the.bytecode.club.bytecodeviewer.util.MiscUtils;
* @author Bibl
* @since 01/16/16, 14:36, Adaptable PluginLaunchStrategy system.
*/
public final class PluginManager {
public final class PluginManager
{
private static final Map<String, PluginLaunchStrategy> launchStrategies = new HashMap<>();
private static final PluginFileFilter filter = new PluginFileFilter();
private static List<Plugin> pluginInstances = new ArrayList<>();
//TODO this system needs to be redone, currently it will conflict if more than one plugin is ran at the same time
// the solution is to tie the plugin object into the plugin console,
// then move all of this into the plugin class as non-static objects
private static Plugin activePlugin;
private static JFrameConsoleTabbed activeTabbedConsole;
private static int consoleCount = 0;
static
{
@ -67,6 +78,15 @@ public final class PluginManager {
*/
public static void runPlugin(Plugin newPluginInstance)
{
//reset the console count
consoleCount = 0;
//reset the active tabbed console
activeTabbedConsole = null;
//reset the active plugin
activePlugin = newPluginInstance;
//clean the plugin list from dead threads
pluginInstances.removeIf(Plugin::isFinished);
@ -96,6 +116,23 @@ public final class PluginManager {
if (p != null)
runPlugin(p);
}
/**
* Add an active console from a plugin being ran
*/
public static void addConsole(PluginConsole console)
{
int id = consoleCount++;
if(activeTabbedConsole == null)
{
activeTabbedConsole = new JFrameConsoleTabbed(console.getTitle());
activeTabbedConsole.setVisible(true);
}
console.setConsoleID(id);
activeTabbedConsole.addConsole(console.getComponent(0), activePlugin.activeContainer.name);
}
public static void register(String name, PluginLaunchStrategy strat) {
launchStrategies.put(name, strat);