Merge pull request #45 from TheBiblMan/master

pull
This commit is contained in:
Kalen (Konloch) Kinloch 2015-06-01 08:04:08 -06:00
commit c888f42404
26 changed files with 751 additions and 457 deletions

View file

@ -39,6 +39,7 @@ import the.bytecode.club.bytecodeviewer.gui.SearchingPane;
import the.bytecode.club.bytecodeviewer.gui.SystemErrConsole;
import the.bytecode.club.bytecodeviewer.gui.WorkPane;
import the.bytecode.club.bytecodeviewer.obfuscators.mapping.Refactorer;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
/**
* A lightweight Java Reverse Engineering suite, developed by Konloch -
@ -668,18 +669,18 @@ public class BytecodeViewer {
/**
* Starts the specified plugin
* @param plugin the file of the plugin
* @param file the file of the plugin
*/
public static void startPlugin(File plugin) {
if (!plugin.exists())
public static void startPlugin(File file) {
if (!file.exists())
return;
try {
PluginManager.runPlugin(plugin);
} catch (Exception e) {
PluginManager.runPlugin(file);
} catch (Throwable e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
}
addRecentPlugin(plugin);
addRecentPlugin(file);
}
/**
@ -792,6 +793,7 @@ public class BytecodeViewer {
if (!s.isEmpty()) {
JMenuItem m = new JMenuItem(s);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem m = (JMenuItem) e.getSource();
openFiles(new File[] { new File(m.getText()) }, true);
@ -804,6 +806,7 @@ public class BytecodeViewer {
if (!s.isEmpty()) {
JMenuItem m = new JMenuItem(s);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JMenuItem m = (JMenuItem) e.getSource();
startPlugin(new File(m.getText()));

View file

@ -79,4 +79,8 @@ public class MiscUtils {
}
return i;
}
public static String extension(String name) {
return name.substring(name.lastIndexOf('.') + 1);
}
}

View file

@ -1,155 +0,0 @@
package the.bytecode.club.bytecodeviewer;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import me.konloch.kontainer.io.DiskReader;
import org.codehaus.janino.*;
import the.bytecode.club.bytecodeviewer.api.Plugin;
/**
* Supports loading of groovy, python or ruby scripts.
*
* Only allows one plugin to be running at once.
*
* @author Konloch
*
*/
public class PluginManager {
private static Plugin pluginInstance;
private static SimpleCompiler compiler = new SimpleCompiler();
/**
* Runs a new plugin instance
* @param newPluginInstance the new plugin instance
*/
public static void runPlugin(Plugin newPluginInstance) {
if (pluginInstance == null || pluginInstance.isFinished()) {
pluginInstance = newPluginInstance;
pluginInstance.start(); // start the thread
} else if (!pluginInstance.isFinished()) {
BytecodeViewer.showMessage("There is currently another plugin running right now, please wait for that to finish executing.");
}
}
/**
* Starts and runs a plugin from file
* @param f the file of the plugin
* @throws Exception
*/
public static void runPlugin(File f) throws Exception {
Plugin p = null;
if (f.getName().endsWith(".java")) {
p = loadJavaScript(f);
}
if (f.getName().endsWith(".gy") || f.getName().endsWith(".groovy")) {
p = loadGroovyScript(f);
}
if (f.getName().endsWith(".py") || f.getName().endsWith(".python")) {
p = loadPythonScript(f);
}
if (f.getName().endsWith(".rb") || f.getName().endsWith(".ruby")) {
p = loadRubyScript(f);
}
if (p != null) {
runPlugin(p);
}
}
/**
* Loads a Java file as a Script
*
* @param file
* @return
* @throws Exception
*/
private static Plugin loadJavaScript(File file) throws Exception {
compiler.cook(DiskReader.loadAsString(file.getAbsolutePath()));
System.out.println(file.getName().substring(0,(int)(file.getName().length()-(".java".length()))));
Class<?> clazz = (Class<?>) Class.forName(
file.getName().substring(0,(int)file.getName().length()-".java".length()),
true,
compiler.getClassLoader()
);
return (Plugin) clazz.newInstance();
}
/**
* Loads a groovy file as a Script
*
* @param file
* @return
* @throws Exception
*/
private static Plugin loadGroovyScript(File file) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
if (engine == null)
throw new Exception(
"Cannot find Groovy script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval("new "
+ file.getName().replace(".gy", "").replace(".groovy", "")
+ "();");
}
/**
* Loads a python file as a Script
*
* @param file
* @return
* @throws Exception
*/
private static Plugin loadPythonScript(File file) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
if (engine == null)
throw new Exception(
"Cannot find Jython script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval(file.getName().replace(".py", "")
.replace(".python", "")
+ "()");
}
/**
* Loads a ruby file as a Script
*
* @param file
* @return
* @throws Exception
*/
private static Plugin loadRubyScript(File file) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
if (engine == null)
throw new Exception(
"Cannot find jRuby script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval(file.getName().replace(".rb", "")
.replace(".ruby", "")
+ ".new");
}
}

View file

@ -13,7 +13,7 @@ import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.JarUtils;
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.plugins.EZInjection;
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.EZInjection;
/**
* The official API for BCV, this was designed for plugin authors and

View file

@ -1,20 +1,18 @@
package the.bytecode.club.bytecodeviewer.api;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import java.awt.Dimension;
import java.awt.CardLayout;
import javax.swing.JTextArea;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
import java.awt.Color;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* A simple class designed to show exceptions in the UI.
*
@ -30,7 +28,7 @@ public class ExceptionUI extends JFrame {
* @param e
* The exception to be shown
*/
public ExceptionUI(Exception e) {
public ExceptionUI(Throwable e) {
setup(e, "@Konloch - konloch@gmail.com");
}
@ -48,7 +46,7 @@ public class ExceptionUI extends JFrame {
* @param author
* the author of the plugin throwing this exception.
*/
public ExceptionUI(Exception e, String author) {
public ExceptionUI(Throwable e, String author) {
setup(e, author);
}
@ -62,7 +60,7 @@ public class ExceptionUI extends JFrame {
setup(e, author);
}
private void setup(Exception e, String author) {
private void setup(Throwable e, String author) {
this.setIconImages(Resources.iconList);
setSize(new Dimension(600, 400));

View file

@ -1,30 +1,34 @@
package the.bytecode.club.bytecodeviewer.gui;
import javax.swing.ButtonGroup;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.BoxLayout;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.ArrayList;
import javax.swing.filechooser.FileFilter;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JSeparator;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import org.objectweb.asm.tree.ClassNode;
@ -32,20 +36,19 @@ import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Dex2Jar;
import the.bytecode.club.bytecodeviewer.FileChangeNotifier;
import the.bytecode.club.bytecodeviewer.JarUtils;
import the.bytecode.club.bytecodeviewer.PluginManager;
import the.bytecode.club.bytecodeviewer.MiscUtils;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.decompilers.Decompiler;
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameClasses;
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameFields;
import the.bytecode.club.bytecodeviewer.obfuscators.rename.RenameMethods;
import the.bytecode.club.bytecodeviewer.plugins.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import javax.swing.JRadioButtonMenuItem;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
import the.bytecode.club.bytecodeviewer.plugins.AllatoriStringDecrypter;
import the.bytecode.club.bytecodeviewer.plugins.CodeSequenceDiagram;
import the.bytecode.club.bytecodeviewer.plugins.ShowAllStrings;
import the.bytecode.club.bytecodeviewer.plugins.ShowMainMethods;
import the.bytecode.club.bytecodeviewer.plugins.ZKMStringDecrypter;
import the.bytecode.club.bytecodeviewer.plugins.ZStringArrayDecrypter;
/**
* The main file for the GUI.n
@ -53,7 +56,6 @@ import javax.swing.JRadioButtonMenuItem;
* @author Konloch
*
*/
public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public void pythonC() {
@ -459,6 +461,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public final JRadioButtonMenuItem panel3Hexcode = new JRadioButtonMenuItem("Hexcode");
public void setIcon(final boolean busy) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (busy) {
try {
@ -494,7 +497,8 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_5.setVisible(false);
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new Test());
this.addWindowStateListener(new WindowAdapter() {
public void windowStateChanged(WindowEvent evt) {
@Override
public void windowStateChanged(WindowEvent evt) {
int oldState = evt.getOldState();
int newState = evt.getNewState();
@ -540,6 +544,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
menuBar.add(mnNewMenu);
mntmNewWorkspace.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
BytecodeViewer.resetWorkSpace(true);
}
@ -547,6 +552,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JMenuItem mntmLoadJar = new JMenuItem("Add..");
mntmLoadJar.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser();
try {
@ -581,6 +587,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JMenuItem mntmSave = new JMenuItem("Save As Zip..");
mntmSave.setActionCommand("");
mntmSave.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -637,6 +644,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu.add(separator_3);
mntmNewMenuItem_3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -681,11 +689,13 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}
});
mntmNewMenuItem_13.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
BytecodeViewer.compile(true);
}
});
mntmRun.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -703,6 +713,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu.add(mntmNewMenuItem_3);
mntmSaveAsApk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -769,6 +780,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu.add(mntmSaveAsApk);
mnNewMenu.add(mntmSave);
mntmNewMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -905,6 +917,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}
});
mntmNewMenuItem_12.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(workPane.getCurrentViewer() == null) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -1056,6 +1069,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JSeparator separator_1 = new JSeparator();
mnNewMenu.add(separator_1);
mntmAbout.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
aboutWindow.setVisible(true);
}
@ -1065,6 +1079,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
JMenuItem mntmExit = new JMenuItem("Exit");
mntmExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JOptionPane pane = new JOptionPane(
"Are you sure you want to exit?");
@ -1085,6 +1100,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}
});
mntmPingback.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
BytecodeViewer.pingback();
}
@ -1304,6 +1320,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnSettings.add(separator_13);
mntmSetPythonDirectory.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
pythonC();
}
@ -1311,6 +1328,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnSettings.add(mntmSetPythonDirectory);
mntmSetJreRt.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
rtC();
}
@ -1318,6 +1336,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnSettings.add(mntmSetJreRt);
mntmSetOpitonalLibrary.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
library();
}
@ -1542,6 +1561,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
menuBar.add(mnNewMenu_5);
mntmNewMenuItem_6.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (BytecodeViewer.runningObfuscation) {
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish.");
@ -1564,6 +1584,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_5.add(mntmNewMenuItem_6);
mntmNewMenuItem_7.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (BytecodeViewer.runningObfuscation) {
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish.");
@ -1577,6 +1598,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_5.add(mntmNewMenuItem_7);
mntmNewMenuItem_11.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (BytecodeViewer.runningObfuscation) {
BytecodeViewer.showMessage("You're currently running an obfuscation task, wait for this to finish.");
@ -1602,6 +1624,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_1.add(mnRecentPlugins);
mnNewMenu_1.add(separator_5);
mntmCodeSequenceDiagram.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -1616,6 +1639,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_1.add(mntmShowMainMethods);
mnNewMenu_1.add(mntmShowAllStrings);
mntmReplaceStrings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -1629,6 +1653,7 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
mnNewMenu_1.add(mntmNewMenuItem_2);
mnNewMenu_1.add(mntmStartZkmString);
mntmZstringarrayDecrypter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
PluginManager.runPlugin(new ZStringArrayDecrypter());
}
@ -1639,9 +1664,10 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
menuBar.add(mntmNewMenuItem_4);
mntmStartExternalPlugin.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JFileChooser fc = new JFileChooser();
fc.setFileFilter(new JavaPFileFilter());
fc.setFileFilter(PluginManager.fileFilter());
fc.setFileHidingEnabled(false);
fc.setAcceptAllFileFilterUsed(false);
int returnVal = fc.showOpenDialog(BytecodeViewer.viewer);
@ -1657,16 +1683,19 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}
});
mntmStartZkmString.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PluginManager.runPlugin(new ZKMStringDecrypter());
}
});
mntmNewMenuItem_2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PluginManager.runPlugin(new AllatoriStringDecrypter());
}
});
mntmNewMenuItem_1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(BytecodeViewer.getLoadedClasses().isEmpty()) {
BytecodeViewer.showMessage("First open a class, jar, zip, apk or dex file.");
@ -1676,12 +1705,14 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
}
});
mntmShowAllStrings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PluginManager.runPlugin(new ShowAllStrings());
}
});
mntmShowMainMethods.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PluginManager.runPlugin(new ShowMainMethods());
}
@ -1801,13 +1832,15 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
return null;
}
/* 01/06/15, 14:33 changed by Bibl. */
public class GroovyPythonRubyFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
String extension = MiscUtils.extension(f.getAbsolutePath());
if (extension != null)
return (extension.equals("gy") || extension.equals("groovy")
|| extension.equals("py") || extension.equals("python")
@ -1820,27 +1853,15 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public String getDescription() {
return "Groovy, Python or Ruby plugins.";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class GroovyFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
String extension = MiscUtils.extension(f.getAbsolutePath());
if (extension != null)
return (extension.equals("gy") || extension.equals("groovy"));
@ -1851,25 +1872,15 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public String getDescription() {
return "Groovy plugins.";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class APKDEXJarZipClassFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
String extension = MiscUtils.extension(f.getAbsolutePath());
if (extension != null)
if (extension.equals("jar") || extension.equals("zip")
|| extension.equals("class") || extension.equals("apk")
@ -1883,167 +1894,54 @@ public class MainViewerGUI extends JFrame implements FileChangeNotifier {
public String getDescription() {
return "APKs, DEX, Class Files or Zip/Jar Archives";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class ZipFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("zip"));
return false;
return f.isDirectory() || MiscUtils.extension(f.getAbsolutePath()).equals("zip");
}
@Override
public String getDescription() {
return "Zip Archives";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class JarFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("jar"));
return false;
return f.isDirectory() || MiscUtils.extension(f.getAbsolutePath()).equals("jar");
}
@Override
public String getDescription() {
return "Jar Archives";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class JavaFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("java"));
return false;
return f.isDirectory() || MiscUtils.extension(f.getAbsolutePath()).equals("java");
}
@Override
public String getDescription() {
return "Java Source Files";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class JavaPFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("java"));
return false;
}
@Override
public String getDescription() {
return "Java Plugins";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class DexFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = getExtension(f);
if (extension != null)
return (extension.equals("dex"));
return false;
return f.isDirectory() || MiscUtils.extension(f.getAbsolutePath()).equals("dex");
}
@Override
public String getDescription() {
return "Android DEX Files";
}
public String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');
if (i > 0 && i < s.length() - 1)
ext = s.substring(i + 1).toLowerCase();
return ext;
}
}
public class PythonCFileFilter extends FileFilter {

View file

@ -7,9 +7,9 @@ import java.awt.Dimension;
import javax.swing.JCheckBox;
import javax.swing.JButton;
import the.bytecode.club.bytecodeviewer.PluginManager;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.plugins.MaliciousCodeScanner;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.MaliciousCodeScanner;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

View file

@ -7,9 +7,9 @@ import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import the.bytecode.club.bytecodeviewer.PluginManager;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.plugins.ReplaceStrings;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.ReplaceStrings;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

View file

@ -8,9 +8,9 @@ import javax.swing.JCheckBox;
import javax.swing.JButton;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.PluginManager;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.plugins.EZInjection;
import the.bytecode.club.bytecodeviewer.plugin.PluginManager;
import the.bytecode.club.bytecodeviewer.plugin.preinstalled.EZInjection;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

View file

@ -0,0 +1,14 @@
package the.bytecode.club.bytecodeviewer.plugin;
import java.io.File;
import the.bytecode.club.bytecodeviewer.api.Plugin;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public abstract interface PluginLaunchStrategy {
public abstract Plugin run(File file) throws Throwable;
}

View file

@ -0,0 +1,128 @@
package the.bytecode.club.bytecodeviewer.plugin;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.filechooser.FileFilter;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.MiscUtils;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.strategies.CompiledJavaPluginLaunchStrategy;
import the.bytecode.club.bytecodeviewer.plugin.strategies.GroovyPluginLaunchStrategy;
import the.bytecode.club.bytecodeviewer.plugin.strategies.JavaPluginLaunchStrategy;
import the.bytecode.club.bytecodeviewer.plugin.strategies.PythonPluginLaunchStrategy;
import the.bytecode.club.bytecodeviewer.plugin.strategies.RubyPluginLaunchStrategy;
/**
* Supports loading of groovy, python or ruby scripts.
*
* Only allows one plugin to be running at once.
*
* @author Konloch
* @author Bibl
*
* @since 01/16/16, 14:36, Adaptable PluginLaunchStrategy system.
*/
public final class PluginManager {
private static final Map<String, PluginLaunchStrategy> launchStrategies = new HashMap<String, PluginLaunchStrategy>();
private static final PluginFileFilter filter = new PluginFileFilter();
private static Plugin pluginInstance;
static {
launchStrategies.put("jar", new CompiledJavaPluginLaunchStrategy());
launchStrategies.put("java", new JavaPluginLaunchStrategy());
GroovyPluginLaunchStrategy groovy = new GroovyPluginLaunchStrategy();
launchStrategies.put("gy", groovy);
launchStrategies.put("groovy", groovy);
PythonPluginLaunchStrategy python = new PythonPluginLaunchStrategy();
launchStrategies.put("py", python);
launchStrategies.put("python", python);
RubyPluginLaunchStrategy ruby = new RubyPluginLaunchStrategy();
launchStrategies.put("rb", ruby);
launchStrategies.put("ruby", ruby);
}
/**
* Runs a new plugin instance
* @param newPluginInstance the new plugin instance
*/
public static void runPlugin(Plugin newPluginInstance) {
if (pluginInstance == null || pluginInstance.isFinished()) {
pluginInstance = newPluginInstance;
pluginInstance.start(); // start the thread
} else if (!pluginInstance.isFinished()) {
BytecodeViewer.showMessage("There is currently another plugin running right now, please wait for that to finish executing.");
}
}
/**
* Starts and runs a plugin from file
* @param f the file of the plugin
* @throws Exception
*/
public static void runPlugin(File f) throws Throwable {
String ext = f.getName().substring(f.getName().lastIndexOf('.') + 1);
PluginLaunchStrategy strategy = launchStrategies.get(ext);
if(strategy == null) {
throw new RuntimeException(String.format("No launch strategy for extension %s (%s)", ext, f.getAbsolutePath()));
}
Plugin p = strategy.run(f);
if(p != null) {
runPlugin(p);
}
/*if (f.getName().endsWith(".java")) {
p = loadJavaScript(f);
}
if (f.getName().endsWith(".gy") || f.getName().endsWith(".groovy")) {
p = loadGroovyScript(f);
}
if (f.getName().endsWith(".py") || f.getName().endsWith(".python")) {
p = loadPythonScript(f);
}
if (f.getName().endsWith(".rb") || f.getName().endsWith(".ruby")) {
p = loadRubyScript(f);
}
if (p != null) {
runPlugin(p);
}*/
}
public static void register(String name, PluginLaunchStrategy strat) {
launchStrategies.put(name, strat);
}
public static Set<String> pluginExtensions() {
return launchStrategies.keySet();
}
public static FileFilter fileFilter() {
return filter;
}
public static class PluginFileFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory())
return true;
return PluginManager.pluginExtensions().contains(MiscUtils.extension(f.getAbsolutePath()));
}
@Override
public String getDescription() {
return "Plugins";
}
}
}

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;

View file

@ -0,0 +1,93 @@
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.UIManager;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
/**
* A simple code sequence diagram.
*
* @author Konloch
*
*/
public class CodeSequenceDiagram extends Plugin {
@SuppressWarnings("unchecked")
@Override
public void execute(ArrayList<ClassNode> classNodeList) {
if(BytecodeViewer.viewer.workPane.getCurrentViewer() == null || !(BytecodeViewer.viewer.workPane.getCurrentViewer() instanceof ClassViewer)) {
BytecodeViewer.showMessage("First open a class file.");
return;
}
ClassNode c = BytecodeViewer.viewer.workPane.getCurrentViewer().cn;
JFrame frame = new JFrame("Code Sequence Diagram - " +c.name);
frame.setIconImages(Resources.iconList);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 320);
mxGraph graph = new mxGraph();
graph.setVertexLabelsMovable(false);
graph.setGridEnabled(true);
graph.setEnabled(false);
graph.setCellsEditable(false);
graph.setCellsSelectable(false);
graph.setCellsMovable(false);
graph.setCellsLocked(true);
Object parent = graph.getDefaultParent();
Font font = UIManager.getDefaults().getFont("TabbedPane.font");
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
graph.getModel().beginUpdate();
try
{
int testX = 10;
int testY = 0;
double magicNumber = 5.8;
for(MethodNode m : (ArrayList<MethodNode>)c.methods) {
String mIdentifier = c.name+"."+m.name+m.desc;
Object node = graph.insertVertex(parent, null, mIdentifier, testX, testY, mIdentifier.length() * magicNumber, 30);
Object attach = node;
testX += (int) (font.getStringBounds(mIdentifier, frc).getWidth()) + 60;
for (AbstractInsnNode i : m.instructions.toArray()) {
if (i instanceof MethodInsnNode) {
MethodInsnNode mi = (MethodInsnNode) i;
String identifier = mi.owner+"."+mi.name+mi.desc;
Object node2 = graph.insertVertex(parent, null, identifier, testX, testY, identifier.length() * 5, 30);
testX += (int) (font.getStringBounds(identifier, frc).getWidth()) + 60;
graph.insertEdge(parent, null, null, attach, node2);
attach = node2;
}
}
testY += 60;
testX = 10;
}
} finally {
graph.getModel().endUpdate();
}
mxGraphComponent graphComponent = new mxGraphComponent(graph);
frame.getContentPane().add(graphComponent);
frame.setVisible(true);
}
}

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.io.PrintWriter;
import java.io.StringWriter;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import java.util.ArrayList;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import org.objectweb.asm.tree.ClassNode;

View file

@ -1,4 +1,4 @@
package the.bytecode.club.bytecodeviewer.plugins;
package the.bytecode.club.bytecodeviewer.plugin.preinstalled;
import org.objectweb.asm.tree.ClassNode;

View file

@ -0,0 +1,179 @@
package the.bytecode.club.bytecodeviewer.plugin.strategies;
import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.tree.ClassNode;
import the.bytecode.club.bytecodeviewer.JarUtils;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public class CompiledJavaPluginLaunchStrategy implements PluginLaunchStrategy {
private static final String PLUGIN_CLASS_NAME = Plugin.class.getCanonicalName().replace(".", "/");
private final Set<LoadedPluginData> loaded = new HashSet<LoadedPluginData>();
@Override
public Plugin run(File file) throws Throwable {
Set<LoadedNodeData> set = loadData(file);
LoadedNodeData pdata = null;
for(LoadedNodeData d : set) {
ClassNode cn = d.node;
if(cn.superName.equals(PLUGIN_CLASS_NAME)) {
if(pdata == null) {
pdata = d;
} else {
throw new RuntimeException("Multiple plugin subclasses.");
}
}
}
LoadingClassLoader cl = new LoadingClassLoader(pdata, set);
Plugin p = cl.pluginKlass.newInstance();
LoadedPluginData npdata = new LoadedPluginData(pdata, cl, p);
loaded.add(npdata);
return p;
}
public Set<LoadedPluginData> getLoaded() {
return loaded;
}
private static Set<LoadedNodeData> loadData(File jarFile) throws Throwable {
ZipInputStream jis = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry entry;
Set<LoadedNodeData> set = new HashSet<LoadedNodeData>();
while ((entry = jis.getNextEntry()) != null) {
try {
String name = entry.getName();
if(!name.endsWith(".class")){
byte[] bytes = JarUtils.getBytes(jis);
String magic = String.format("%02X", bytes[0]) + String.format("%02X", bytes[1]) + String.format("%02X", bytes[2]) + String.format("%02X", bytes[3]);
if(magic.toLowerCase().equals("cafebabe")) {
try {
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
LoadedNodeData data = new LoadedNodeData(bytes, cn);
set.add(data);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println(jarFile + ">" + name + ": Header does not start with CAFEBABE, ignoring.");
}
}
} catch(Exception e) {
new the.bytecode.club.bytecodeviewer.api.ExceptionUI(e);
} finally {
jis.closeEntry();
}
}
jis.close();
return set;
}
public static class LoadedNodeData {
private final byte[] bytes;
private final ClassNode node;
public LoadedNodeData(byte[] bytes, ClassNode node) {
this.bytes = bytes;
this.node = node;
}
}
public static class LoadedPluginData {
private final LoadedNodeData data;
private final LoadingClassLoader classLoader;
private final Plugin plugin;
public LoadedPluginData(LoadedNodeData data, LoadingClassLoader classLoader, Plugin plugin) {
this.data = data;
this.classLoader = classLoader;
this.plugin = plugin;
}
public LoadedNodeData getData() {
return data;
}
public LoadingClassLoader getClassLoader() {
return classLoader;
}
public Plugin getPlugin() {
return plugin;
}
}
public static class LoadingClassLoader extends ClassLoader {
private final LoadedNodeData data;
private Map<String, LoadedNodeData> cache;
private Map<String, Class<?>> ccache;
private final Class<? extends Plugin> pluginKlass;
public LoadingClassLoader(LoadedNodeData data, Set<LoadedNodeData> set) throws Throwable{
this.data = data;
cache = new HashMap<String, LoadedNodeData>();
ccache = new HashMap<String, Class<?>>();
for(LoadedNodeData d: set) {
if(d != data) {
cache.put(d.node.name, d);
}
}
@SuppressWarnings("unchecked")
Class<? extends Plugin> pluginKlass = (Class<? extends Plugin>) loadClass(data.node.name.replace("/", "."));
if(pluginKlass == null)
throw new RuntimeException();
this.pluginKlass = pluginKlass;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
name = name.replace("/", ".");
if(ccache.containsKey(name))
return ccache.get(name);
LoadedNodeData data = cache.get(name);
if(data != null) {
byte[] bytes = data.bytes;
Class<?> klass = defineClass(data.node.name, bytes, 0, bytes.length);
ccache.put(name, klass);
return klass;
}
return super.findClass(name);
}
public LoadedNodeData getPluginNode() {
return data;
}
public Class<? extends Plugin> getPluginKlass() {
return pluginKlass;
}
}
}

View file

@ -0,0 +1,33 @@
package the.bytecode.club.bytecodeviewer.plugin.strategies;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public class GroovyPluginLaunchStrategy implements PluginLaunchStrategy {
@Override
public Plugin run(File file) throws Throwable {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("groovy");
if (engine == null)
throw new Exception(
"Cannot find Groovy script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval("new " + file.getName().replace(".gy", "").replace(".groovy", "") + "();");
}
}

View file

@ -0,0 +1,33 @@
package the.bytecode.club.bytecodeviewer.plugin.strategies;
import java.io.File;
import me.konloch.kontainer.io.DiskReader;
import org.codehaus.janino.SimpleCompiler;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public class JavaPluginLaunchStrategy implements PluginLaunchStrategy {
private static SimpleCompiler compiler = new SimpleCompiler();
@Override
public Plugin run(File file) throws Throwable {
compiler.cook(DiskReader.loadAsString(file.getAbsolutePath()));
System.out.println(file.getName().substring(0,(int)(file.getName().length()-(".java".length()))));
Class<?> clazz = (Class<?>) Class.forName(
file.getName().substring(0,(int)file.getName().length()-".java".length()),
true,
compiler.getClassLoader()
);
return (Plugin) clazz.newInstance();
}
}

View file

@ -0,0 +1,33 @@
package the.bytecode.club.bytecodeviewer.plugin.strategies;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public class PythonPluginLaunchStrategy implements PluginLaunchStrategy {
@Override
public Plugin run(File file) throws Throwable {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");
if (engine == null)
throw new Exception(
"Cannot find Jython script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval(file.getName().replace(".py", "").replace(".python", "") + "()");
}
}

View file

@ -0,0 +1,33 @@
package the.bytecode.club.bytecodeviewer.plugin.strategies;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.plugin.PluginLaunchStrategy;
/**
* @author Bibl (don't ban me pls)
* @created 1 Jun 2015
*/
public class RubyPluginLaunchStrategy implements PluginLaunchStrategy {
@Override
public Plugin run(File file) throws Throwable {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
if (engine == null)
throw new Exception(
"Cannot find jRuby script engine! Please contact Konloch.");
Reader reader = new FileReader(file);
engine.eval(reader);
return (Plugin) engine.eval(file.getName().replace(".rb", "").replace(".ruby", "") + ".new");
}
}

View file

@ -1,102 +1,102 @@
package the.bytecode.club.bytecodeviewer.plugins;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.UIManager;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
/**
* A simple code sequence diagram.
*
* @author Konloch
*
*/
public class CodeSequenceDiagram extends Plugin {
@SuppressWarnings("unchecked")
@Override
public void execute(ArrayList<ClassNode> classNodeList) {
if(BytecodeViewer.viewer.workPane.getCurrentViewer() == null || !(BytecodeViewer.viewer.workPane.getCurrentViewer() instanceof ClassViewer)) {
BytecodeViewer.showMessage("First open a class file.");
return;
}
ClassNode c = BytecodeViewer.viewer.workPane.getCurrentViewer().cn;
if(c == null) {
BytecodeViewer.showMessage("ClassNode is null for CodeSequenceDiagram. Please report to @Konloch");
return;
}
JFrame frame = null;
if(c.name != null)
frame = new JFrame("Code Sequence Diagram - "+c.name);
else
frame = new JFrame("Code Sequence Diagram - Unknown Name");
frame.setIconImages(Resources.iconList);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 320);
mxGraph graph = new mxGraph();
graph.setVertexLabelsMovable(false);
graph.setGridEnabled(true);
graph.setEnabled(false);
graph.setCellsEditable(false);
graph.setCellsSelectable(false);
graph.setCellsMovable(false);
graph.setCellsLocked(true);
Object parent = graph.getDefaultParent();
Font font = UIManager.getDefaults().getFont("TabbedPane.font");
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
graph.getModel().beginUpdate();
try
{
int testX = 10;
int testY = 0;
double magicNumber = 5.8;
for(MethodNode m : (ArrayList<MethodNode>)c.methods) {
String mIdentifier = c.name+"."+m.name+m.desc;
Object node = graph.insertVertex(parent, null, mIdentifier, testX, testY, mIdentifier.length() * magicNumber, 30);
Object attach = node;
testX += (int) (font.getStringBounds(mIdentifier, frc).getWidth()) + 60;
for (AbstractInsnNode i : m.instructions.toArray()) {
if (i instanceof MethodInsnNode) {
MethodInsnNode mi = (MethodInsnNode) i;
String identifier = mi.owner+"."+mi.name+mi.desc;
Object node2 = graph.insertVertex(parent, null, identifier, testX, testY, identifier.length() * 5, 30);
testX += (int) (font.getStringBounds(identifier, frc).getWidth()) + 60;
graph.insertEdge(parent, null, null, attach, node2);
attach = node2;
}
}
testY += 60;
testX = 10;
}
} finally {
graph.getModel().endUpdate();
}
mxGraphComponent graphComponent = new mxGraphComponent(graph);
frame.getContentPane().add(graphComponent);
frame.setVisible(true);
}
package the.bytecode.club.bytecodeviewer.plugins;
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.UIManager;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.view.mxGraph;
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
import the.bytecode.club.bytecodeviewer.Resources;
import the.bytecode.club.bytecodeviewer.api.Plugin;
import the.bytecode.club.bytecodeviewer.gui.ClassViewer;
/**
* A simple code sequence diagram.
*
* @author Konloch
*
*/
public class CodeSequenceDiagram extends Plugin {
@SuppressWarnings("unchecked")
@Override
public void execute(ArrayList<ClassNode> classNodeList) {
if(BytecodeViewer.viewer.workPane.getCurrentViewer() == null || !(BytecodeViewer.viewer.workPane.getCurrentViewer() instanceof ClassViewer)) {
BytecodeViewer.showMessage("First open a class file.");
return;
}
ClassNode c = BytecodeViewer.viewer.workPane.getCurrentViewer().cn;
if(c == null) {
BytecodeViewer.showMessage("ClassNode is null for CodeSequenceDiagram. Please report to @Konloch");
return;
}
JFrame frame = null;
if(c.name != null)
frame = new JFrame("Code Sequence Diagram - "+c.name);
else
frame = new JFrame("Code Sequence Diagram - Unknown Name");
frame.setIconImages(Resources.iconList);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setSize(400, 320);
mxGraph graph = new mxGraph();
graph.setVertexLabelsMovable(false);
graph.setGridEnabled(true);
graph.setEnabled(false);
graph.setCellsEditable(false);
graph.setCellsSelectable(false);
graph.setCellsMovable(false);
graph.setCellsLocked(true);
Object parent = graph.getDefaultParent();
Font font = UIManager.getDefaults().getFont("TabbedPane.font");
AffineTransform affinetransform = new AffineTransform();
FontRenderContext frc = new FontRenderContext(affinetransform,true,true);
graph.getModel().beginUpdate();
try
{
int testX = 10;
int testY = 0;
double magicNumber = 5.8;
for(MethodNode m : (ArrayList<MethodNode>)c.methods) {
String mIdentifier = c.name+"."+m.name+m.desc;
Object node = graph.insertVertex(parent, null, mIdentifier, testX, testY, mIdentifier.length() * magicNumber, 30);
Object attach = node;
testX += (int) (font.getStringBounds(mIdentifier, frc).getWidth()) + 60;
for (AbstractInsnNode i : m.instructions.toArray()) {
if (i instanceof MethodInsnNode) {
MethodInsnNode mi = (MethodInsnNode) i;
String identifier = mi.owner+"."+mi.name+mi.desc;
Object node2 = graph.insertVertex(parent, null, identifier, testX, testY, identifier.length() * 5, 30);
testX += (int) (font.getStringBounds(identifier, frc).getWidth()) + 60;
graph.insertEdge(parent, null, null, attach, node2);
attach = node2;
}
}
testY += 60;
testX = 10;
}
} finally {
graph.getModel().endUpdate();
}
mxGraphComponent graphComponent = new mxGraphComponent(graph);
frame.getContentPane().add(graphComponent);
frame.setVisible(true);
}
}