Built-in Script Editor
Still a work in progress
This commit is contained in:
parent
d052d0e6d3
commit
f3d5f25743
21 changed files with 498 additions and 111 deletions
|
@ -84,12 +84,14 @@ import static the.bytecode.club.bytecodeviewer.util.MiscUtils.guessLanguage;
|
||||||
* + Krakatau Assembly compile - Needs to be fixed
|
* + Krakatau Assembly compile - Needs to be fixed
|
||||||
*
|
*
|
||||||
* TODO IN-PROGRESS:
|
* TODO IN-PROGRESS:
|
||||||
|
* + While loading an external plugin it should check if its java or JS, if so it should ask if you'd like to run or edit the plugin using the PluginWriter
|
||||||
* + Resource Importer needs to be rewriten to handle resources better
|
* + Resource Importer needs to be rewriten to handle resources better
|
||||||
* + Finish dragging code
|
* + Finish dragging code
|
||||||
* + Finish right-click tab menu detection
|
* + Finish right-click tab menu detection
|
||||||
* + Fix hook inject for EZ-Injection
|
* + Fix hook inject for EZ-Injection
|
||||||
*
|
*
|
||||||
* TODO FEATURES:
|
* TODO FEATURES:
|
||||||
|
* + CLI Headless needs to be supported
|
||||||
* + Add stackmapframes to bytecode decompiler
|
* + Add stackmapframes to bytecode decompiler
|
||||||
* + Add JEB decompiler optionally, requires them to add jeb library jar
|
* + Add JEB decompiler optionally, requires them to add jeb library jar
|
||||||
* + Add https://github.com/ptnkjke/Java-Bytecode-Editor visualize as a plugin
|
* + Add https://github.com/ptnkjke/Java-Bytecode-Editor visualize as a plugin
|
||||||
|
@ -164,7 +166,8 @@ public class BytecodeViewer
|
||||||
*
|
*
|
||||||
* @param args files you want to open or CLI
|
* @param args files you want to open or CLI
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
BytecodeViewer.args = args;
|
BytecodeViewer.args = args;
|
||||||
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + VERSION + ", " + "Fat-Jar: " + FAT_JAR);
|
System.out.println("https://the.bytecode.club - Created by @Konloch - Bytecode Viewer " + VERSION + ", " + "Fat-Jar: " + FAT_JAR);
|
||||||
System.setSecurityManager(sm);
|
System.setSecurityManager(sm);
|
||||||
|
@ -179,13 +182,22 @@ public class BytecodeViewer
|
||||||
showMessage("WARNING: This is a preview/dev copy, you WON'T be alerted when " + VERSION + " is "
|
showMessage("WARNING: This is a preview/dev copy, you WON'T be alerted when " + VERSION + " is "
|
||||||
+ "actually out if you use this." + nl +
|
+ "actually out if you use this." + nl +
|
||||||
"Make sure to watch the repo: https://github.com/Konloch/bytecode-viewer for " + VERSION + "'s release");
|
"Make sure to watch the repo: https://github.com/Konloch/bytecode-viewer for " + VERSION + "'s release");
|
||||||
|
|
||||||
|
//set swing specific system properties
|
||||||
|
System.setProperty("swing.aatext", "true");
|
||||||
|
|
||||||
|
//setup swing components
|
||||||
viewer = new MainViewerGUI();
|
viewer = new MainViewerGUI();
|
||||||
SwingUtilities.updateComponentTreeUI(viewer);
|
SwingUtilities.updateComponentTreeUI(viewer);
|
||||||
|
|
||||||
|
//load settings and set swing components state
|
||||||
SettingsSerializer.loadSettings();
|
SettingsSerializer.loadSettings();
|
||||||
|
|
||||||
|
//set translation language
|
||||||
if(!Settings.hasSetLanguageAsSystemLanguage)
|
if(!Settings.hasSetLanguageAsSystemLanguage)
|
||||||
MiscUtils.setLanguage(guessLanguage());
|
MiscUtils.setLanguage(guessLanguage());
|
||||||
|
|
||||||
|
//handle CLI
|
||||||
int CLI = CommandLineInput.parseCommandLine(args);
|
int CLI = CommandLineInput.parseCommandLine(args);
|
||||||
|
|
||||||
if (CLI == CommandLineInput.STOP)
|
if (CLI == CommandLineInput.STOP)
|
||||||
|
@ -634,7 +646,7 @@ public class BytecodeViewer
|
||||||
|
|
||||||
if ((e.getKeyCode() == KeyEvent.VK_O) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
if ((e.getKeyCode() == KeyEvent.VK_O) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
|
||||||
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
Configuration.lastHotKeyExecuted = System.currentTimeMillis();
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select File or Folder to open in BCV",
|
"Select File or Folder to open in BCV",
|
||||||
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
||||||
Constants.SUPPORTED_FILE_EXTENSIONS);
|
Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||||
|
@ -678,7 +690,7 @@ public class BytecodeViewer
|
||||||
if (viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Zip Export",
|
"Select Zip Export",
|
||||||
"Zip Archives",
|
"Zip Archives",
|
||||||
"zip");
|
"zip");
|
||||||
|
@ -688,20 +700,12 @@ public class BytecodeViewer
|
||||||
{
|
{
|
||||||
Configuration.lastDirectory = fc.getSelectedFile().getAbsolutePath();
|
Configuration.lastDirectory = fc.getSelectedFile().getAbsolutePath();
|
||||||
File file = fc.getSelectedFile();
|
File file = fc.getSelectedFile();
|
||||||
|
|
||||||
if (!file.getAbsolutePath().endsWith(".zip"))
|
if (!file.getAbsolutePath().endsWith(".zip"))
|
||||||
file = new File(file.getAbsolutePath() + ".zip");
|
file = new File(file.getAbsolutePath() + ".zip");
|
||||||
|
|
||||||
if (file.exists()) {
|
if (!DialogueUtils.canOverwriteFile(file))
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
return;
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final File file2 = file;
|
final File file2 = file;
|
||||||
|
|
||||||
|
|
|
@ -44,4 +44,13 @@ public class Configuration
|
||||||
|
|
||||||
public static LAFTheme lafTheme = LAFTheme.SYSTEM; //lightmode by default since it uses the system theme
|
public static LAFTheme lafTheme = LAFTheme.SYSTEM; //lightmode by default since it uses the system theme
|
||||||
public static RSTATheme rstaTheme = lafTheme.getRSTATheme();
|
public static RSTATheme rstaTheme = lafTheme.getRSTATheme();
|
||||||
|
|
||||||
|
public static File getLastDirectory()
|
||||||
|
{
|
||||||
|
File lastDir = new File(lastDirectory);
|
||||||
|
if(lastDir.exists())
|
||||||
|
return lastDir;
|
||||||
|
|
||||||
|
return new File(".");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,12 +3,15 @@ package the.bytecode.club.bytecodeviewer;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.swing.ImageIcon;
|
import javax.swing.ImageIcon;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.imgscalr.Scalr;
|
import org.imgscalr.Scalr;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.libsDirectory;
|
import static the.bytecode.club.bytecodeviewer.Constants.libsDirectory;
|
||||||
|
@ -102,6 +105,11 @@ public class Resources {
|
||||||
size += 2;
|
size += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String loadResourceAsString(String resourcePath) throws IOException
|
||||||
|
{
|
||||||
|
return IOUtils.toString(Resources.class.getResourceAsStream(resourcePath), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
public static BufferedImage resize(BufferedImage image, int width, int height) {
|
public static BufferedImage resize(BufferedImage image, int width, int height) {
|
||||||
return Scalr.resize(image, Scalr.Method.ULTRA_QUALITY, width, height);
|
return Scalr.resize(image, Scalr.Method.ULTRA_QUALITY, width, height);
|
||||||
|
|
|
@ -14,9 +14,12 @@ import the.bytecode.club.bytecodeviewer.compilers.InternalCompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.InternalDecompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.EZInjection;
|
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.EZInjection;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
import static the.bytecode.club.bytecodeviewer.Constants.*;
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
@ -220,6 +223,28 @@ public class BytecodeViewer {
|
||||||
the.bytecode.club.bytecodeviewer.BytecodeViewer.showMessage(message);
|
the.bytecode.club.bytecodeviewer.BytecodeViewer.showMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks if the user would like to overwrite the file
|
||||||
|
*/
|
||||||
|
public static boolean canOverwriteFile(File file) {
|
||||||
|
return DialogueUtils.canOverwriteFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void hideFrame(JFrame frame, long milliseconds)
|
||||||
|
{
|
||||||
|
new Thread(()->{
|
||||||
|
long started = System.currentTimeMillis();
|
||||||
|
while(System.currentTimeMillis()-started <= milliseconds)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
} catch (InterruptedException e) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.setVisible(false);
|
||||||
|
}, "Timed Swing Hide").start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the wrapped Krakatau Decompiler instance.
|
* Returns the wrapped Krakatau Decompiler instance.
|
||||||
*
|
*
|
||||||
|
|
|
@ -24,6 +24,7 @@ import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameClasses;
|
||||||
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameFields;
|
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameFields;
|
||||||
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameMethods;
|
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameMethods;
|
||||||
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
|
||||||
|
import the.bytecode.club.bytecodeviewer.plugin.PluginTemplate;
|
||||||
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.*;
|
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.*;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.exporting.Export;
|
import the.bytecode.club.bytecodeviewer.resources.exporting.Export;
|
||||||
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBoxMenuItem;
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJCheckBoxMenuItem;
|
||||||
|
@ -104,6 +105,8 @@ public class MainViewerGUI extends JFrame
|
||||||
public final JMenu pluginsMainMenu = new TranslatedJMenu("Plugins", Translation.PLUGINS);
|
public final JMenu pluginsMainMenu = new TranslatedJMenu("Plugins", Translation.PLUGINS);
|
||||||
public final JMenuItem openExternalPlugin = new TranslatedJMenuItem("Open Plugin...", Translation.OPEN_PLUGIN);
|
public final JMenuItem openExternalPlugin = new TranslatedJMenuItem("Open Plugin...", Translation.OPEN_PLUGIN);
|
||||||
public final JMenu recentPluginsSecondaryMenu = new TranslatedJMenu("Recent Plugins", Translation.RECENT_PLUGINS);
|
public final JMenu recentPluginsSecondaryMenu = new TranslatedJMenu("Recent Plugins", Translation.RECENT_PLUGINS);
|
||||||
|
public final JMenuItem newJavaPlugin = new TranslatedJMenuItem("New Java Plugin...", Translation.NEW_JAVA_PLUGIN);
|
||||||
|
public final JMenuItem newJavascriptPlugin = new TranslatedJMenuItem("New Javascript Plugin...", Translation.NEW_JAVASCRIPT_PLUGIN);
|
||||||
public final JMenuItem codeSequenceDiagram = new TranslatedJMenuItem("Code Sequence Diagram", Translation.CODE_SEQUENCE_DIAGRAM);
|
public final JMenuItem codeSequenceDiagram = new TranslatedJMenuItem("Code Sequence Diagram", Translation.CODE_SEQUENCE_DIAGRAM);
|
||||||
public final JMenuItem maliciousCodeScanner = new TranslatedJMenuItem("Malicious Code Scanner", Translation.MALICIOUS_CODE_SCANNER);
|
public final JMenuItem maliciousCodeScanner = new TranslatedJMenuItem("Malicious Code Scanner", Translation.MALICIOUS_CODE_SCANNER);
|
||||||
public final JMenuItem showAllStrings = new TranslatedJMenuItem("Show All Strings", Translation.SHOW_ALL_STRINGS);
|
public final JMenuItem showAllStrings = new TranslatedJMenuItem("Show All Strings", Translation.SHOW_ALL_STRINGS);
|
||||||
|
@ -591,6 +594,9 @@ public class MainViewerGUI extends JFrame
|
||||||
pluginsMainMenu.add(new JSeparator());
|
pluginsMainMenu.add(new JSeparator());
|
||||||
pluginsMainMenu.add(recentPluginsSecondaryMenu);
|
pluginsMainMenu.add(recentPluginsSecondaryMenu);
|
||||||
pluginsMainMenu.add(new JSeparator());
|
pluginsMainMenu.add(new JSeparator());
|
||||||
|
pluginsMainMenu.add(newJavaPlugin);
|
||||||
|
pluginsMainMenu.add(newJavascriptPlugin);
|
||||||
|
pluginsMainMenu.add(new JSeparator());
|
||||||
pluginsMainMenu.add(codeSequenceDiagram);
|
pluginsMainMenu.add(codeSequenceDiagram);
|
||||||
pluginsMainMenu.add(maliciousCodeScanner);
|
pluginsMainMenu.add(maliciousCodeScanner);
|
||||||
pluginsMainMenu.add(showMainMethods);
|
pluginsMainMenu.add(showMainMethods);
|
||||||
|
@ -604,6 +610,8 @@ public class MainViewerGUI extends JFrame
|
||||||
pluginsMainMenu.add(zStringArrayDecrypter);
|
pluginsMainMenu.add(zStringArrayDecrypter);
|
||||||
|
|
||||||
openExternalPlugin.addActionListener(arg0 -> openExternalPlugin());
|
openExternalPlugin.addActionListener(arg0 -> openExternalPlugin());
|
||||||
|
newJavaPlugin.addActionListener(arg0 -> PluginTemplate.JAVA.openEditorExceptionHandled());
|
||||||
|
newJavascriptPlugin.addActionListener(arg0 -> PluginTemplate.JAVASCRIPT.openEditorExceptionHandled());
|
||||||
codeSequenceDiagram.addActionListener(arg0 -> CodeSequenceDiagram.open());
|
codeSequenceDiagram.addActionListener(arg0 -> CodeSequenceDiagram.open());
|
||||||
maliciousCodeScanner.addActionListener(e -> MaliciousCodeScannerOptions.open());
|
maliciousCodeScanner.addActionListener(e -> MaliciousCodeScannerOptions.open());
|
||||||
showMainMethods.addActionListener(e -> PluginManager.runPlugin(new ShowMainMethods()));
|
showMainMethods.addActionListener(e -> PluginManager.runPlugin(new ShowMainMethods()));
|
||||||
|
@ -839,7 +847,7 @@ public class MainViewerGUI extends JFrame
|
||||||
|
|
||||||
public void selectFile()
|
public void selectFile()
|
||||||
{
|
{
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select File or Folder to open in BCV",
|
"Select File or Folder to open in BCV",
|
||||||
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
"APKs, DEX, Class Files or Zip/Jar/War Archives",
|
||||||
Constants.SUPPORTED_FILE_EXTENSIONS);
|
Constants.SUPPORTED_FILE_EXTENSIONS);
|
||||||
|
@ -859,7 +867,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectPythonC() {
|
public void selectPythonC() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Python 2.7 Executable",
|
"Select Python 2.7 Executable",
|
||||||
"Python (Or PyPy for speed) 2.7 Executable",
|
"Python (Or PyPy for speed) 2.7 Executable",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -876,7 +884,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectJavac() {
|
public void selectJavac() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Javac Executable",
|
"Select Javac Executable",
|
||||||
"Javac Executable (Requires JDK 'C:/programfiles/Java/JDK_xx/bin/javac.exe)",
|
"Javac Executable (Requires JDK 'C:/programfiles/Java/JDK_xx/bin/javac.exe)",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -893,7 +901,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectJava() {
|
public void selectJava() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Java Executable",
|
"Select Java Executable",
|
||||||
"Java Executable (Inside Of JRE/JDK 'C:/programfiles/Java/JDK_xx/bin/java.exe')",
|
"Java Executable (Inside Of JRE/JDK 'C:/programfiles/Java/JDK_xx/bin/java.exe')",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -910,7 +918,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectPythonC3() {
|
public void selectPythonC3() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Python 3.x Executable",
|
"Select Python 3.x Executable",
|
||||||
"Python (Or PyPy for speed) 3.x Executable",
|
"Python (Or PyPy for speed) 3.x Executable",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -927,7 +935,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectOpenalLibraryFolder() {
|
public void selectOpenalLibraryFolder() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Library Folder",
|
"Select Library Folder",
|
||||||
"Optional Library Folder",
|
"Optional Library Folder",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -948,7 +956,7 @@ public class MainViewerGUI extends JFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectJRERTLibrary() {
|
public void selectJRERTLibrary() {
|
||||||
final JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
final JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select JRE RT Jar",
|
"Select JRE RT Jar",
|
||||||
"JRE RT Library",
|
"JRE RT Library",
|
||||||
"everything");
|
"everything");
|
||||||
|
@ -966,7 +974,7 @@ public class MainViewerGUI extends JFrame
|
||||||
|
|
||||||
public void openExternalPlugin()
|
public void openExternalPlugin()
|
||||||
{
|
{
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select External Plugin",
|
"Select External Plugin",
|
||||||
"External Plugin",
|
"External Plugin",
|
||||||
"everything");
|
"everything");
|
||||||
|
|
|
@ -50,6 +50,7 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
||||||
private final JLabel titleHeader = new JLabel("");
|
private final JLabel titleHeader = new JLabel("");
|
||||||
private final Color scrollBackground = new Color(0x3c3f41);
|
private final Color scrollBackground = new Color(0x3c3f41);
|
||||||
private final Color scrollForeground = new Color(0x575859);
|
private final Color scrollForeground = new Color(0x575859);
|
||||||
|
private Runnable onCtrlS;
|
||||||
|
|
||||||
public SearchableRSyntaxTextArea()
|
public SearchableRSyntaxTextArea()
|
||||||
{
|
{
|
||||||
|
@ -91,6 +92,12 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
||||||
if ((keyEvent.getKeyCode() == KeyEvent.VK_F) && ((keyEvent.getModifiers() & KeyEvent.CTRL_MASK) != 0))
|
if ((keyEvent.getKeyCode() == KeyEvent.VK_F) && ((keyEvent.getModifiers() & KeyEvent.CTRL_MASK) != 0))
|
||||||
searchInput.requestFocus();
|
searchInput.requestFocus();
|
||||||
|
|
||||||
|
if (onCtrlS != null && (keyEvent.getKeyCode() == KeyEvent.VK_S) && ((keyEvent.getModifiers() & KeyEvent.CTRL_MASK) != 0))
|
||||||
|
{
|
||||||
|
onCtrlS.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BytecodeViewer.checkHotKey(keyEvent);
|
BytecodeViewer.checkHotKey(keyEvent);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -116,6 +123,11 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOnCtrlS(Runnable onCtrlS)
|
||||||
|
{
|
||||||
|
this.onCtrlS = onCtrlS;
|
||||||
|
}
|
||||||
|
|
||||||
public RTextScrollPane getScrollPane()
|
public RTextScrollPane getScrollPane()
|
||||||
{
|
{
|
||||||
return scrollPane;
|
return scrollPane;
|
||||||
|
@ -140,4 +152,9 @@ public class SearchableRSyntaxTextArea extends RSyntaxTextArea
|
||||||
{
|
{
|
||||||
return titleHeader;
|
return titleHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Runnable getOnCtrlS()
|
||||||
|
{
|
||||||
|
return onCtrlS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,12 @@ public final class PluginManager {
|
||||||
public static Set<String> pluginExtensions() {
|
public static Set<String> pluginExtensions() {
|
||||||
return launchStrategies.keySet();
|
return launchStrategies.keySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Map<String, PluginLaunchStrategy> getLaunchStrategies()
|
||||||
|
{
|
||||||
|
return launchStrategies;
|
||||||
|
}
|
||||||
|
|
||||||
public static FileFilter fileFilter() {
|
public static FileFilter fileFilter() {
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
package the.bytecode.club.bytecodeviewer.plugin;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import the.bytecode.club.bytecodeviewer.Resources;
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Konloch
|
||||||
|
* @since 7/1/2021
|
||||||
|
*/
|
||||||
|
public enum PluginTemplate
|
||||||
|
{
|
||||||
|
JAVA("/templates/Template.java"),
|
||||||
|
JAVASCRIPT("/templates/Template.js"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final String resourcePath;
|
||||||
|
private final String extension;
|
||||||
|
private String contents;
|
||||||
|
|
||||||
|
PluginTemplate(String resourcePath)
|
||||||
|
{
|
||||||
|
this.resourcePath = resourcePath;
|
||||||
|
this.extension = FilenameUtils.getExtension(resourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContents() throws IOException
|
||||||
|
{
|
||||||
|
if(contents == null)
|
||||||
|
contents = Resources.loadResourceAsString(resourcePath);
|
||||||
|
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension()
|
||||||
|
{
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginWriter openEditorExceptionHandled()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return openEditor();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
new ExceptionUI(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginWriter openEditor() throws IOException
|
||||||
|
{
|
||||||
|
PluginWriter writer = new PluginWriter(this);
|
||||||
|
writer.setVisible(true);
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,176 @@
|
||||||
|
package the.bytecode.club.bytecodeviewer.plugin;
|
||||||
|
|
||||||
|
import me.konloch.kontainer.io.DiskWriter;
|
||||||
|
import org.apache.commons.compress.utils.FileNameUtils;
|
||||||
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
|
import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
|
import the.bytecode.club.bytecodeviewer.Resources;
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||||
|
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
|
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
||||||
|
import the.bytecode.club.bytecodeviewer.translation.Translation;
|
||||||
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJMenu;
|
||||||
|
import the.bytecode.club.bytecodeviewer.translation.components.TranslatedJMenuItem;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.SyntaxLanguage;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static the.bytecode.club.bytecodeviewer.Constants.fs;
|
||||||
|
import static the.bytecode.club.bytecodeviewer.Constants.tempDirectory;
|
||||||
|
import static the.bytecode.club.bytecodeviewer.Settings.addRecentPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Konloch
|
||||||
|
* @since 7/1/2021
|
||||||
|
*/
|
||||||
|
public class PluginWriter extends JFrame
|
||||||
|
{
|
||||||
|
private SearchableRSyntaxTextArea area;
|
||||||
|
private JMenuItem menuSaveAs;
|
||||||
|
private JMenuItem menuSave;
|
||||||
|
private String content;
|
||||||
|
private String pluginName;
|
||||||
|
private File savePath;
|
||||||
|
|
||||||
|
public PluginWriter(PluginTemplate template) throws IOException
|
||||||
|
{
|
||||||
|
this.content = template.getContents();
|
||||||
|
this.pluginName = "Template." + template.getExtension();
|
||||||
|
buildGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PluginWriter(String content, String pluginName)
|
||||||
|
{
|
||||||
|
this.content = content;
|
||||||
|
this.pluginName = pluginName;
|
||||||
|
buildGUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void buildGUI()
|
||||||
|
{
|
||||||
|
setTitle("Editing BCV Plugin: " + pluginName);
|
||||||
|
setIconImages(Resources.iconList);
|
||||||
|
setSize(new Dimension(542, 316));
|
||||||
|
|
||||||
|
area = (SearchableRSyntaxTextArea) Configuration.rstaTheme.apply(new SearchableRSyntaxTextArea());
|
||||||
|
area.setOnCtrlS(this::save);
|
||||||
|
area.setText(content);
|
||||||
|
area.setCaretPosition(0);
|
||||||
|
area.setSyntaxEditingStyle(SyntaxLanguage.detectLanguage(pluginName, content).getSyntaxConstant());
|
||||||
|
content = null;
|
||||||
|
|
||||||
|
JButton run = new JButton("Run");
|
||||||
|
|
||||||
|
JMenuBar menuBar = new JMenuBar();
|
||||||
|
JMenu menu = new TranslatedJMenu("File", Translation.FILE);
|
||||||
|
JMenuItem menuRun = new TranslatedJMenuItem("Run", Translation.RUN);
|
||||||
|
menuSaveAs = new TranslatedJMenuItem("Save As...", Translation.SAVE_AS);
|
||||||
|
menuSave = new TranslatedJMenuItem("Save...", Translation.SAVE);
|
||||||
|
menuSave.setVisible(false);
|
||||||
|
|
||||||
|
menuBar.add(menu);
|
||||||
|
menu.add(menuRun);
|
||||||
|
menu.add(menuSaveAs);
|
||||||
|
menu.add(menuSave);
|
||||||
|
|
||||||
|
setJMenuBar(menuBar);
|
||||||
|
add(area.getScrollPane());
|
||||||
|
add(run, BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
run.addActionListener((l)->runPlugin());
|
||||||
|
menuRun.addActionListener((l)->runPlugin());
|
||||||
|
menuSaveAs.addActionListener((l)-> save());
|
||||||
|
menuSave.addActionListener((l)-> save());
|
||||||
|
|
||||||
|
this.setLocationRelativeTo(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runPlugin()
|
||||||
|
{
|
||||||
|
File tempFile = new File(tempDirectory + fs + "temp" + MiscUtils.randomString(32) + fs + pluginName);
|
||||||
|
tempFile.getParentFile().mkdirs();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//write to temporary file location
|
||||||
|
DiskWriter.replaceFile(tempFile.getAbsolutePath(), area.getText(), false);
|
||||||
|
//run plugin from that location
|
||||||
|
PluginManager.runPlugin(tempFile);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
new ExceptionUI(e);
|
||||||
|
}
|
||||||
|
catch (Throwable t)
|
||||||
|
{
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
tempFile.getParentFile().delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPluginName(String name)
|
||||||
|
{
|
||||||
|
this.pluginName = name;
|
||||||
|
setTitle("Editing BCV Plugin: " + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save()
|
||||||
|
{
|
||||||
|
Thread exportThread = new Thread(() ->
|
||||||
|
{
|
||||||
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(savePath == null)
|
||||||
|
{
|
||||||
|
final String ext = FileNameUtils.getExtension(pluginName);
|
||||||
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
|
"Save Plugin",
|
||||||
|
"BCV Plugin",
|
||||||
|
ext);
|
||||||
|
|
||||||
|
int returnVal = fc.showSaveDialog(BytecodeViewer.viewer);
|
||||||
|
if (returnVal == JFileChooser.APPROVE_OPTION)
|
||||||
|
{
|
||||||
|
Configuration.lastDirectory = fc.getSelectedFile().getAbsolutePath();
|
||||||
|
File file = fc.getSelectedFile();
|
||||||
|
String path = file.getAbsolutePath();
|
||||||
|
|
||||||
|
//auto append extension
|
||||||
|
if (!path.endsWith("." + ext))
|
||||||
|
path = path + "." + ext;
|
||||||
|
|
||||||
|
if (!DialogueUtils.canOverwriteFile(path))
|
||||||
|
return;
|
||||||
|
|
||||||
|
//swap from save-as to having a defined path each save
|
||||||
|
setSourceFile(new File(path));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DiskWriter.replaceFile(savePath.getAbsolutePath(), area.getText(), false);
|
||||||
|
addRecentPlugin(savePath);
|
||||||
|
}, "Plugin Editor Save");
|
||||||
|
exportThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceFile(File file)
|
||||||
|
{
|
||||||
|
menuSaveAs.setVisible(false);
|
||||||
|
menuSave.setVisible(true);
|
||||||
|
savePath = file;
|
||||||
|
setPluginName(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
|
||||||
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
|
@ -39,7 +40,7 @@ public class ResourceDecompiling
|
||||||
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Zip Export",
|
"Select Zip Export",
|
||||||
"Zip Archives",
|
"Zip Archives",
|
||||||
"zip");
|
"zip");
|
||||||
|
@ -54,18 +55,8 @@ public class ResourceDecompiling
|
||||||
if (!file.getAbsolutePath().endsWith(".zip"))
|
if (!file.getAbsolutePath().endsWith(".zip"))
|
||||||
file = new File(file.getAbsolutePath() + ".zip");
|
file = new File(file.getAbsolutePath() + ".zip");
|
||||||
|
|
||||||
if (file.exists())
|
if (!DialogueUtils.canOverwriteFile(file))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final File javaSucks = file;
|
final File javaSucks = file;
|
||||||
final String path = MiscUtils.append(file, ".zip"); // cheap hax cause string is final
|
final String path = MiscUtils.append(file, ".zip"); // cheap hax cause string is final
|
||||||
|
@ -207,7 +198,7 @@ public class ResourceDecompiling
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Java Files",
|
"Select Java Files",
|
||||||
"Java Source Files",
|
"Java Source Files",
|
||||||
"java");
|
"java");
|
||||||
|
@ -221,18 +212,8 @@ public class ResourceDecompiling
|
||||||
BytecodeViewer.viewer.updateBusyStatus(true);
|
BytecodeViewer.viewer.updateBusyStatus(true);
|
||||||
final String path = MiscUtils.append(file, ".java"); // cheap hax because string is final
|
final String path = MiscUtils.append(file, ".java"); // cheap hax because string is final
|
||||||
|
|
||||||
if (new File(path).exists())
|
if (!DialogueUtils.canOverwriteFile(path))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JOptionPane pane = new JOptionPane(
|
JOptionPane pane = new JOptionPane(
|
||||||
"What decompiler will you use?");
|
"What decompiler will you use?");
|
||||||
|
|
|
@ -5,10 +5,7 @@ import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
||||||
import the.bytecode.club.bytecodeviewer.util.APKTool;
|
import the.bytecode.club.bytecodeviewer.util.*;
|
||||||
import the.bytecode.club.bytecodeviewer.util.FileContainer;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -73,7 +70,7 @@ public class APKExport implements Exporter
|
||||||
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select APK Export",
|
"Select APK Export",
|
||||||
"Android APK",
|
"Android APK",
|
||||||
"apk");
|
"apk");
|
||||||
|
@ -90,18 +87,8 @@ public class APKExport implements Exporter
|
||||||
output = output + ".apk";
|
output = output + ".apk";
|
||||||
|
|
||||||
final File file2 = new File(output);
|
final File file2 = new File(output);
|
||||||
if (file2.exists())
|
if (!DialogueUtils.canOverwriteFile(file2))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread saveThread = new Thread(() ->
|
Thread saveThread = new Thread(() ->
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@ import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
||||||
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
import the.bytecode.club.bytecodeviewer.util.Dex2Jar;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
import the.bytecode.club.bytecodeviewer.util.MiscUtils;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ public class DexExport implements Exporter
|
||||||
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select DEX Export",
|
"Select DEX Export",
|
||||||
"Android DEX Files",
|
"Android DEX Files",
|
||||||
"dex");
|
"dex");
|
||||||
|
@ -53,18 +54,8 @@ public class DexExport implements Exporter
|
||||||
output = output + ".dex";
|
output = output + ".dex";
|
||||||
|
|
||||||
File outputPath = new File(output);
|
File outputPath = new File(output);
|
||||||
if (outputPath.exists())
|
if (!DialogueUtils.canOverwriteFile(outputPath))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread saveAsJar = new Thread(() ->
|
Thread saveAsJar = new Thread(() ->
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@ import the.bytecode.club.bytecodeviewer.gui.components.ExportJar;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -30,7 +31,7 @@ public class RunnableJarExporter implements Exporter
|
||||||
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Jar Export",
|
"Select Jar Export",
|
||||||
"Jar Archives",
|
"Jar Archives",
|
||||||
"jar");
|
"jar");
|
||||||
|
@ -46,18 +47,8 @@ public class RunnableJarExporter implements Exporter
|
||||||
if (!path.endsWith(".jar"))
|
if (!path.endsWith(".jar"))
|
||||||
path = path + ".jar";
|
path = path + ".jar";
|
||||||
|
|
||||||
if (new File(path).exists())
|
if (!DialogueUtils.canOverwriteFile(path))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new ExportJar(path).setVisible(true);
|
new ExportJar(path).setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import the.bytecode.club.bytecodeviewer.Configuration;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
import the.bytecode.club.bytecodeviewer.gui.components.FileChooser;
|
||||||
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
import the.bytecode.club.bytecodeviewer.resources.exporting.Exporter;
|
||||||
|
import the.bytecode.club.bytecodeviewer.util.DialogueUtils;
|
||||||
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
import the.bytecode.club.bytecodeviewer.util.JarUtils;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
@ -30,7 +31,7 @@ public class ZipExport implements Exporter
|
||||||
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
if (BytecodeViewer.viewer.compileOnSave.isSelected() && !BytecodeViewer.compile(false))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Zip Export",
|
"Select Zip Export",
|
||||||
"Zip Archives",
|
"Zip Archives",
|
||||||
"zip");
|
"zip");
|
||||||
|
@ -45,18 +46,8 @@ public class ZipExport implements Exporter
|
||||||
if (!file.getAbsolutePath().endsWith(".zip"))
|
if (!file.getAbsolutePath().endsWith(".zip"))
|
||||||
file = new File(file.getAbsolutePath() + ".zip");
|
file = new File(file.getAbsolutePath() + ".zip");
|
||||||
|
|
||||||
if (file.exists())
|
if (!DialogueUtils.canOverwriteFile(file))
|
||||||
{
|
return;
|
||||||
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
|
||||||
"Are you sure you wish to overwrite this existing file?",
|
|
||||||
new String[]{"Yes", "No"});
|
|
||||||
|
|
||||||
if (dialogue.promptChoice() == 0) {
|
|
||||||
file.delete();
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final File file2 = file;
|
final File file2 = file;
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ public enum Language
|
||||||
printMissingLanguageKeys();
|
printMissingLanguageKeys();
|
||||||
|
|
||||||
HashMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
|
HashMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
|
||||||
IOUtils.toString(Resources.class.getResourceAsStream(resourcePath), StandardCharsets.UTF_8),
|
Resources.loadResourceAsString(resourcePath),
|
||||||
new TypeToken<HashMap<String, String>>(){}.getType());
|
new TypeToken<HashMap<String, String>>(){}.getType());
|
||||||
|
|
||||||
for(Translation translation : Translation.values())
|
for(Translation translation : Translation.values())
|
||||||
|
@ -100,7 +100,7 @@ public enum Language
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LinkedMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
|
LinkedMap<String, String> translationMap = BytecodeViewer.gson.fromJson(
|
||||||
IOUtils.toString(Resources.class.getResourceAsStream(resourcePath), StandardCharsets.UTF_8),
|
Resources.loadResourceAsString(resourcePath),
|
||||||
new TypeToken<LinkedMap<String, String>>(){}.getType());
|
new TypeToken<LinkedMap<String, String>>(){}.getType());
|
||||||
|
|
||||||
HashSet<String> existingKeys = new HashSet<>();
|
HashSet<String> existingKeys = new HashSet<>();
|
||||||
|
|
|
@ -14,6 +14,8 @@ public enum Translation
|
||||||
RELOAD_RESOURCES,
|
RELOAD_RESOURCES,
|
||||||
RUN,
|
RUN,
|
||||||
COMPILE,
|
COMPILE,
|
||||||
|
SAVE,
|
||||||
|
SAVE_AS,
|
||||||
SAVE_AS_RUNNABLE_JAR,
|
SAVE_AS_RUNNABLE_JAR,
|
||||||
SAVE_AS_ZIP,
|
SAVE_AS_ZIP,
|
||||||
SAVE_AS_DEX,
|
SAVE_AS_DEX,
|
||||||
|
@ -79,6 +81,8 @@ public enum Translation
|
||||||
PLUGINS,
|
PLUGINS,
|
||||||
OPEN_PLUGIN,
|
OPEN_PLUGIN,
|
||||||
RECENT_PLUGINS,
|
RECENT_PLUGINS,
|
||||||
|
NEW_JAVA_PLUGIN,
|
||||||
|
NEW_JAVASCRIPT_PLUGIN,
|
||||||
CODE_SEQUENCE_DIAGRAM,
|
CODE_SEQUENCE_DIAGRAM,
|
||||||
MALICIOUS_CODE_SCANNER,
|
MALICIOUS_CODE_SCANNER,
|
||||||
SHOW_MAIN_METHODS,
|
SHOW_MAIN_METHODS,
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
|
import the.bytecode.club.bytecodeviewer.gui.components.MultipleChoiceDialogue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Konloch
|
||||||
|
* @since 7/1/2021
|
||||||
|
*/
|
||||||
|
public class DialogueUtils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Asks if the user would like to overwrite the file
|
||||||
|
*/
|
||||||
|
public static boolean canOverwriteFile(String filePath)
|
||||||
|
{
|
||||||
|
return canOverwriteFile(new File(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks if the user would like to overwrite the file
|
||||||
|
*/
|
||||||
|
public static boolean canOverwriteFile(File file) {
|
||||||
|
if (file.exists())
|
||||||
|
{
|
||||||
|
MultipleChoiceDialogue dialogue = new MultipleChoiceDialogue("Bytecode Viewer - Overwrite File",
|
||||||
|
"Are you sure you wish to overwrite this existing file?",
|
||||||
|
new String[]{"Yes", "No"});
|
||||||
|
|
||||||
|
if (dialogue.promptChoice() == 0) {
|
||||||
|
file.delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package the.bytecode.club.bytecodeviewer.util;
|
package the.bytecode.club.bytecodeviewer.util;
|
||||||
|
|
||||||
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
|
||||||
|
import the.bytecode.club.bytecodeviewer.gui.components.SearchableRSyntaxTextArea;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
@ -12,7 +13,16 @@ import java.awt.event.KeyEvent;
|
||||||
public class KeyEventDispatch implements KeyEventDispatcher
|
public class KeyEventDispatch implements KeyEventDispatcher
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchKeyEvent(KeyEvent e) {
|
public boolean dispatchKeyEvent(KeyEvent e)
|
||||||
|
{
|
||||||
|
//hardcoded check for searchable syntax panes, this allows specific panels to ctrl + s save externally
|
||||||
|
if(e.getSource() instanceof SearchableRSyntaxTextArea)
|
||||||
|
{
|
||||||
|
SearchableRSyntaxTextArea rSyntaxTextArea = (SearchableRSyntaxTextArea) e.getSource();
|
||||||
|
if(rSyntaxTextArea.getOnCtrlS() != null)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
BytecodeViewer.checkHotKey(e);
|
BytecodeViewer.checkHotKey(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class VersionChecker implements Runnable
|
||||||
}
|
}
|
||||||
else if (result == 1)
|
else if (result == 1)
|
||||||
{
|
{
|
||||||
JFileChooser fc = new FileChooser(new File(Configuration.lastDirectory),
|
JFileChooser fc = new FileChooser(Configuration.getLastDirectory(),
|
||||||
"Select Save File",
|
"Select Save File",
|
||||||
"Zip Archives",
|
"Zip Archives",
|
||||||
"zip");
|
"zip");
|
||||||
|
|
41
src/main/resources/templates/Template.java
Normal file
41
src/main/resources/templates/Template.java
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
import the.bytecode.club.bytecodeviewer.api.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
public class Template extends Plugin
|
||||||
|
{
|
||||||
|
PluginConsole gui = new PluginConsole("Java Template");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(ArrayList<ClassNode> classNodeList)
|
||||||
|
{
|
||||||
|
gui.setVisible(true); //show the console
|
||||||
|
out("Class Nodes: " + classNodeList.size());
|
||||||
|
|
||||||
|
//iterate through each class node
|
||||||
|
for(ClassNode cn : classNodeList)
|
||||||
|
process(cn);
|
||||||
|
|
||||||
|
BytecodeViewer.hideFrame(gui, 10000); //hides the console after 10 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process each class node
|
||||||
|
*/
|
||||||
|
public void process(ClassNode cn)
|
||||||
|
{
|
||||||
|
out("Node: " + cn.name + ".class");
|
||||||
|
//TODO developer plugin code goes here
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print to console
|
||||||
|
*/
|
||||||
|
public void out(String text)
|
||||||
|
{
|
||||||
|
gui.appendText(text);
|
||||||
|
}
|
||||||
|
}
|
35
src/main/resources/templates/Template.js
Normal file
35
src/main/resources/templates/Template.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
var BCV = Java.type("the.bytecode.club.bytecodeviewer.api.BytecodeViewer");
|
||||||
|
var PluginConsole = Java.type("the.bytecode.club.bytecodeviewer.api.PluginConsole");
|
||||||
|
var gui = new PluginConsole("Javascript Template");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function
|
||||||
|
*/
|
||||||
|
function execute(classNodeList)
|
||||||
|
{
|
||||||
|
gui.setVisible(true); //show the console
|
||||||
|
out("Class Nodes: " + classNodeList.size());
|
||||||
|
|
||||||
|
//iterate through each class node
|
||||||
|
for (index = 0; index < classNodeList.length; index++)
|
||||||
|
process(classNodeList[index]);
|
||||||
|
|
||||||
|
BCV.hideFrame(gui, 10000); //hides the console after 10 seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process each class node
|
||||||
|
*/
|
||||||
|
function process(cn)
|
||||||
|
{
|
||||||
|
out("Node: " + cn.name + ".class");
|
||||||
|
//TODO developer plugin code goes here
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print to console
|
||||||
|
*/
|
||||||
|
function out(text)
|
||||||
|
{
|
||||||
|
gui.appendText(text);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue