mirror of
https://github.com/SuspiciousActivity/ByteEdit.git
synced 2026-08-13 17:56:17 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac247a89ca | ||
|
|
b5e4847be5 | ||
|
|
30c9c81d38 | ||
|
|
65235c6b5b | ||
|
|
d8096a4ec5 | ||
|
|
add82951e6 | ||
|
|
afc59d63d3 | ||
|
|
53f214b7b0 | ||
|
|
385c9ad9e3 | ||
|
|
a70bc89deb |
No files matched your search
@@ -1,7 +1,6 @@
|
|||||||
package me.ByteEdit.boxes;
|
package me.ByteEdit.boxes;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@@ -22,7 +21,6 @@ import javax.swing.JFrame;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.tools.JavaCompiler;
|
import javax.tools.JavaCompiler;
|
||||||
import javax.tools.SimpleJavaFileObject;
|
import javax.tools.SimpleJavaFileObject;
|
||||||
@@ -36,6 +34,7 @@ import org.objectweb.asm.tree.ClassNode;
|
|||||||
|
|
||||||
import me.ByteEdit.edit.Disassembler;
|
import me.ByteEdit.edit.Disassembler;
|
||||||
import me.ByteEdit.main.Main;
|
import me.ByteEdit.main.Main;
|
||||||
|
import me.ByteEdit.main.ThemeManager;
|
||||||
|
|
||||||
public class CompilationBox extends JFrame {
|
public class CompilationBox extends JFrame {
|
||||||
|
|
||||||
@@ -46,32 +45,25 @@ public class CompilationBox extends JFrame {
|
|||||||
|
|
||||||
public CompilationBox() {
|
public CompilationBox() {
|
||||||
compSuccess = new CompilationSuccess();
|
compSuccess = new CompilationSuccess();
|
||||||
try {
|
ThemeManager.registerFrames(compSuccess);
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setTitle("Java Compiler");
|
setTitle("Java Compiler");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 400),
|
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 400),
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 200), 800, 400);
|
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 200), 800, 400);
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
contentPane.setBackground(Main.dark ? new Color(0x2F2F2F) : Color.GRAY);
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
setContentPane(contentPane);
|
setContentPane(contentPane);
|
||||||
contentPane.setLayout(new BorderLayout(0, 0));
|
contentPane.setLayout(new BorderLayout(0, 0));
|
||||||
|
|
||||||
Main.theme.apply(textArea);
|
ThemeManager.registerTextArea(textArea);
|
||||||
textArea.setEditable(true);
|
textArea.setEditable(true);
|
||||||
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
|
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
|
||||||
textArea.setCodeFoldingEnabled(true);
|
textArea.setCodeFoldingEnabled(true);
|
||||||
textArea.setBackground(Main.dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
|
|
||||||
RTextScrollPane scrollPane = new RTextScrollPane();
|
RTextScrollPane scrollPane = new RTextScrollPane();
|
||||||
scrollPane.setViewportView(textArea);
|
scrollPane.setViewportView(textArea);
|
||||||
scrollPane.setLineNumbersEnabled(true);
|
scrollPane.setLineNumbersEnabled(true);
|
||||||
scrollPane.setFoldIndicatorEnabled(true);
|
scrollPane.setFoldIndicatorEnabled(true);
|
||||||
scrollPane.getGutter().setBackground(Main.dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
contentPane.add(scrollPane);
|
contentPane.add(scrollPane);
|
||||||
|
|
||||||
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
package me.ByteEdit.boxes;
|
package me.ByteEdit.boxes;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
|
||||||
import me.ByteEdit.main.Main;
|
import me.ByteEdit.main.ThemeManager;
|
||||||
|
|
||||||
public class CompilationSuccess extends JFrame {
|
public class CompilationSuccess extends JFrame {
|
||||||
|
|
||||||
@@ -21,32 +19,24 @@ public class CompilationSuccess extends JFrame {
|
|||||||
RSyntaxTextArea textArea = new RSyntaxTextArea();
|
RSyntaxTextArea textArea = new RSyntaxTextArea();
|
||||||
|
|
||||||
public CompilationSuccess() {
|
public CompilationSuccess() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setTitle("Java Compiler - Result");
|
setTitle("Java Compiler - Result");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 400),
|
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 400),
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 200), 800, 400);
|
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 200), 800, 400);
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
contentPane.setBackground(Main.dark ? new Color(0x2F2F2F) : Color.GRAY);
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
setContentPane(contentPane);
|
setContentPane(contentPane);
|
||||||
contentPane.setLayout(new BorderLayout(0, 0));
|
contentPane.setLayout(new BorderLayout(0, 0));
|
||||||
|
|
||||||
Main.theme.apply(textArea);
|
ThemeManager.registerTextArea(textArea);
|
||||||
textArea.setEditable(true);
|
textArea.setEditable(true);
|
||||||
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE);
|
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE);
|
||||||
textArea.setCodeFoldingEnabled(true);
|
textArea.setCodeFoldingEnabled(true);
|
||||||
textArea.setBackground(Main.dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
|
|
||||||
RTextScrollPane scrollPane = new RTextScrollPane();
|
RTextScrollPane scrollPane = new RTextScrollPane();
|
||||||
scrollPane.setViewportView(textArea);
|
scrollPane.setViewportView(textArea);
|
||||||
scrollPane.setLineNumbersEnabled(true);
|
scrollPane.setLineNumbersEnabled(true);
|
||||||
scrollPane.setFoldIndicatorEnabled(true);
|
scrollPane.setFoldIndicatorEnabled(true);
|
||||||
scrollPane.getGutter().setBackground(Main.dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
contentPane.add(scrollPane);
|
contentPane.add(scrollPane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,6 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
@@ -27,6 +26,7 @@ import org.objectweb.asm.tree.MethodNode;
|
|||||||
|
|
||||||
import me.ByteEdit.boxes.GlobalSearchOpenBox.Info;
|
import me.ByteEdit.boxes.GlobalSearchOpenBox.Info;
|
||||||
import me.ByteEdit.main.Main;
|
import me.ByteEdit.main.Main;
|
||||||
|
import me.ByteEdit.main.ThemeManager;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
|
|
||||||
public class GlobalSearchBox extends JFrame {
|
public class GlobalSearchBox extends JFrame {
|
||||||
@@ -43,12 +43,8 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
private GlobalSearchOpenBox openBox;
|
private GlobalSearchOpenBox openBox;
|
||||||
|
|
||||||
public GlobalSearchBox() {
|
public GlobalSearchBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
openBox = new GlobalSearchOpenBox();
|
openBox = new GlobalSearchOpenBox();
|
||||||
|
ThemeManager.registerFrames(openBox);
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Global Search");
|
setTitle("Global Search");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
@@ -141,7 +137,7 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
openBox.model.clear();
|
openBox.model.clear();
|
||||||
Set<Info> set = new HashSet<>();
|
Set<Info> set = new HashSet<>();
|
||||||
if (!txtString.getText().isEmpty()) {
|
if (!txtString.getText().isEmpty()) {
|
||||||
String str = UnicodeUtils.unescape(txtString.getText());
|
String str = UnicodeUtils.unescape(null, txtString.getText(), true);
|
||||||
if (ignoreCase) {
|
if (ignoreCase) {
|
||||||
str = str.toLowerCase();
|
str = str.toLowerCase();
|
||||||
}
|
}
|
||||||
@@ -161,11 +157,11 @@ public class GlobalSearchBox extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String owner = UnicodeUtils.unescape(txtOwner.getText());
|
String owner = UnicodeUtils.unescape(null, txtOwner.getText(), true);
|
||||||
boolean wildCardOwner = owner.isEmpty();
|
boolean wildCardOwner = owner.isEmpty();
|
||||||
String name = UnicodeUtils.unescape(txtName.getText());
|
String name = UnicodeUtils.unescape(null, txtName.getText(), true);
|
||||||
boolean wildCardName = name.isEmpty();
|
boolean wildCardName = name.isEmpty();
|
||||||
String desc = UnicodeUtils.unescape(txtDesc.getText());
|
String desc = UnicodeUtils.unescape(null, txtDesc.getText(), true);
|
||||||
boolean wildCardDesc = desc.isEmpty();
|
boolean wildCardDesc = desc.isEmpty();
|
||||||
for (ClassNode cn : Main.classNodes.values()) {
|
for (ClassNode cn : Main.classNodes.values()) {
|
||||||
for (MethodNode mn : cn.methods) {
|
for (MethodNode mn : cn.methods) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import javax.swing.JList;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.ListSelectionEvent;
|
import javax.swing.event.ListSelectionEvent;
|
||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
@@ -24,11 +23,6 @@ public class GlobalSearchOpenBox extends JFrame {
|
|||||||
DefaultListModel<Info> model;
|
DefaultListModel<Info> model;
|
||||||
|
|
||||||
public GlobalSearchOpenBox() {
|
public GlobalSearchOpenBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Global Search - Result");
|
setTitle("Global Search - Result");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.awt.Toolkit;
|
|||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
public class OptionBox extends JFrame {
|
public class OptionBox extends JFrame {
|
||||||
@@ -15,11 +14,6 @@ public class OptionBox extends JFrame {
|
|||||||
public JCheckBox chckbxComputeMax;
|
public JCheckBox chckbxComputeMax;
|
||||||
|
|
||||||
public OptionBox() {
|
public OptionBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Options");
|
setTitle("Options");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
|
|||||||
@@ -84,8 +84,8 @@ public class RenameBox extends JFrame {
|
|||||||
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String newName = UnicodeUtils.unescape(txtName.getText());
|
String newName = UnicodeUtils.unescape(null, txtName.getText(), true);
|
||||||
String newDesc = UnicodeUtils.unescape(txtDesc.getText());
|
String newDesc = UnicodeUtils.unescape(null, txtDesc.getText(), true);
|
||||||
if (ClassUtil.isObjectClassMethod(newName, newDesc, true)) {
|
if (ClassUtil.isObjectClassMethod(newName, newDesc, true)) {
|
||||||
JOptionPane.showMessageDialog(null, "Invalid name!", "Error!", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(null, "Invalid name!", "Error!", JOptionPane.ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import javax.swing.JLabel;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import me.ByteEdit.main.Main;
|
import me.ByteEdit.main.Main;
|
||||||
@@ -28,11 +27,6 @@ public class SearchBox extends JFrame {
|
|||||||
public JCheckBox chckbxCaseSensitive;
|
public JCheckBox chckbxCaseSensitive;
|
||||||
|
|
||||||
public SearchBox() {
|
public SearchBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Find/Replace");
|
setTitle("Find/Replace");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package me.ByteEdit.boxes;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import javax.swing.UIManager.LookAndFeelInfo;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
|
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||||
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
|
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||||
|
import com.formdev.flatlaf.FlatLightLaf;
|
||||||
|
import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes;
|
||||||
|
|
||||||
|
import me.ByteEdit.main.ThemeManager;
|
||||||
|
|
||||||
|
public class ThemeBox extends JFrame {
|
||||||
|
|
||||||
|
private JPanel contentPane;
|
||||||
|
private final JScrollPane scrollPane = new JScrollPane();
|
||||||
|
private final JList<LAFI> list;
|
||||||
|
|
||||||
|
public ThemeBox() {
|
||||||
|
setTitle("Theme Chooser");
|
||||||
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
|
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 200),
|
||||||
|
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 200), 400, 400);
|
||||||
|
contentPane = new JPanel();
|
||||||
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
|
setContentPane(contentPane);
|
||||||
|
contentPane.setLayout(new BorderLayout(0, 0));
|
||||||
|
|
||||||
|
contentPane.add(scrollPane, BorderLayout.CENTER);
|
||||||
|
DefaultListModel<LAFI> model = new DefaultListModel<>();
|
||||||
|
list = new JList(model);
|
||||||
|
list.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
if (e.getClickCount() == 2) {
|
||||||
|
LAFI lafi = model.get(list.locationToIndex(e.getPoint()));
|
||||||
|
if (lafi.className != null)
|
||||||
|
ThemeManager.changeUIManager(lafi.className, lafi.isDark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
list.setFont(new Font("Tahoma", Font.BOLD, 18));
|
||||||
|
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
model.addElement(new LAFI(null, "--- Installed Themes ---"));
|
||||||
|
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
||||||
|
model.addElement(new LAFI(info.getClassName(), info.getName(), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
model.addElement(new LAFI(null, "--- Core Themes ---"));
|
||||||
|
model.addElement(new LAFI(FlatLightLaf.class.getName(), "Flat Light", false));
|
||||||
|
model.addElement(new LAFI(FlatDarkLaf.class.getName(), "Flat Dark", true));
|
||||||
|
model.addElement(new LAFI(FlatIntelliJLaf.class.getName(), "Flat IntelliJ", false));
|
||||||
|
model.addElement(new LAFI(FlatDarculaLaf.class.getName(), "Flat Darcula", true));
|
||||||
|
|
||||||
|
model.addElement(new LAFI(null, "--- IntelliJ Themes ---"));
|
||||||
|
for (LookAndFeelInfo info : FlatAllIJThemes.INFOS) {
|
||||||
|
model.addElement(new LAFI(info.getClassName(), info.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollPane.setViewportView(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class LAFI {
|
||||||
|
final String className;
|
||||||
|
final String name;
|
||||||
|
final Boolean isDark;
|
||||||
|
|
||||||
|
public LAFI(String className, String name) {
|
||||||
|
this.className = className;
|
||||||
|
this.name = name;
|
||||||
|
this.isDark = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LAFI(String className, String name, boolean isDark) {
|
||||||
|
this.className = className;
|
||||||
|
this.name = name;
|
||||||
|
this.isDark = Boolean.valueOf(isDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ import javax.swing.JPanel;
|
|||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
import javax.swing.ListSelectionModel;
|
import javax.swing.ListSelectionModel;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.DocumentEvent;
|
import javax.swing.event.DocumentEvent;
|
||||||
import javax.swing.event.DocumentListener;
|
import javax.swing.event.DocumentListener;
|
||||||
@@ -27,11 +26,6 @@ public class TypeOpenBox extends JFrame {
|
|||||||
public JTextField txtSearch;
|
public JTextField txtSearch;
|
||||||
|
|
||||||
public TypeOpenBox() {
|
public TypeOpenBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Open Type");
|
setTitle("Open Type");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
@@ -82,7 +76,7 @@ public class TypeOpenBox extends JFrame {
|
|||||||
if (txtSearch.getText().isEmpty()) {
|
if (txtSearch.getText().isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String search = UnicodeUtils.unescape(txtSearch.getText()).toLowerCase();
|
String search = UnicodeUtils.unescape(null, txtSearch.getText(), true).toLowerCase();
|
||||||
if (search.contains("/")) {
|
if (search.contains("/")) {
|
||||||
for (String s : Main.classNodes.keySet()) {
|
for (String s : Main.classNodes.keySet()) {
|
||||||
String className = s.substring(0, s.length() - 6);
|
String className = s.substring(0, s.length() - 6);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import javax.swing.JFrame;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
import me.ByteEdit.main.Main;
|
import me.ByteEdit.main.Main;
|
||||||
@@ -20,11 +19,6 @@ public class UnicodeBox extends JFrame {
|
|||||||
private JPanel contentPane;
|
private JPanel contentPane;
|
||||||
|
|
||||||
public UnicodeBox() {
|
public UnicodeBox() {
|
||||||
try {
|
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
setResizable(false);
|
setResizable(false);
|
||||||
setTitle("Unicode Converter");
|
setTitle("Unicode Converter");
|
||||||
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
|
||||||
@@ -42,7 +36,7 @@ public class UnicodeBox extends JFrame {
|
|||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
textArea.setText(UnicodeUtils.escape(textArea.getText()));
|
textArea.setText(UnicodeUtils.escape(null, textArea.getText(), true));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
Main.showError(ex.getMessage());
|
Main.showError(ex.getMessage());
|
||||||
}
|
}
|
||||||
@@ -56,7 +50,7 @@ public class UnicodeBox extends JFrame {
|
|||||||
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
try {
|
try {
|
||||||
textArea.setText(UnicodeUtils.unescape(textArea.getText()));
|
textArea.setText(UnicodeUtils.unescape(null, textArea.getText(), true));
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
Main.showError(ex.getMessage());
|
Main.showError(ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
+247
-221
@@ -1,5 +1,6 @@
|
|||||||
package me.ByteEdit.edit;
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -9,6 +10,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
|
|
||||||
@@ -51,30 +53,47 @@ import me.ByteEdit.utils.UnicodeUtils;
|
|||||||
|
|
||||||
public class Assembler {
|
public class Assembler {
|
||||||
|
|
||||||
|
public static final Pattern SPACE = Pattern.compile(" ");
|
||||||
|
|
||||||
public static ClassNode assemble(String input) {
|
public static ClassNode assemble(String input) {
|
||||||
Main.txtByteEditView.removeAllLineHighlights();
|
Main.txtByteEditView.removeAllLineHighlights();
|
||||||
CustomBufferedReader read = null;
|
CustomBufferedReader read = null;
|
||||||
try {
|
try {
|
||||||
ClassNode clazz = new ClassNode();
|
ClassNode clazz = new ClassNode();
|
||||||
|
HugeStringsRev hsr = new HugeStringsRev();
|
||||||
|
try (BufferedReader reader = new BufferedReader(new StringReader(input))) {
|
||||||
|
String s;
|
||||||
|
while (!(s = reader.readLine()).startsWith("// #SourceFile: ")) {
|
||||||
|
}
|
||||||
|
while (!(s = reader.readLine()).equals("// #Fields")) {
|
||||||
|
if (s.startsWith("#")) {
|
||||||
|
String[] split = SPACE.split(s, 2);
|
||||||
|
hsr.add(Integer.parseInt(split[0].substring(1, split[0].length() - 1)),
|
||||||
|
UnicodeUtils.unescape(null, split[1], true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
read = new CustomBufferedReader(new StringReader(input));
|
read = new CustomBufferedReader(new StringReader(input));
|
||||||
String s;
|
String s;
|
||||||
while (!(s = read.readLine()).startsWith("// #Class v:")) {
|
while (!(s = read.readLine()).startsWith("// #Class v:")) {
|
||||||
if (clazz.visibleAnnotations == null) {
|
if (clazz.visibleAnnotations == null) {
|
||||||
clazz.visibleAnnotations = new ArrayList<>();
|
clazz.visibleAnnotations = new ArrayList<>();
|
||||||
}
|
}
|
||||||
clazz.visibleAnnotations.add(parseAnnotation(s));
|
clazz.visibleAnnotations.add(parseAnnotation(hsr, s));
|
||||||
}
|
}
|
||||||
clazz.version = Integer.parseInt(s.substring(12));
|
clazz.version = Integer.parseInt(s.substring(12));
|
||||||
while ((s = read.readLine()).startsWith("// ")) {
|
while ((s = read.readLine()).startsWith("// ")) {
|
||||||
if (s.startsWith("// #Signature: ")) {
|
if (s.startsWith("// #Signature: ")) {
|
||||||
clazz.signature = s.substring(15).equals("null") ? null : UnicodeUtils.unescape(s.substring(15));
|
clazz.signature = s.substring(15).equals("null") ? null
|
||||||
|
: UnicodeUtils.unescape(hsr, s.substring(15));
|
||||||
} else if (s.startsWith("// #OuterClass: ")) {
|
} else if (s.startsWith("// #OuterClass: ")) {
|
||||||
clazz.outerClass = s.substring(16).equals("null") ? null : UnicodeUtils.unescape(s.substring(16));
|
clazz.outerClass = s.substring(16).equals("null") ? null
|
||||||
|
: UnicodeUtils.unescape(hsr, s.substring(16));
|
||||||
} else if (s.startsWith("// #OuterMethod: ")) {
|
} else if (s.startsWith("// #OuterMethod: ")) {
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
if (split.length > 3) {
|
if (split.length > 3) {
|
||||||
clazz.outerMethod = UnicodeUtils.unescape(split[2]);
|
clazz.outerMethod = UnicodeUtils.unescape(hsr, split[2]);
|
||||||
clazz.outerMethodDesc = UnicodeUtils.unescape(split[3]);
|
clazz.outerMethodDesc = UnicodeUtils.unescape(hsr, split[3]);
|
||||||
}
|
}
|
||||||
} else if (s.equals("// #InnerClasses:")) {
|
} else if (s.equals("// #InnerClasses:")) {
|
||||||
clazz.innerClasses = new ArrayList<>();
|
clazz.innerClasses = new ArrayList<>();
|
||||||
@@ -137,9 +156,9 @@ public class Assembler {
|
|||||||
access ^= ClassUtil.ACC_MANDATED;
|
access ^= ClassUtil.ACC_MANDATED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clazz.innerClasses.add(new InnerClassNode(UnicodeUtils.unescape(split[1]),
|
clazz.innerClasses.add(new InnerClassNode(UnicodeUtils.unescape(hsr, split[1]),
|
||||||
split[2].equals("null") ? null : UnicodeUtils.unescape(split[2]),
|
split[2].equals("null") ? null : UnicodeUtils.unescape(hsr, split[2]),
|
||||||
split[3].equals("null") ? null : UnicodeUtils.unescape(split[3]), access));
|
split[3].equals("null") ? null : UnicodeUtils.unescape(hsr, split[3]), access));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -148,14 +167,14 @@ public class Assembler {
|
|||||||
String interfaces = s.substring(s.lastIndexOf(" implements ") + 12);
|
String interfaces = s.substring(s.lastIndexOf(" implements ") + 12);
|
||||||
clazz.interfaces = new ArrayList<>();
|
clazz.interfaces = new ArrayList<>();
|
||||||
for (String interf : interfaces.split(", ")) {
|
for (String interf : interfaces.split(", ")) {
|
||||||
clazz.interfaces.add(UnicodeUtils.unescape(interf));
|
clazz.interfaces.add(UnicodeUtils.unescape(hsr, interf));
|
||||||
}
|
}
|
||||||
s = s.substring(0, s.lastIndexOf(" implements "));
|
s = s.substring(0, s.lastIndexOf(" implements "));
|
||||||
}
|
}
|
||||||
clazz.superName = UnicodeUtils.unescape(s.substring(s.lastIndexOf(" extends ") + 9));
|
clazz.superName = UnicodeUtils.unescape(hsr, s.substring(s.lastIndexOf(" extends ") + 9));
|
||||||
s = s.substring(0, s.lastIndexOf(" extends "));
|
s = s.substring(0, s.lastIndexOf(" extends "));
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
clazz.name = UnicodeUtils.unescape(split[split.length - 1]);
|
clazz.name = UnicodeUtils.unescape(hsr, split[split.length - 1]);
|
||||||
clazz.access = ClassUtil.ACC_SUPER;
|
clazz.access = ClassUtil.ACC_SUPER;
|
||||||
switch (split[split.length - 2]) {
|
switch (split[split.length - 2]) {
|
||||||
case "class":
|
case "class":
|
||||||
@@ -192,7 +211,7 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
s = read.readLine();
|
s = read.readLine();
|
||||||
clazz.sourceFile = s.substring(16).equals("null") ? null : UnicodeUtils.unescape(s.substring(16));
|
clazz.sourceFile = s.substring(16).equals("null") ? null : UnicodeUtils.unescape(hsr, s.substring(16));
|
||||||
while (!(s = read.readLine()).equals("// #Fields")) {
|
while (!(s = read.readLine()).equals("// #Fields")) {
|
||||||
}
|
}
|
||||||
clazz.fields = new ArrayList<>();
|
clazz.fields = new ArrayList<>();
|
||||||
@@ -207,7 +226,7 @@ public class Assembler {
|
|||||||
annotationsForNext.add(s);
|
annotationsForNext.add(s);
|
||||||
} else {
|
} else {
|
||||||
if (s.startsWith("// #Signature: ")) {
|
if (s.startsWith("// #Signature: ")) {
|
||||||
signature = UnicodeUtils.unescape(s.substring(15));
|
signature = UnicodeUtils.unescape(hsr, s.substring(15));
|
||||||
} else {
|
} else {
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
boolean hasValue = false;
|
boolean hasValue = false;
|
||||||
@@ -218,9 +237,9 @@ public class Assembler {
|
|||||||
if (hasValue) {
|
if (hasValue) {
|
||||||
split = s.substring(0, s.indexOf(" = ")).split(" ");
|
split = s.substring(0, s.indexOf(" = ")).split(" ");
|
||||||
}
|
}
|
||||||
String name = UnicodeUtils.unescape(split[split.length - 1]);
|
String name = UnicodeUtils.unescape(hsr, split[split.length - 1]);
|
||||||
String desc = UnicodeUtils.unescape(split[split.length - 2]);
|
String desc = UnicodeUtils.unescape(hsr, split[split.length - 2]);
|
||||||
value = getValue((String) value, desc);
|
value = getValue(hsr, (String) value, desc);
|
||||||
int access = 0;
|
int access = 0;
|
||||||
if (split.length > 2) {
|
if (split.length > 2) {
|
||||||
String cons = consolidateStrings(split, 0, split.length - 2);
|
String cons = consolidateStrings(split, 0, split.length - 2);
|
||||||
@@ -283,7 +302,7 @@ public class Assembler {
|
|||||||
node.visibleAnnotations = new ArrayList<>();
|
node.visibleAnnotations = new ArrayList<>();
|
||||||
}
|
}
|
||||||
for (String anno : annotationsForNext) {
|
for (String anno : annotationsForNext) {
|
||||||
node.visibleAnnotations.add(parseAnnotation(anno));
|
node.visibleAnnotations.add(parseAnnotation(hsr, anno));
|
||||||
}
|
}
|
||||||
annotationsForNext.clear();
|
annotationsForNext.clear();
|
||||||
}
|
}
|
||||||
@@ -292,7 +311,7 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HashMap<Label, Integer> methodLabelMap = new HashMap<Label, Integer>();
|
HashMap<LabelNode, Integer> methodLabelMap = new HashMap<LabelNode, Integer>();
|
||||||
annotationsForNext.clear();
|
annotationsForNext.clear();
|
||||||
MethodNode node = null;
|
MethodNode node = null;
|
||||||
String temp = "";
|
String temp = "";
|
||||||
@@ -319,7 +338,7 @@ public class Assembler {
|
|||||||
tryCatchBlocksToParse.clear();
|
tryCatchBlocksToParse.clear();
|
||||||
stage = 0;
|
stage = 0;
|
||||||
} else if (s.startsWith("// #Signature: ")) {
|
} else if (s.startsWith("// #Signature: ")) {
|
||||||
node.signature = UnicodeUtils.unescape(s.substring(15));
|
node.signature = UnicodeUtils.unescape(hsr, s.substring(15));
|
||||||
} else if (s.equals("// #TryCatch:")) {
|
} else if (s.equals("// #TryCatch:")) {
|
||||||
stage = 1;
|
stage = 1;
|
||||||
} else if (s.equals("// #LocalVars:")) {
|
} else if (s.equals("// #LocalVars:")) {
|
||||||
@@ -337,7 +356,7 @@ public class Assembler {
|
|||||||
node.visibleAnnotations = new ArrayList<>();
|
node.visibleAnnotations = new ArrayList<>();
|
||||||
}
|
}
|
||||||
for (String anno : annotationsForNext) {
|
for (String anno : annotationsForNext) {
|
||||||
node.visibleAnnotations.add(parseAnnotation(anno));
|
node.visibleAnnotations.add(parseAnnotation(hsr, anno));
|
||||||
}
|
}
|
||||||
annotationsForNext.clear();
|
annotationsForNext.clear();
|
||||||
}
|
}
|
||||||
@@ -345,20 +364,20 @@ public class Assembler {
|
|||||||
String[] sp = st.split(":");
|
String[] sp = st.split(":");
|
||||||
int start = Integer.parseInt(sp[3].substring(0, sp[3].length() - 2));
|
int start = Integer.parseInt(sp[3].substring(0, sp[3].length() - 2));
|
||||||
int end = Integer.parseInt(sp[4].substring(0, sp[4].length() - 4));
|
int end = Integer.parseInt(sp[4].substring(0, sp[4].length() - 4));
|
||||||
String signat = sp[5].equals("null") ? null : UnicodeUtils.unescape(sp[5]);
|
String signat = sp[5].equals("null") ? null : UnicodeUtils.unescape(hsr, sp[5]);
|
||||||
LabelNode _start = null;
|
LabelNode _start = null;
|
||||||
LabelNode _end = null;
|
LabelNode _end = null;
|
||||||
for (Entry<Label, Integer> entry : methodLabelMap.entrySet()) {
|
for (Entry<LabelNode, Integer> entry : methodLabelMap.entrySet()) {
|
||||||
if (entry.getValue() == start) {
|
if (entry.getValue().intValue() == start) {
|
||||||
_start = new LabelNode(entry.getKey());
|
_start = entry.getKey();
|
||||||
}
|
}
|
||||||
if (entry.getValue() == end) {
|
if (entry.getValue().intValue() == end) {
|
||||||
_end = new LabelNode(entry.getKey());
|
_end = entry.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.localVariables.add(new LocalVariableNode(UnicodeUtils.unescape(sp[0]),
|
node.localVariables.add(new LocalVariableNode(UnicodeUtils.unescape(hsr, sp[0]),
|
||||||
UnicodeUtils.unescape(sp[1].substring(1, sp[1].length() - 2)), signat, _start, _end,
|
UnicodeUtils.unescape(hsr, sp[1].substring(1, sp[1].length() - 2)), signat, _start,
|
||||||
Integer.parseInt(sp[2].substring(0, sp[2].length() - 2))));
|
_end, Integer.parseInt(sp[2].substring(0, sp[2].length() - 2))));
|
||||||
}
|
}
|
||||||
for (String st : tryCatchBlocksToParse) {
|
for (String st : tryCatchBlocksToParse) {
|
||||||
String[] sp = st.split(" ");
|
String[] sp = st.split(" ");
|
||||||
@@ -368,19 +387,19 @@ public class Assembler {
|
|||||||
LabelNode _start = null;
|
LabelNode _start = null;
|
||||||
LabelNode _end = null;
|
LabelNode _end = null;
|
||||||
LabelNode _handler = null;
|
LabelNode _handler = null;
|
||||||
for (Entry<Label, Integer> entry : methodLabelMap.entrySet()) {
|
for (Entry<LabelNode, Integer> entry : methodLabelMap.entrySet()) {
|
||||||
if (entry.getValue() == start) {
|
if (entry.getValue().intValue() == start) {
|
||||||
_start = new LabelNode(entry.getKey());
|
_start = entry.getKey();
|
||||||
}
|
}
|
||||||
if (entry.getValue() == end) {
|
if (entry.getValue().intValue() == end) {
|
||||||
_end = new LabelNode(entry.getKey());
|
_end = entry.getKey();
|
||||||
}
|
}
|
||||||
if (entry.getValue() == handler) {
|
if (entry.getValue().intValue() == handler) {
|
||||||
_handler = new LabelNode(entry.getKey());
|
_handler = entry.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.tryCatchBlocks.add(new TryCatchBlockNode(_start, _end, _handler,
|
node.tryCatchBlocks.add(new TryCatchBlockNode(_start, _end, _handler,
|
||||||
sp[0].equals("null") ? null : UnicodeUtils.unescape(sp[0])));
|
sp[0].equals("null") ? null : UnicodeUtils.unescape(hsr, sp[0])));
|
||||||
}
|
}
|
||||||
clazz.methods.add(node);
|
clazz.methods.add(node);
|
||||||
} else if (!s.startsWith("\t")) {
|
} else if (!s.startsWith("\t")) {
|
||||||
@@ -388,13 +407,13 @@ public class Assembler {
|
|||||||
if (s.contains(" throws ")) {
|
if (s.contains(" throws ")) {
|
||||||
String exceptions = s.substring(s.lastIndexOf(" throws ") + 8);
|
String exceptions = s.substring(s.lastIndexOf(" throws ") + 8);
|
||||||
for (String excp : exceptions.split(", ")) {
|
for (String excp : exceptions.split(", ")) {
|
||||||
node.exceptions.add(UnicodeUtils.unescape(excp));
|
node.exceptions.add(UnicodeUtils.unescape(hsr, excp));
|
||||||
}
|
}
|
||||||
s = s.substring(0, s.lastIndexOf(" throws "));
|
s = s.substring(0, s.lastIndexOf(" throws "));
|
||||||
}
|
}
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
node.desc = UnicodeUtils.unescape(split[split.length - 1]);
|
node.desc = UnicodeUtils.unescape(hsr, split[split.length - 1]);
|
||||||
node.name = UnicodeUtils.unescape(split[split.length - 2]);
|
node.name = UnicodeUtils.unescape(hsr, split[split.length - 2]);
|
||||||
int access = 0;
|
int access = 0;
|
||||||
if (split.length > 2) {
|
if (split.length > 2) {
|
||||||
String cons = consolidateStrings(split, 0, split.length - 2);
|
String cons = consolidateStrings(split, 0, split.length - 2);
|
||||||
@@ -458,7 +477,7 @@ public class Assembler {
|
|||||||
if (!temp.isEmpty()) {
|
if (!temp.isEmpty()) {
|
||||||
if (s.equals("]")) {
|
if (s.equals("]")) {
|
||||||
temp += s;
|
temp += s;
|
||||||
node.instructions.add(getNode(temp, methodLabelMap));
|
node.instructions.add(getNode(hsr, temp, methodLabelMap));
|
||||||
temp = "";
|
temp = "";
|
||||||
} else {
|
} else {
|
||||||
temp += s + "\n";
|
temp += s + "\n";
|
||||||
@@ -467,7 +486,7 @@ public class Assembler {
|
|||||||
if (s.endsWith("[")) {
|
if (s.endsWith("[")) {
|
||||||
temp += s + "\n";
|
temp += s + "\n";
|
||||||
} else {
|
} else {
|
||||||
node.instructions.add(getNode(s, methodLabelMap));
|
node.instructions.add(getNode(hsr, s, methodLabelMap));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -496,31 +515,37 @@ public class Assembler {
|
|||||||
ArrayList<String> ret = new ArrayList<>();
|
ArrayList<String> ret = new ArrayList<>();
|
||||||
String[] split = s.split(", ");
|
String[] split = s.split(", ");
|
||||||
String building = null;
|
String building = null;
|
||||||
|
boolean inString = false;
|
||||||
|
|
||||||
for (int i = 0; i < split.length; i++) {
|
for (int i = 0; i < split.length; i++) {
|
||||||
if (split[i].startsWith("(")) {
|
if (split[i].startsWith("(")) {
|
||||||
ret.add(split[i]);
|
ret.add(split[i]);
|
||||||
} else if (split[i].endsWith("\"")) {
|
} else if (split[i].startsWith("\"") && split[i].endsWith("\"")) {
|
||||||
|
ret.add(split[i]);
|
||||||
|
} else if (split[i].endsWith("\"") && inString) {
|
||||||
if (building == null)
|
if (building == null)
|
||||||
ret.add(split[i]);
|
ret.add(split[i]);
|
||||||
else
|
else
|
||||||
ret.add(building + ", " + split[i]);
|
ret.add(building + ", " + split[i]);
|
||||||
building = null;
|
building = null;
|
||||||
} else {
|
} else if (inString || split[i].startsWith("\"")) {
|
||||||
|
inString = true;
|
||||||
if (building == null)
|
if (building == null)
|
||||||
building = split[i];
|
building = split[i];
|
||||||
else
|
else
|
||||||
building += ", " + split[i];
|
building += ", " + split[i];
|
||||||
|
} else {
|
||||||
|
ret.add(split[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret.toArray(new String[0]);
|
return ret.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnnotationNode parseAnnotation(String s) {
|
private static AnnotationNode parseAnnotation(HugeStringsRev hsr, String s) {
|
||||||
s = s.substring(1);
|
s = s.substring(1);
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
AnnotationNode node = new AnnotationNode(UnicodeUtils.unescape(split[0]));
|
AnnotationNode node = new AnnotationNode(UnicodeUtils.unescape(hsr, split[0]));
|
||||||
if (split.length > 1) {
|
if (split.length > 1) {
|
||||||
if (node.values == null) {
|
if (node.values == null) {
|
||||||
node.values = new ArrayList<>();
|
node.values = new ArrayList<>();
|
||||||
@@ -538,7 +563,7 @@ public class Assembler {
|
|||||||
String split3[] = splitWithStrings(value.substring(2, value.length() - 2));
|
String split3[] = splitWithStrings(value.substring(2, value.length() - 2));
|
||||||
List<Object> list = new ArrayList<>();
|
List<Object> list = new ArrayList<>();
|
||||||
for (String rofl : split3) {
|
for (String rofl : split3) {
|
||||||
rofl = UnicodeUtils.unescape(rofl);
|
rofl = UnicodeUtils.unescape(hsr, rofl);
|
||||||
if (rofl.startsWith("\"")) {
|
if (rofl.startsWith("\"")) {
|
||||||
int index = rofl.lastIndexOf("\"");
|
int index = rofl.lastIndexOf("\"");
|
||||||
list.add(rofl.substring(1, index));
|
list.add(rofl.substring(1, index));
|
||||||
@@ -552,7 +577,7 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
node.values.add(list);
|
node.values.add(list);
|
||||||
} else {
|
} else {
|
||||||
value = UnicodeUtils.unescape(value);
|
value = UnicodeUtils.unescape(hsr, value);
|
||||||
if (value.startsWith("\"")) {
|
if (value.startsWith("\"")) {
|
||||||
int index = value.lastIndexOf("\"");
|
int index = value.lastIndexOf("\"");
|
||||||
node.values.add(value.substring(1, index));
|
node.values.add(value.substring(1, index));
|
||||||
@@ -596,7 +621,7 @@ public class Assembler {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object getValue(String s, String to) {
|
private static Object getValue(HugeStringsRev hsr, String s, String to) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -618,35 +643,36 @@ public class Assembler {
|
|||||||
case "S":
|
case "S":
|
||||||
return Short.parseShort(s);
|
return Short.parseShort(s);
|
||||||
case "Ljava/lang/String;":
|
case "Ljava/lang/String;":
|
||||||
return UnicodeUtils.unescape(s.substring(1, s.length() - 1));
|
return UnicodeUtils.unescape(hsr, s.substring(1, s.length() - 1));
|
||||||
default: {
|
default: {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AbstractInsnNode getNode(String s, HashMap<Label, Integer> labels) throws Exception {
|
private static AbstractInsnNode getNode(HugeStringsRev hsr, String s, HashMap<LabelNode, Integer> labels)
|
||||||
|
throws Exception {
|
||||||
if (s.startsWith("// label ")) {
|
if (s.startsWith("// label ")) {
|
||||||
int labelNr = Integer.parseInt(s.substring(9));
|
int labelNr = Integer.parseInt(s.substring(9));
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new LabelNode(entry.getKey());
|
return entry.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new LabelNode(l);
|
return ln;
|
||||||
} else if (s.startsWith("// line ")) {
|
} else if (s.startsWith("// line ")) {
|
||||||
s = s.substring(8);
|
s = s.substring(8);
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), new LabelNode(entry.getKey()));
|
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), new LabelNode(l));
|
return new LineNumberNode(Integer.parseInt(s.split(" ")[0]), ln);
|
||||||
} else if (s.startsWith("// frame ")) {
|
} else if (s.startsWith("// frame ")) {
|
||||||
String str1 = s.substring(7);
|
String str1 = s.substring(7);
|
||||||
String str = str1.substring(str1.indexOf(' ', 3) + 1);
|
String str = str1.substring(str1.indexOf(' ', 3) + 1);
|
||||||
@@ -665,25 +691,22 @@ public class Assembler {
|
|||||||
int frameType = ClassUtil.getFrameTypeByName(asd);
|
int frameType = ClassUtil.getFrameTypeByName(asd);
|
||||||
if (frameType != -1)
|
if (frameType != -1)
|
||||||
arr.add(new Integer(frameType));
|
arr.add(new Integer(frameType));
|
||||||
else {
|
else
|
||||||
String frame = UnicodeUtils.unescape(asd);
|
arr.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
|
||||||
frame = frame.substring(1, frame.length() - 1);
|
|
||||||
arr.add(frame);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (asd.startsWith("(label) ")) {
|
if (asd.startsWith("(label) ")) {
|
||||||
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
arr.add(new LabelNode(entry.getKey()));
|
arr.add(entry.getKey());
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
Label lb = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(lb, labelNr);
|
labels.put(ln, labelNr);
|
||||||
arr.add(new LabelNode(lb));
|
arr.add(ln);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
||||||
@@ -711,25 +734,22 @@ public class Assembler {
|
|||||||
int frameType = ClassUtil.getFrameTypeByName(asd);
|
int frameType = ClassUtil.getFrameTypeByName(asd);
|
||||||
if (frameType != -1)
|
if (frameType != -1)
|
||||||
arr.add(new Integer(frameType));
|
arr.add(new Integer(frameType));
|
||||||
else {
|
else
|
||||||
String frame = UnicodeUtils.unescape(asd);
|
arr.add(UnicodeUtils.unescape(hsr, asd.substring(1, asd.length() - 1)));
|
||||||
frame = frame.substring(1, frame.length() - 1);
|
|
||||||
arr.add(frame);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (asd.startsWith("(label) ")) {
|
if (asd.startsWith("(label) ")) {
|
||||||
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
int labelNr = Integer.parseInt(asd.split(" ")[1]);
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
arr.add(new LabelNode(entry.getKey()));
|
arr.add(entry.getKey());
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
arr.add(new LabelNode(l));
|
arr.add(ln);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
arr.add(ClassUtil.getCastedValue(asd.split(" ")[1], asd.split("\\) ")[0].substring(1)));
|
||||||
@@ -818,10 +838,12 @@ public class Assembler {
|
|||||||
String type = split2[0].substring(7);
|
String type = split2[0].substring(7);
|
||||||
// Reflection
|
// Reflection
|
||||||
val = new Type(ClassUtil.getIDFromClassNameForType(type),
|
val = new Type(ClassUtil.getIDFromClassNameForType(type),
|
||||||
UnicodeUtils.unescape(split2[3].substring(6, split2[3].length() - 1)),
|
UnicodeUtils.unescape(hsr, split2[3].substring(6, split2[3].length() - 1)),
|
||||||
Integer.parseInt(split2[1].substring(7)), Integer.parseInt(split2[2].substring(5)));
|
Integer.parseInt(split2[1].substring(7)), Integer.parseInt(split2[2].substring(5)));
|
||||||
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
} else if (str.startsWith("\"") && str.endsWith("\"")) {
|
||||||
val = UnicodeUtils.unescape(str.substring(1, str.length() - 1));
|
val = UnicodeUtils.unescape(hsr, str.substring(1, str.length() - 1), true);
|
||||||
|
} else if (str.startsWith("#")) {
|
||||||
|
val = UnicodeUtils.unescape(hsr, str);
|
||||||
} else if (str.endsWith("l")) {
|
} else if (str.endsWith("l")) {
|
||||||
val = Long.parseLong(str.substring(0, str.length() - 1));
|
val = Long.parseLong(str.substring(0, str.length() - 1));
|
||||||
} else if (str.endsWith("f")) {
|
} else if (str.endsWith("f")) {
|
||||||
@@ -1115,179 +1137,179 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
case "ifeq": {
|
case "ifeq": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(153, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(153, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(153, new LabelNode(l));
|
return new JumpInsnNode(153, ln);
|
||||||
}
|
}
|
||||||
case "ifne": {
|
case "ifne": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(154, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(154, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(154, new LabelNode(l));
|
return new JumpInsnNode(154, ln);
|
||||||
}
|
}
|
||||||
case "iflt": {
|
case "iflt": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(155, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(155, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(155, new LabelNode(l));
|
return new JumpInsnNode(155, ln);
|
||||||
}
|
}
|
||||||
case "ifge": {
|
case "ifge": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(156, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(156, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(156, new LabelNode(l));
|
return new JumpInsnNode(156, ln);
|
||||||
}
|
}
|
||||||
case "ifgt": {
|
case "ifgt": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(157, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(157, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(157, new LabelNode(l));
|
return new JumpInsnNode(157, ln);
|
||||||
}
|
}
|
||||||
case "ifle": {
|
case "ifle": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(158, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(158, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(158, new LabelNode(l));
|
return new JumpInsnNode(158, ln);
|
||||||
}
|
}
|
||||||
case "if_icmpeq": {
|
case "if_icmpeq": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(159, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(159, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(159, new LabelNode(l));
|
return new JumpInsnNode(159, ln);
|
||||||
}
|
}
|
||||||
case "if_icmpne": {
|
case "if_icmpne": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(160, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(160, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(160, new LabelNode(l));
|
return new JumpInsnNode(160, ln);
|
||||||
}
|
}
|
||||||
case "if_icmplt": {
|
case "if_icmplt": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(161, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(161, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(161, new LabelNode(l));
|
return new JumpInsnNode(161, ln);
|
||||||
}
|
}
|
||||||
case "if_icmpge": {
|
case "if_icmpge": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(162, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(162, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(162, new LabelNode(l));
|
return new JumpInsnNode(162, ln);
|
||||||
}
|
}
|
||||||
case "if_icmpgt": {
|
case "if_icmpgt": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(163, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(163, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(163, new LabelNode(l));
|
return new JumpInsnNode(163, ln);
|
||||||
}
|
}
|
||||||
case "if_icmple": {
|
case "if_icmple": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(164, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(164, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(164, new LabelNode(l));
|
return new JumpInsnNode(164, ln);
|
||||||
}
|
}
|
||||||
case "if_acmpeq": {
|
case "if_acmpeq": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(165, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(165, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(165, new LabelNode(l));
|
return new JumpInsnNode(165, ln);
|
||||||
}
|
}
|
||||||
case "if_acmpne": {
|
case "if_acmpne": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(166, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(166, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(166, new LabelNode(l));
|
return new JumpInsnNode(166, ln);
|
||||||
}
|
}
|
||||||
case "goto": {
|
case "goto": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(167, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(167, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(167, new LabelNode(l));
|
return new JumpInsnNode(167, ln);
|
||||||
}
|
}
|
||||||
case "jsr": {
|
case "jsr": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(168, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(168, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(168, new LabelNode(l));
|
return new JumpInsnNode(168, ln);
|
||||||
}
|
}
|
||||||
case "ret": {
|
case "ret": {
|
||||||
return new VarInsnNode(169, Integer.parseInt(s.split(" ")[1]));
|
return new VarInsnNode(169, Integer.parseInt(s.split(" ")[1]));
|
||||||
@@ -1307,9 +1329,9 @@ public class Assembler {
|
|||||||
LabelNode dflt = null;
|
LabelNode dflt = null;
|
||||||
if (!split2[2].substring(9).equals("null")) {
|
if (!split2[2].substring(9).equals("null")) {
|
||||||
int dfltLabelNr = Integer.parseInt(split2[2].substring(9));
|
int dfltLabelNr = Integer.parseInt(split2[2].substring(9));
|
||||||
for (Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == dfltLabelNr) {
|
if (entry.getValue() == dfltLabelNr) {
|
||||||
dflt = new LabelNode(entry.getKey());
|
dflt = entry.getKey();
|
||||||
labelIDs.put(BigInteger.valueOf(dfltLabelNr), dflt);
|
labelIDs.put(BigInteger.valueOf(dfltLabelNr), dflt);
|
||||||
}
|
}
|
||||||
labelMap.replaceAll(new BiFunction<SwitchIntContainer, LabelNode, LabelNode>() {
|
labelMap.replaceAll(new BiFunction<SwitchIntContainer, LabelNode, LabelNode>() {
|
||||||
@@ -1317,7 +1339,7 @@ public class Assembler {
|
|||||||
@Override
|
@Override
|
||||||
public LabelNode apply(SwitchIntContainer t, LabelNode u) {
|
public LabelNode apply(SwitchIntContainer t, LabelNode u) {
|
||||||
if (entry.getValue().intValue() == t.getId()) {
|
if (entry.getValue().intValue() == t.getId()) {
|
||||||
return new LabelNode(entry.getKey());
|
return entry.getKey();
|
||||||
}
|
}
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
@@ -1325,9 +1347,9 @@ public class Assembler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (dflt == null) {
|
if (dflt == null) {
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, dfltLabelNr);
|
labels.put(ln, dfltLabelNr);
|
||||||
dflt = new LabelNode(l);
|
dflt = ln;
|
||||||
labelIDs.put(BigInteger.valueOf(dfltLabelNr), dflt);
|
labelIDs.put(BigInteger.valueOf(dfltLabelNr), dflt);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1338,9 +1360,8 @@ public class Assembler {
|
|||||||
for (Entry<SwitchIntContainer, LabelNode> entry : labelMap.entrySet()) {
|
for (Entry<SwitchIntContainer, LabelNode> entry : labelMap.entrySet()) {
|
||||||
LabelNode ln;
|
LabelNode ln;
|
||||||
if (((ln = labelIDs.get(BigInteger.valueOf(entry.getKey().getId()))) == null)) {
|
if (((ln = labelIDs.get(BigInteger.valueOf(entry.getKey().getId()))) == null)) {
|
||||||
Label l = new Label();
|
ln = new LabelNode(new Label());
|
||||||
labels.put(l, entry.getKey().getId());
|
labels.put(ln, entry.getKey().getId());
|
||||||
ln = new LabelNode(l);
|
|
||||||
labelIDs.put(BigInteger.valueOf(entry.getKey().getId()), ln);
|
labelIDs.put(BigInteger.valueOf(entry.getKey().getId()), ln);
|
||||||
}
|
}
|
||||||
arr[counter] = ln;
|
arr[counter] = ln;
|
||||||
@@ -1374,9 +1395,9 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
LabelNode dflt = null;
|
LabelNode dflt = null;
|
||||||
int labelNr = Integer.parseInt(split2[0].substring(9));
|
int labelNr = Integer.parseInt(split2[0].substring(9));
|
||||||
for (Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
dflt = new LabelNode(entry.getKey());
|
dflt = entry.getKey();
|
||||||
labelIDs.put(BigInteger.valueOf(labelNr), dflt);
|
labelIDs.put(BigInteger.valueOf(labelNr), dflt);
|
||||||
}
|
}
|
||||||
labelMap.replaceAll(new BiFunction<SwitchIntContainer, LabelNode, LabelNode>() {
|
labelMap.replaceAll(new BiFunction<SwitchIntContainer, LabelNode, LabelNode>() {
|
||||||
@@ -1384,7 +1405,7 @@ public class Assembler {
|
|||||||
@Override
|
@Override
|
||||||
public LabelNode apply(SwitchIntContainer t, LabelNode u) {
|
public LabelNode apply(SwitchIntContainer t, LabelNode u) {
|
||||||
if (entry.getValue().intValue() == t.getId()) {
|
if (entry.getValue().intValue() == t.getId()) {
|
||||||
return new LabelNode(entry.getKey());
|
return entry.getKey();
|
||||||
}
|
}
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
@@ -1392,9 +1413,9 @@ public class Assembler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (dflt == null) {
|
if (dflt == null) {
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
dflt = new LabelNode(l);
|
dflt = ln;
|
||||||
labelIDs.put(BigInteger.valueOf(labelNr), dflt);
|
labelIDs.put(BigInteger.valueOf(labelNr), dflt);
|
||||||
}
|
}
|
||||||
LabelNode[] arr = new LabelNode[labelMap.size()];
|
LabelNode[] arr = new LabelNode[labelMap.size()];
|
||||||
@@ -1402,9 +1423,8 @@ public class Assembler {
|
|||||||
for (Entry<SwitchIntContainer, LabelNode> entry : labelMap.entrySet()) {
|
for (Entry<SwitchIntContainer, LabelNode> entry : labelMap.entrySet()) {
|
||||||
LabelNode ln;
|
LabelNode ln;
|
||||||
if (((ln = labelIDs.get(BigInteger.valueOf(entry.getKey().getId()))) == null)) {
|
if (((ln = labelIDs.get(BigInteger.valueOf(entry.getKey().getId()))) == null)) {
|
||||||
Label l = new Label();
|
ln = new LabelNode(new Label());
|
||||||
labels.put(l, entry.getKey().getId());
|
labels.put(ln, entry.getKey().getId());
|
||||||
ln = new LabelNode(l);
|
|
||||||
labelIDs.put(BigInteger.valueOf(entry.getKey().getId()), ln);
|
labelIDs.put(BigInteger.valueOf(entry.getKey().getId()), ln);
|
||||||
}
|
}
|
||||||
arr[counter] = ln;
|
arr[counter] = ln;
|
||||||
@@ -1439,50 +1459,54 @@ public class Assembler {
|
|||||||
case "getstatic": {
|
case "getstatic": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new FieldInsnNode(178, UnicodeUtils.unescape(target.substring(0, index)),
|
return new FieldInsnNode(178, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]));
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "putstatic": {
|
case "putstatic": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new FieldInsnNode(179, UnicodeUtils.unescape(target.substring(0, index)),
|
return new FieldInsnNode(179, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]));
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "getfield": {
|
case "getfield": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new FieldInsnNode(180, UnicodeUtils.unescape(target.substring(0, index)),
|
return new FieldInsnNode(180, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]));
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "putfield": {
|
case "putfield": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new FieldInsnNode(181, UnicodeUtils.unescape(target.substring(0, index)),
|
return new FieldInsnNode(181, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]));
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "invokevirtual": {
|
case "invokevirtual": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new MethodInsnNode(182, UnicodeUtils.unescape(target.substring(0, index)),
|
return new MethodInsnNode(182, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]), false);
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
case "invokespecial": {
|
case "invokespecial": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new MethodInsnNode(183, UnicodeUtils.unescape(target.substring(0, index)),
|
return new MethodInsnNode(183, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]), false);
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
case "invokestatic": {
|
case "invokestatic": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new MethodInsnNode(184, UnicodeUtils.unescape(target.substring(0, index)),
|
return new MethodInsnNode(184, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]), false);
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
case "invokeinterface": {
|
case "invokeinterface": {
|
||||||
String target = split[2];
|
String target = split[2];
|
||||||
int index = target.lastIndexOf("/");
|
int index = target.lastIndexOf("/");
|
||||||
return new MethodInsnNode(185, UnicodeUtils.unescape(target.substring(0, index)),
|
return new MethodInsnNode(185, UnicodeUtils.unescape(hsr, target.substring(0, index)),
|
||||||
UnicodeUtils.unescape(target.substring(index + 1)), UnicodeUtils.unescape(split[1]), true);
|
UnicodeUtils.unescape(hsr, target.substring(index + 1)), UnicodeUtils.unescape(hsr, split[1]),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
case "invokedynamic": {
|
case "invokedynamic": {
|
||||||
String str = s.substring(16, s.length() - 2).replace("", "");
|
String str = s.substring(16, s.length() - 2).replace("", "");
|
||||||
@@ -1497,7 +1521,7 @@ public class Assembler {
|
|||||||
try {
|
try {
|
||||||
// Reflection
|
// Reflection
|
||||||
args.add(new Type(ClassUtil.getIDFromClassNameForType(vals.get(0).substring(6)),
|
args.add(new Type(ClassUtil.getIDFromClassNameForType(vals.get(0).substring(6)),
|
||||||
UnicodeUtils.unescape(vals.get(3).substring(6, vals.get(3).length() - 1)),
|
UnicodeUtils.unescape(hsr, vals.get(3).substring(6, vals.get(3).length() - 1)),
|
||||||
Integer.parseInt(vals.get(1).substring(7)),
|
Integer.parseInt(vals.get(1).substring(7)),
|
||||||
Integer.parseInt(vals.get(2).substring(5))));
|
Integer.parseInt(vals.get(2).substring(5))));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -1505,9 +1529,9 @@ public class Assembler {
|
|||||||
}
|
}
|
||||||
} else if (stage == 2) {
|
} else if (stage == 2) {
|
||||||
args.add(new Handle(OpcodesReverse.getHandleOpcode(vals.get(4).substring(5)),
|
args.add(new Handle(OpcodesReverse.getHandleOpcode(vals.get(4).substring(5)),
|
||||||
UnicodeUtils.unescape(vals.get(1).substring(7)),
|
UnicodeUtils.unescape(hsr, vals.get(1).substring(7)),
|
||||||
UnicodeUtils.unescape(vals.get(0).substring(6)),
|
UnicodeUtils.unescape(hsr, vals.get(0).substring(6)),
|
||||||
UnicodeUtils.unescape(vals.get(2).substring(6)),
|
UnicodeUtils.unescape(hsr, vals.get(2).substring(6)),
|
||||||
Boolean.parseBoolean(vals.get(3).substring(13))));
|
Boolean.parseBoolean(vals.get(3).substring(13))));
|
||||||
vals.clear();
|
vals.clear();
|
||||||
}
|
}
|
||||||
@@ -1525,7 +1549,7 @@ public class Assembler {
|
|||||||
vals.add(st);
|
vals.add(st);
|
||||||
} else if (stage == 0) {
|
} else if (stage == 0) {
|
||||||
if (st.startsWith("\"") && st.endsWith("\"")) {
|
if (st.startsWith("\"") && st.endsWith("\"")) {
|
||||||
args.add(UnicodeUtils.unescape(st.substring(1, st.length() - 1)));
|
args.add(UnicodeUtils.unescape(hsr, st.substring(1, st.length() - 1)));
|
||||||
} else if (st.endsWith("l")) {
|
} else if (st.endsWith("l")) {
|
||||||
args.add(Long.parseLong(st.substring(0, st.length() - 1)));
|
args.add(Long.parseLong(st.substring(0, st.length() - 1)));
|
||||||
} else if (st.endsWith("f")) {
|
} else if (st.endsWith("f")) {
|
||||||
@@ -1543,21 +1567,23 @@ public class Assembler {
|
|||||||
_args[stage] = o;
|
_args[stage] = o;
|
||||||
stage++;
|
stage++;
|
||||||
}
|
}
|
||||||
return new InvokeDynamicInsnNode(UnicodeUtils.unescape(sp[0].substring(7)),
|
return new InvokeDynamicInsnNode(UnicodeUtils.unescape(hsr, sp[0].substring(7)),
|
||||||
UnicodeUtils.unescape(sp[1].substring(6)),
|
UnicodeUtils.unescape(hsr, sp[1].substring(6)),
|
||||||
new Handle(OpcodesReverse.getHandleOpcode(sp[7].substring(6)),
|
new Handle(OpcodesReverse.getHandleOpcode(sp[7].substring(6)),
|
||||||
UnicodeUtils.unescape(sp[4].substring(8)), UnicodeUtils.unescape(sp[3].substring(7)),
|
UnicodeUtils.unescape(hsr, sp[4].substring(8)),
|
||||||
UnicodeUtils.unescape(sp[5].substring(7)), Boolean.parseBoolean(sp[6].substring(14))),
|
UnicodeUtils.unescape(hsr, sp[3].substring(7)),
|
||||||
|
UnicodeUtils.unescape(hsr, sp[5].substring(7)),
|
||||||
|
Boolean.parseBoolean(sp[6].substring(14))),
|
||||||
_args);
|
_args);
|
||||||
}
|
}
|
||||||
case "new": {
|
case "new": {
|
||||||
return new TypeInsnNode(187, UnicodeUtils.unescape(split[1]));
|
return new TypeInsnNode(187, UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "newarray": {
|
case "newarray": {
|
||||||
return new IntInsnNode(188, ClassUtil.getArrayIDByType(split[1]));
|
return new IntInsnNode(188, ClassUtil.getArrayIDByType(split[1]));
|
||||||
}
|
}
|
||||||
case "anewarray": {
|
case "anewarray": {
|
||||||
return new TypeInsnNode(189, UnicodeUtils.unescape(split[1]));
|
return new TypeInsnNode(189, UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "arraylength": {
|
case "arraylength": {
|
||||||
return new InsnNode(190);
|
return new InsnNode(190);
|
||||||
@@ -1566,10 +1592,10 @@ public class Assembler {
|
|||||||
return new InsnNode(191);
|
return new InsnNode(191);
|
||||||
}
|
}
|
||||||
case "checkcast": {
|
case "checkcast": {
|
||||||
return new TypeInsnNode(192, UnicodeUtils.unescape(split[1]));
|
return new TypeInsnNode(192, UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "instanceof": {
|
case "instanceof": {
|
||||||
return new TypeInsnNode(193, UnicodeUtils.unescape(split[1]));
|
return new TypeInsnNode(193, UnicodeUtils.unescape(hsr, split[1]));
|
||||||
}
|
}
|
||||||
case "monitorenter": {
|
case "monitorenter": {
|
||||||
return new InsnNode(194);
|
return new InsnNode(194);
|
||||||
@@ -1578,29 +1604,29 @@ public class Assembler {
|
|||||||
return new InsnNode(195);
|
return new InsnNode(195);
|
||||||
}
|
}
|
||||||
case "multianewarray": {
|
case "multianewarray": {
|
||||||
return new MultiANewArrayInsnNode(UnicodeUtils.unescape(split[1]), Integer.parseInt(split[2]));
|
return new MultiANewArrayInsnNode(UnicodeUtils.unescape(hsr, split[1]), Integer.parseInt(split[2]));
|
||||||
}
|
}
|
||||||
case "ifnull": {
|
case "ifnull": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(198, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(198, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(198, new LabelNode(l));
|
return new JumpInsnNode(198, ln);
|
||||||
}
|
}
|
||||||
case "ifnonnull": {
|
case "ifnonnull": {
|
||||||
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
int labelNr = Integer.parseInt(s.split(" ")[1]);
|
||||||
for (Map.Entry<Label, Integer> entry : labels.entrySet()) {
|
for (Map.Entry<LabelNode, Integer> entry : labels.entrySet()) {
|
||||||
if (entry.getValue() == labelNr) {
|
if (entry.getValue() == labelNr) {
|
||||||
return new JumpInsnNode(199, new LabelNode(entry.getKey()));
|
return new JumpInsnNode(199, entry.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Label l = new Label();
|
LabelNode ln = new LabelNode(new Label());
|
||||||
labels.put(l, labelNr);
|
labels.put(ln, labelNr);
|
||||||
return new JumpInsnNode(199, new LabelNode(l));
|
return new JumpInsnNode(199, ln);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Illegal Instruction: " + s);
|
throw new IllegalArgumentException("Illegal Instruction: " + s);
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import org.objectweb.asm.Handle;
|
import org.objectweb.asm.Handle;
|
||||||
import org.objectweb.asm.Label;
|
import org.objectweb.asm.Label;
|
||||||
@@ -17,6 +24,7 @@ import org.objectweb.asm.tree.FieldNode;
|
|||||||
import org.objectweb.asm.tree.FrameNode;
|
import org.objectweb.asm.tree.FrameNode;
|
||||||
import org.objectweb.asm.tree.IincInsnNode;
|
import org.objectweb.asm.tree.IincInsnNode;
|
||||||
import org.objectweb.asm.tree.InnerClassNode;
|
import org.objectweb.asm.tree.InnerClassNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
import org.objectweb.asm.tree.InsnNode;
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
import org.objectweb.asm.tree.IntInsnNode;
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
||||||
@@ -34,12 +42,16 @@ import org.objectweb.asm.tree.TryCatchBlockNode;
|
|||||||
import org.objectweb.asm.tree.TypeInsnNode;
|
import org.objectweb.asm.tree.TypeInsnNode;
|
||||||
import org.objectweb.asm.tree.VarInsnNode;
|
import org.objectweb.asm.tree.VarInsnNode;
|
||||||
|
|
||||||
|
import me.ByteEdit.main.Main;
|
||||||
import me.ByteEdit.utils.ClassUtil;
|
import me.ByteEdit.utils.ClassUtil;
|
||||||
import me.ByteEdit.utils.OpcodesReverse;
|
import me.ByteEdit.utils.OpcodesReverse;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
|
|
||||||
public class Disassembler {
|
public class Disassembler {
|
||||||
|
|
||||||
|
private static final ExecutorService exec = Executors
|
||||||
|
.newFixedThreadPool((Runtime.getRuntime().availableProcessors() + 1) / 2);
|
||||||
|
|
||||||
public static String disassemble(ClassNode classNode) {
|
public static String disassemble(ClassNode classNode) {
|
||||||
return disassemble(classNode, null).getDisassembly();
|
return disassemble(classNode, null).getDisassembly();
|
||||||
}
|
}
|
||||||
@@ -74,12 +86,75 @@ public class Disassembler {
|
|||||||
return new DisassembleTuple("ClassNode is null! This is not a valid java class file!");
|
return new DisassembleTuple("ClassNode is null! This is not a valid java class file!");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int lineFound = -1;
|
HugeStrings hs = new HugeStrings();
|
||||||
String s = "";
|
AtomicInteger lineFound = new AtomicInteger(-1);
|
||||||
s += "// #Annotations:\n";
|
StringContext ctx = new StringContext(18);
|
||||||
if (classNode.visibleAnnotations != null && !classNode.visibleAnnotations.isEmpty()) {
|
ctx.next("// #Annotations:\n");
|
||||||
for (AnnotationNode annotationNode : classNode.visibleAnnotations) {
|
ctx.next(doAnnotations(classNode.visibleAnnotations, hs));
|
||||||
s += "@" + UnicodeUtils.escapeWithSpaces(annotationNode.desc);
|
ctx.next("// #Class v:" + classNode.version + "\n");
|
||||||
|
if (classNode.signature != null)
|
||||||
|
ctx.next("// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, classNode.signature) + "\n");
|
||||||
|
if (classNode.outerMethod != null)
|
||||||
|
ctx.next(
|
||||||
|
"// #OuterMethod: "
|
||||||
|
+ (classNode.outerMethod == null ? "null"
|
||||||
|
: (UnicodeUtils.escapeWithSpaces(hs, classNode.outerMethod) + " "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, classNode.outerMethodDesc)))
|
||||||
|
+ "\n");
|
||||||
|
if (classNode.outerClass != null)
|
||||||
|
ctx.next("// #OuterClass: " + UnicodeUtils.escapeWithSpaces(hs, classNode.outerClass) + "\n");
|
||||||
|
ctx.next("// #InnerClasses:\n");
|
||||||
|
if (classNode.innerClasses != null) {
|
||||||
|
String ics = "";
|
||||||
|
for (InnerClassNode icn : classNode.innerClasses) {
|
||||||
|
ics += "// " + UnicodeUtils.escapeWithSpaces(hs, icn.name) + " "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, icn.outerName) + " "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, icn.innerName)
|
||||||
|
+ (icn.access == 0 ? "" : " " + ClassUtil.getAccessFlagsFull(icn.access).trim()) + "\n";
|
||||||
|
}
|
||||||
|
ctx.next(ics);
|
||||||
|
}
|
||||||
|
ctx.next(ClassUtil.getAccessFlagsClass(classNode.access) + UnicodeUtils.escapeWithSpaces(hs, classNode.name)
|
||||||
|
+ " ");
|
||||||
|
ctx.next("extends " + UnicodeUtils.escapeWithSpaces(hs, classNode.superName) + " ");
|
||||||
|
if (classNode.interfaces != null && !classNode.interfaces.isEmpty()) {
|
||||||
|
String interfaceStr = "";
|
||||||
|
for (String interfc : classNode.interfaces) {
|
||||||
|
if (interfaceStr.isEmpty()) {
|
||||||
|
interfaceStr += UnicodeUtils.escapeWithSpaces(hs, interfc);
|
||||||
|
} else {
|
||||||
|
interfaceStr += ", " + UnicodeUtils.escapeWithSpaces(hs, interfc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!interfaceStr.isEmpty())
|
||||||
|
ctx.next("implements " + interfaceStr + " ");
|
||||||
|
}
|
||||||
|
ctx.next("{\n// #SourceFile: "
|
||||||
|
+ (classNode.sourceFile == null ? "null" : UnicodeUtils.escape(hs, classNode.sourceFile)) + "\n");
|
||||||
|
int hugeIdx = ctx.next("");
|
||||||
|
ctx.next("\n// #Fields\n");
|
||||||
|
ctx.next(doFields(classNode.fields, nodeToFind, lineFound, hs));
|
||||||
|
ctx.next("\n// #Methods\n");
|
||||||
|
ctx.next(doMethods(classNode.methods, classNode.name, nodeToFind, lineFound, hs));
|
||||||
|
ctx.next("}\n");
|
||||||
|
|
||||||
|
if (!hs.isEmpty())
|
||||||
|
ctx.set(hugeIdx, hs.makeStringsList());
|
||||||
|
return new DisassembleTuple(ctx.finish(), lineFound.get());
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return new DisassembleTuple("Class couldn't be decompiled:\n" + e.getClass().getName() + ": "
|
||||||
|
+ e.getMessage() + "\n"
|
||||||
|
+ Arrays.toString(e.getStackTrace()).replace(", ", "\n\tat ").replace("[", "\tat ").replace("]", "")
|
||||||
|
+ "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String doAnnotations(List<AnnotationNode> annotations, HugeStrings hs) {
|
||||||
|
if (annotations == null)
|
||||||
|
return "";
|
||||||
|
StringContext ctx = new StringContext(annotations.size());
|
||||||
|
for (AnnotationNode annotationNode : annotations) {
|
||||||
|
String s = "@" + UnicodeUtils.escapeWithSpaces(hs, annotationNode.desc);
|
||||||
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
||||||
s += " (";
|
s += " (";
|
||||||
boolean valBefore = true;
|
boolean valBefore = true;
|
||||||
@@ -94,10 +169,10 @@ public class Disassembler {
|
|||||||
boolean w8ing = false;
|
boolean w8ing = false;
|
||||||
for (String rofl : arr) {
|
for (String rofl : arr) {
|
||||||
if (!w8ing) {
|
if (!w8ing) {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
w8ing = true;
|
w8ing = true;
|
||||||
} else {
|
} else {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "]";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s += ", ";
|
s += ", ";
|
||||||
@@ -110,21 +185,21 @@ public class Disassembler {
|
|||||||
boolean w8ing = false;
|
boolean w8ing = false;
|
||||||
for (String rofl : arr) {
|
for (String rofl : arr) {
|
||||||
if (!w8ing) {
|
if (!w8ing) {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
w8ing = true;
|
w8ing = true;
|
||||||
} else {
|
} else {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl);
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s += "\"" + UnicodeUtils.escape(String.valueOf(obj)) + "\"";
|
s += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj)) + "\"";
|
||||||
}
|
}
|
||||||
s += ", ";
|
s += ", ";
|
||||||
}
|
}
|
||||||
s = s.substring(0, s.length() - 2);
|
s = s.substring(0, s.length() - 2);
|
||||||
s += " }]";
|
s += " }]";
|
||||||
} else if (o instanceof String) {
|
} else if (o instanceof String) {
|
||||||
s += "\"" + UnicodeUtils.escapeWithSpaces((String) o) + "\"], ";
|
s += "\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"], ";
|
||||||
} else {
|
} else {
|
||||||
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
||||||
}
|
}
|
||||||
@@ -136,50 +211,141 @@ public class Disassembler {
|
|||||||
s += ")";
|
s += ")";
|
||||||
}
|
}
|
||||||
s += "\n";
|
s += "\n";
|
||||||
|
ctx.next(s);
|
||||||
}
|
}
|
||||||
|
return ctx.finish();
|
||||||
}
|
}
|
||||||
s += "// #Class v:" + classNode.version + "\n";
|
|
||||||
if (classNode.signature != null)
|
private static String doMethods(List<MethodNode> methods, String className, Object nodeToFind,
|
||||||
s += "// #Signature: " + UnicodeUtils.escapeWithSpaces(classNode.signature) + "\n";
|
AtomicInteger lineFound, HugeStrings hs) throws InterruptedException, ExecutionException {
|
||||||
if (classNode.outerMethod != null)
|
boolean multithreaded = Main.INSTANCE.mntmMultithreaded.isSelected();
|
||||||
s += "// #OuterMethod: " + (classNode.outerMethod == null ? "null"
|
Future<String>[] futures = new Future[methods.size()];
|
||||||
: (UnicodeUtils.escapeWithSpaces(classNode.outerMethod) + " "
|
for (int i = 0; i < futures.length; i++) {
|
||||||
+ UnicodeUtils.escapeWithSpaces(classNode.outerMethodDesc)))
|
MethodNode mn = methods.get(i);
|
||||||
+ "\n";
|
Callable<String> callable = new Callable<String>() {
|
||||||
if (classNode.outerClass != null)
|
@Override
|
||||||
s += "// #OuterClass: " + UnicodeUtils.escapeWithSpaces(classNode.outerClass) + "\n";
|
public String call() throws Exception {
|
||||||
s += "// #InnerClasses:\n";
|
String ms = "";
|
||||||
if (classNode.innerClasses != null) {
|
try {
|
||||||
for (InnerClassNode icn : classNode.innerClasses) {
|
ms += "\t// #Max: l:" + mn.maxLocals + " s:" + mn.maxStack + "\n";
|
||||||
s += "// " + UnicodeUtils.escapeWithSpaces(icn.name) + " "
|
if (mn.signature != null)
|
||||||
+ UnicodeUtils.escapeWithSpaces(icn.outerName) + " "
|
ms += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, mn.signature) + "\n";
|
||||||
+ UnicodeUtils.escapeWithSpaces(icn.innerName)
|
String[] dis = disassembleMethod(className, mn, hs);
|
||||||
+ (icn.access == 0 ? "" : " " + ClassUtil.getAccessFlagsFull(icn.access).trim()) + "\n";
|
ms += dis[2];
|
||||||
}
|
ms += dis[1];
|
||||||
}
|
if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty()) {
|
||||||
s += ClassUtil.getAccessFlagsClass(classNode.access) + UnicodeUtils.escapeWithSpaces(classNode.name) + " ";
|
for (AnnotationNode annotationNode : mn.visibleAnnotations) {
|
||||||
s += "extends " + UnicodeUtils.escapeWithSpaces(classNode.superName) + " ";
|
ms += "\t@" + annotationNode.desc;
|
||||||
if (classNode.interfaces != null && !classNode.interfaces.isEmpty()) {
|
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
||||||
String interfaceStr = "";
|
ms += " (";
|
||||||
for (String interfc : classNode.interfaces) {
|
boolean valBefore = true;
|
||||||
if (interfaceStr.isEmpty()) {
|
for (Object o : annotationNode.values) {
|
||||||
interfaceStr += UnicodeUtils.escapeWithSpaces(interfc);
|
if (valBefore) {
|
||||||
|
ms += o + " = [";
|
||||||
|
valBefore = false;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
interfaceStr += ", " + UnicodeUtils.escapeWithSpaces(interfc);
|
if (o instanceof String[]) {
|
||||||
|
String[] arr = (String[]) o;
|
||||||
|
boolean w8ing = false;
|
||||||
|
for (String rofl : arr) {
|
||||||
|
if (!w8ing) {
|
||||||
|
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
|
w8ing = true;
|
||||||
|
} else {
|
||||||
|
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!interfaceStr.isEmpty())
|
ms += ", ";
|
||||||
s += "implements " + interfaceStr + " ";
|
} else if (o instanceof List) {
|
||||||
|
List list = (List) o;
|
||||||
|
ms += "{ ";
|
||||||
|
for (Object obj : list) {
|
||||||
|
if (obj instanceof String[]) {
|
||||||
|
String[] arr = (String[]) obj;
|
||||||
|
boolean w8ing = false;
|
||||||
|
for (String rofl : arr) {
|
||||||
|
if (!w8ing) {
|
||||||
|
ms += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
|
w8ing = true;
|
||||||
|
} else {
|
||||||
|
ms += UnicodeUtils.escapeWithSpaces(hs, rofl);
|
||||||
}
|
}
|
||||||
s += "{\n// #SourceFile: "
|
}
|
||||||
+ (classNode.sourceFile == null ? "null" : UnicodeUtils.escape(classNode.sourceFile))
|
} else {
|
||||||
+ "\n\n// #Fields\n";
|
ms += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj))
|
||||||
for (FieldNode fn : classNode.fields) {
|
+ "\"";
|
||||||
|
}
|
||||||
|
ms += ", ";
|
||||||
|
}
|
||||||
|
ms = ms.substring(0, ms.length() - 2);
|
||||||
|
ms += " }]";
|
||||||
|
} else {
|
||||||
|
ms += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
||||||
|
}
|
||||||
|
valBefore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ms.endsWith(", "))
|
||||||
|
ms = ms.substring(0, ms.length() - 2);
|
||||||
|
ms += ")";
|
||||||
|
}
|
||||||
|
ms += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mn.equals(nodeToFind)) {
|
||||||
|
lineFound.set(ms.split("\\n").length);
|
||||||
|
}
|
||||||
|
ms += "\t" + ClassUtil.getAccessFlagsFull(mn.access)
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, mn.name) + " "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, mn.desc) + " ";
|
||||||
|
if (mn.exceptions != null && !mn.exceptions.isEmpty()) {
|
||||||
|
String exceptionStr = "";
|
||||||
|
for (String exc : mn.exceptions) {
|
||||||
|
if (exceptionStr.isEmpty()) {
|
||||||
|
exceptionStr += UnicodeUtils.escapeWithSpaces(hs, exc);
|
||||||
|
} else {
|
||||||
|
exceptionStr += ", " + UnicodeUtils.escapeWithSpaces(hs, exc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!exceptionStr.isEmpty())
|
||||||
|
ms += "throws " + exceptionStr + " ";
|
||||||
|
}
|
||||||
|
ms += "{\n";
|
||||||
|
ms += dis[0];
|
||||||
|
ms += "\t}\n\n";
|
||||||
|
} catch (Exception e) {
|
||||||
|
ms += "\t\t// Method couldn't be disassembled:\n\t\t// " + e.getClass().getName() + ": "
|
||||||
|
+ e.getMessage() + "\n" + Arrays.toString(e.getStackTrace())
|
||||||
|
.replace(", ", "\n\t\t// \tat ").replace("[", "\t\t// \tat ").replace("]", "")
|
||||||
|
+ "\n\t}\n\n";
|
||||||
|
}
|
||||||
|
return ms;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
futures[i] = multithreaded ? exec.submit(callable) : new FutureTask<>(callable);
|
||||||
|
}
|
||||||
|
StringContext ctx = new StringContext(futures.length);
|
||||||
|
for (Future<String> f : futures) {
|
||||||
|
if (f instanceof FutureTask)
|
||||||
|
((FutureTask) f).run();
|
||||||
|
ctx.next(f.get());
|
||||||
|
}
|
||||||
|
String s = ctx.finish();
|
||||||
|
if (s.isEmpty())
|
||||||
|
return "\n";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String doFields(List<FieldNode> fields, Object nodeToFind, AtomicInteger lineFound, HugeStrings hs) {
|
||||||
|
StringContext ctx = new StringContext(fields.size());
|
||||||
|
for (FieldNode fn : fields) {
|
||||||
|
String s = "";
|
||||||
if (fn.signature != null)
|
if (fn.signature != null)
|
||||||
s += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(fn.signature) + "\n";
|
s += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(hs, fn.signature) + "\n";
|
||||||
if (fn.visibleAnnotations != null && !fn.visibleAnnotations.isEmpty()) {
|
if (fn.visibleAnnotations != null && !fn.visibleAnnotations.isEmpty()) {
|
||||||
for (AnnotationNode annotationNode : fn.visibleAnnotations) {
|
for (AnnotationNode annotationNode : fn.visibleAnnotations) {
|
||||||
s += "\t@" + UnicodeUtils.escapeWithSpaces(annotationNode.desc);
|
s += "\t@" + UnicodeUtils.escapeWithSpaces(hs, annotationNode.desc);
|
||||||
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
||||||
s += " (";
|
s += " (";
|
||||||
boolean valBefore = true;
|
boolean valBefore = true;
|
||||||
@@ -194,10 +360,10 @@ public class Disassembler {
|
|||||||
boolean w8ing = false;
|
boolean w8ing = false;
|
||||||
for (String rofl : arr) {
|
for (String rofl : arr) {
|
||||||
if (!w8ing) {
|
if (!w8ing) {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
w8ing = true;
|
w8ing = true;
|
||||||
} else {
|
} else {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "]";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s += ", ";
|
s += ", ";
|
||||||
@@ -210,14 +376,14 @@ public class Disassembler {
|
|||||||
boolean w8ing = false;
|
boolean w8ing = false;
|
||||||
for (String rofl : arr) {
|
for (String rofl : arr) {
|
||||||
if (!w8ing) {
|
if (!w8ing) {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl) + "/";
|
||||||
w8ing = true;
|
w8ing = true;
|
||||||
} else {
|
} else {
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl);
|
s += UnicodeUtils.escapeWithSpaces(hs, rofl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s += "\"" + UnicodeUtils.escape(String.valueOf(obj)) + "\"";
|
s += "\"" + UnicodeUtils.escape(hs, String.valueOf(obj)) + "\"";
|
||||||
}
|
}
|
||||||
s += ", ";
|
s += ", ";
|
||||||
}
|
}
|
||||||
@@ -237,163 +403,96 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fn.equals(nodeToFind)) {
|
if (fn.equals(nodeToFind)) {
|
||||||
lineFound = s.split("\\n").length;
|
lineFound.set(s.split("\\n").length);
|
||||||
}
|
}
|
||||||
s += "\t" + ClassUtil.getAccessFlagsFull(fn.access).replace("varargs", "transient")
|
s += "\t" + ClassUtil.getAccessFlagsFull(fn.access).replace("varargs", "transient")
|
||||||
+ UnicodeUtils.escapeWithSpaces(fn.desc) + " " + UnicodeUtils.escapeWithSpaces(fn.name);
|
+ UnicodeUtils.escapeWithSpaces(hs, fn.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, fn.name);
|
||||||
if (fn.value != null) {
|
if (fn.value != null) {
|
||||||
s += " = " + ClassUtil.getDecompiledValue(fn.value, fn.desc, true);
|
s += " = " + ClassUtil.getDecompiledValue(fn.value, fn.desc, true, hs);
|
||||||
}
|
}
|
||||||
s += "\n";
|
s += "\n";
|
||||||
|
ctx.next(s);
|
||||||
}
|
}
|
||||||
s += "\n// #Methods\n";
|
return ctx.finish();
|
||||||
for (MethodNode mn : classNode.methods) {
|
|
||||||
try {
|
|
||||||
s += "\t// #Max: l:" + mn.maxLocals + " s:" + mn.maxStack + "\n";
|
|
||||||
if (mn.signature != null)
|
|
||||||
s += "\t// #Signature: " + UnicodeUtils.escapeWithSpaces(mn.signature) + "\n";
|
|
||||||
String[] dis = disassembleMethod(classNode.name, mn);
|
|
||||||
s += dis[2];
|
|
||||||
s += dis[1];
|
|
||||||
if (mn.visibleAnnotations != null && !mn.visibleAnnotations.isEmpty()) {
|
|
||||||
for (AnnotationNode annotationNode : mn.visibleAnnotations) {
|
|
||||||
s += "\t@" + annotationNode.desc;
|
|
||||||
if (annotationNode.values != null && !annotationNode.values.isEmpty()) {
|
|
||||||
s += " (";
|
|
||||||
boolean valBefore = true;
|
|
||||||
for (Object o : annotationNode.values) {
|
|
||||||
if (valBefore) {
|
|
||||||
s += o + " = [";
|
|
||||||
valBefore = false;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
if (o instanceof String[]) {
|
|
||||||
String[] arr = (String[]) o;
|
|
||||||
boolean w8ing = false;
|
|
||||||
for (String rofl : arr) {
|
|
||||||
if (!w8ing) {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
|
||||||
w8ing = true;
|
|
||||||
} else {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += ", ";
|
|
||||||
} else if (o instanceof List) {
|
|
||||||
List list = (List) o;
|
|
||||||
s += "{ ";
|
|
||||||
for (Object obj : list) {
|
|
||||||
if (obj instanceof String[]) {
|
|
||||||
String[] arr = (String[]) obj;
|
|
||||||
boolean w8ing = false;
|
|
||||||
for (String rofl : arr) {
|
|
||||||
if (!w8ing) {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl) + "/";
|
|
||||||
w8ing = true;
|
|
||||||
} else {
|
|
||||||
s += UnicodeUtils.escapeWithSpaces(rofl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
s += "\"" + UnicodeUtils.escape(String.valueOf(obj)) + "\"";
|
|
||||||
}
|
|
||||||
s += ", ";
|
|
||||||
}
|
|
||||||
s = s.substring(0, s.length() - 2);
|
|
||||||
s += " }]";
|
|
||||||
} else {
|
|
||||||
s += "(" + o.getClass().getName().replace(".", "/") + ") " + o + "], ";
|
|
||||||
}
|
|
||||||
valBefore = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s.endsWith(", "))
|
|
||||||
s = s.substring(0, s.length() - 2);
|
|
||||||
s += ")";
|
|
||||||
}
|
|
||||||
s += "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mn.equals(nodeToFind)) {
|
|
||||||
lineFound = s.split("\\n").length;
|
|
||||||
}
|
|
||||||
s += "\t" + ClassUtil.getAccessFlagsFull(mn.access) + UnicodeUtils.escapeWithSpaces(mn.name) + " "
|
|
||||||
+ UnicodeUtils.escapeWithSpaces(mn.desc) + " ";
|
|
||||||
if (mn.exceptions != null && !mn.exceptions.isEmpty()) {
|
|
||||||
String exceptionStr = "";
|
|
||||||
for (String exc : mn.exceptions) {
|
|
||||||
if (exceptionStr.isEmpty()) {
|
|
||||||
exceptionStr += UnicodeUtils.escapeWithSpaces(exc);
|
|
||||||
} else {
|
|
||||||
exceptionStr += ", " + UnicodeUtils.escapeWithSpaces(exc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!exceptionStr.isEmpty())
|
|
||||||
s += "throws " + exceptionStr + " ";
|
|
||||||
}
|
|
||||||
s += "{\n";
|
|
||||||
s += dis[0];
|
|
||||||
s += "\t}\n\n";
|
|
||||||
} catch (Exception e) {
|
|
||||||
s += "\t\t// Method couldn't be disassembled:\n\t\t// "
|
|
||||||
+ e.getClass().getName() + ": " + e.getMessage() + "\n" + Arrays.toString(e.getStackTrace())
|
|
||||||
.replace(", ", "\n\t\t// \tat ").replace("[", "\t\t// \tat ").replace("]", "")
|
|
||||||
+ "\n\t}\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s += "}\n";
|
|
||||||
return new DisassembleTuple(s, lineFound);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
return new DisassembleTuple("Class couldn't be decompiled:\n" + e.getClass().getName() + ": "
|
|
||||||
+ e.getMessage() + "\n"
|
|
||||||
+ Arrays.toString(e.getStackTrace()).replace(", ", "\n\tat ").replace("[", "\tat ").replace("]", "")
|
|
||||||
+ "\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String[] disassembleMethod(String className, MethodNode mn) {
|
private static String[] disassembleMethod(String className, MethodNode mn, HugeStrings hs) {
|
||||||
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
HashMap<Label, Integer> labels = new HashMap<Label, Integer>();
|
||||||
String s = "";
|
String localVarTable;
|
||||||
String localVarTable = "";
|
String tryCatchTable;
|
||||||
String tryCatchTable = "";
|
|
||||||
for (AbstractInsnNode n : mn.instructions.toArray()) {
|
InsnList insnList = mn.instructions;
|
||||||
|
boolean deobfNumbers = Main.INSTANCE.mntmNumbers.isSelected();
|
||||||
|
|
||||||
|
ArrayList<Label> labelsReversed = deobfNumbers ? new ArrayList<>() : null;
|
||||||
|
|
||||||
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
if (n instanceof LabelNode) {
|
if (n instanceof LabelNode) {
|
||||||
labels.put(((LabelNode) n).getLabel(), labels.size() + 1);
|
int id = labels.size() + 1;
|
||||||
|
if (deobfNumbers)
|
||||||
|
labelsReversed.add(((LabelNode) n).getLabel());
|
||||||
|
labels.put(((LabelNode) n).getLabel(), id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mn.localVariables != null && !mn.localVariables.isEmpty()) {
|
if (mn.localVariables != null && !mn.localVariables.isEmpty()) {
|
||||||
localVarTable = "\t// #LocalVars:\n";
|
List<LocalVariableNode> list = mn.localVariables;
|
||||||
for (LocalVariableNode lvn : mn.localVariables) {
|
StringContext ctx = new StringContext(list.size() + 1);
|
||||||
localVarTable += "\t// " + UnicodeUtils.escapeWithSpaces(lvn.name) + ": "
|
ctx.next("\t// #LocalVars:\n");
|
||||||
+ UnicodeUtils.escapeWithSpaces(lvn.desc) + " i:" + lvn.index + " s:"
|
for (LocalVariableNode lvn : list) {
|
||||||
|
ctx.next("\t// " + UnicodeUtils.escapeWithSpaces(hs, lvn.name) + ": "
|
||||||
|
+ UnicodeUtils.escapeWithSpaces(hs, lvn.desc) + " i:" + lvn.index + " s:"
|
||||||
+ labels.get(lvn.start.getLabel()) + " e:" + labels.get(lvn.end.getLabel()) + " sig:"
|
+ labels.get(lvn.start.getLabel()) + " e:" + labels.get(lvn.end.getLabel()) + " sig:"
|
||||||
+ UnicodeUtils.escapeWithSpaces(lvn.signature) + "\n";
|
+ UnicodeUtils.escapeWithSpaces(hs, lvn.signature) + "\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
localVarTable = ctx.finish();
|
||||||
|
} else
|
||||||
|
localVarTable = "";
|
||||||
if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) {
|
if (mn.tryCatchBlocks != null && !mn.tryCatchBlocks.isEmpty()) {
|
||||||
tryCatchTable = "\t// #TryCatch:\n";
|
List<TryCatchBlockNode> list = mn.tryCatchBlocks;
|
||||||
|
StringContext ctx = new StringContext(list.size() + 1);
|
||||||
|
ctx.next("\t// #TryCatch:\n");
|
||||||
for (TryCatchBlockNode tcbn : mn.tryCatchBlocks) {
|
for (TryCatchBlockNode tcbn : mn.tryCatchBlocks) {
|
||||||
tryCatchTable += "\t// " + UnicodeUtils.escapeWithSpaces(tcbn.type) + " s:"
|
ctx.next("\t// " + UnicodeUtils.escapeWithSpaces(hs, tcbn.type) + " s:"
|
||||||
+ labels.get(tcbn.start.getLabel()) + " e:" + labels.get(tcbn.end.getLabel()) + " h:"
|
+ labels.get(tcbn.start.getLabel()) + " e:" + labels.get(tcbn.end.getLabel()) + " h:"
|
||||||
+ labels.get(tcbn.handler.getLabel()) + "\n";
|
+ labels.get(tcbn.handler.getLabel()) + "\n");
|
||||||
|
}
|
||||||
|
tryCatchTable = ctx.finish();
|
||||||
|
} else
|
||||||
|
tryCatchTable = "";
|
||||||
|
|
||||||
|
if (deobfNumbers) {
|
||||||
|
StackBasedCalculator calc = new StackBasedCalculator(insnList);
|
||||||
|
calc.run();
|
||||||
|
insnList = calc.get();
|
||||||
|
int i = 0;
|
||||||
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
|
if (n instanceof LabelNode) {
|
||||||
|
((LabelNode) n).setLabel(labelsReversed.get(i++));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AbstractInsnNode n : mn.instructions.toArray()) {
|
|
||||||
s += disassembleInstruction(n, labels);
|
|
||||||
}
|
|
||||||
return new String[] { s, localVarTable, tryCatchTable };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels) {
|
StringContext ctx = new StringContext(insnList.size());
|
||||||
if (FieldInsnNode.class.isInstance(n)) {
|
for (AbstractInsnNode n = insnList.getFirst(); n != null; n = n.getNext()) {
|
||||||
|
ctx.next(disassembleInstruction(n, labels, hs));
|
||||||
|
}
|
||||||
|
return new String[] { ctx.finish(), localVarTable, tryCatchTable };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final HashMap<Class, InstructionInterface> iiMap = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
iiMap.put(FieldInsnNode.class, (n, labels, hs) -> {
|
||||||
FieldInsnNode node = (FieldInsnNode) n;
|
FieldInsnNode node = (FieldInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.desc) + " " + UnicodeUtils.escapeWithSpaces(node.owner) + "/"
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.name).replace("/", "\\u002F") + "\n";
|
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
||||||
} else if (LabelNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(LabelNode.class, (n, labels, hs) -> {
|
||||||
LabelNode node = (LabelNode) n;
|
LabelNode node = (LabelNode) n;
|
||||||
return "\t\t// label " + labels.get(node.getLabel()) + "\n";
|
return "\t\t// label " + labels.get(node.getLabel()) + "\n";
|
||||||
} else if (FrameNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(FrameNode.class, (n, labels, hs) -> {
|
||||||
FrameNode node = (FrameNode) n;
|
FrameNode node = (FrameNode) n;
|
||||||
String type = "";
|
String type = "";
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
@@ -424,7 +523,7 @@ public class Disassembler {
|
|||||||
arr.add(null);
|
arr.add(null);
|
||||||
} else {
|
} else {
|
||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
arr.add("\"" + UnicodeUtils.escapeWithSpaces((String) o) + "\"");
|
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
|
||||||
} else if (o instanceof LabelNode) {
|
} else if (o instanceof LabelNode) {
|
||||||
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
||||||
} else if (o instanceof Integer) {
|
} else if (o instanceof Integer) {
|
||||||
@@ -450,7 +549,7 @@ public class Disassembler {
|
|||||||
arr.add(null);
|
arr.add(null);
|
||||||
} else {
|
} else {
|
||||||
if (o instanceof String) {
|
if (o instanceof String) {
|
||||||
arr.add("\"" + UnicodeUtils.escapeWithSpaces((String) o) + "\"");
|
arr.add("\"" + UnicodeUtils.escapeWithSpaces(hs, (String) o) + "\"");
|
||||||
} else if (o instanceof LabelNode) {
|
} else if (o instanceof LabelNode) {
|
||||||
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
arr.add("(label) " + labels.get(((LabelNode) o).getLabel()));
|
||||||
} else if (o instanceof Integer) {
|
} else if (o instanceof Integer) {
|
||||||
@@ -470,21 +569,23 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\n";
|
s += "\n";
|
||||||
return s;
|
return s;
|
||||||
} else if (LineNumberNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(LineNumberNode.class, (n, labels, hs) -> {
|
||||||
LineNumberNode node = (LineNumberNode) n;
|
LineNumberNode node = (LineNumberNode) n;
|
||||||
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
|
return "\t\t// line " + node.line + " " + labels.get(node.start.getLabel()) + "\n";
|
||||||
} else if (InvokeDynamicInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(InvokeDynamicInsnNode.class, (n, labels, hs) -> {
|
||||||
InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n;
|
InvokeDynamicInsnNode node = (InvokeDynamicInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: "
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " [\n\t\t\tname: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n\t\t\tdesc: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.desc) + "\n\t\t\tHandle: [\n\t\t\t\tname: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n\t\t\tHandle: [\n\t\t\t\tname: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.bsm.getName()) + "\n\t\t\t\towner: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.bsm.getName()) + "\n\t\t\t\towner: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.bsm.getOwner()) + "\n\t\t\t\tdesc: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.bsm.getOwner()) + "\n\t\t\t\tdesc: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.bsm.getDesc()) + "\n\t\t\t\tisInterface: "
|
+ UnicodeUtils.escapeWithSpaces(hs, node.bsm.getDesc()) + "\n\t\t\t\tisInterface: "
|
||||||
+ node.bsm.isInterface() + "\n\t\t\t\ttag: " + OpcodesReverse.reverseHandleOpcode(node.bsm.getTag())
|
+ node.bsm.isInterface() + "\n\t\t\t\ttag: " + OpcodesReverse.reverseHandleOpcode(node.bsm.getTag())
|
||||||
+ "\n\t\t\t]\n\t\t\targs: [\n";
|
+ "\n\t\t\t]\n\t\t\targs: [\n";
|
||||||
for (Object l : node.bsmArgs) {
|
for (Object l : node.bsmArgs) {
|
||||||
if (l.getClass().getName().equals("org.objectweb.asm.Type")) {
|
if (l instanceof Type) {
|
||||||
Type type = (Type) l;
|
Type type = (Type) l;
|
||||||
int valueBegin = type.valueBegin;
|
int valueBegin = type.valueBegin;
|
||||||
int valueEnd = type.valueEnd;
|
int valueEnd = type.valueEnd;
|
||||||
@@ -492,47 +593,43 @@ public class Disassembler {
|
|||||||
// Reflection
|
// Reflection
|
||||||
s += "\t\t\t\tType: [\n\t\t\t\t\ttype: " + ClassUtil.getClassNameFromType(type)
|
s += "\t\t\t\tType: [\n\t\t\t\t\ttype: " + ClassUtil.getClassNameFromType(type)
|
||||||
+ "\n\t\t\t\t\tstart: " + valueBegin + "\n\t\t\t\t\tend: " + valueEnd + "\n\t\t\t\t\tbuf: "
|
+ "\n\t\t\t\t\tstart: " + valueBegin + "\n\t\t\t\t\tend: " + valueEnd + "\n\t\t\t\t\tbuf: "
|
||||||
+ ClassUtil.getDecompiledValue(buf, "");
|
+ ClassUtil.getDecompiledValue(buf, "", hs);
|
||||||
s += "\n\t\t\t\t]\n";
|
s += "\n\t\t\t\t]\n";
|
||||||
} else if (l.getClass().getName().equals("org.objectweb.asm.Handle")) {
|
} else if (l instanceof Handle) {
|
||||||
Handle h = (Handle) l;
|
Handle h = (Handle) l;
|
||||||
s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: "
|
s += "\t\t\t\tHandle: [\n\t\t\t\t\tname: "
|
||||||
+ UnicodeUtils.escapeWithSpaces(h.getName()).replace("/", "\\u002F") + "\n\t\t\t\t\towner: "
|
+ UnicodeUtils.escapeWithSpaces(hs, h.getName()).replace("/", "\\u002F")
|
||||||
+ UnicodeUtils.escapeWithSpaces(h.getOwner()) + "\n\t\t\t\t\tdesc: "
|
+ "\n\t\t\t\t\towner: " + UnicodeUtils.escapeWithSpaces(hs, h.getOwner())
|
||||||
+ UnicodeUtils.escapeWithSpaces(h.getDesc()) + "\n\t\t\t\t\tisInterface: " + h.isInterface()
|
+ "\n\t\t\t\t\tdesc: " + UnicodeUtils.escapeWithSpaces(hs, h.getDesc())
|
||||||
+ "\n\t\t\t\t\ttag: " + OpcodesReverse.reverseHandleOpcode(h.getTag());
|
+ "\n\t\t\t\t\tisInterface: " + h.isInterface() + "\n\t\t\t\t\ttag: "
|
||||||
|
+ OpcodesReverse.reverseHandleOpcode(h.getTag());
|
||||||
s += "\n\t\t\t\t]\n";
|
s += "\n\t\t\t\t]\n";
|
||||||
} else {
|
} else {
|
||||||
s += "\t\t\t\t" + ClassUtil.getDecompiledValue(l, "") + "\n";
|
s += "\t\t\t\t" + ClassUtil.getDecompiledValue(l, "", hs) + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
} else if (MethodInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(MethodInsnNode.class, (n, labels, hs) -> {
|
||||||
MethodInsnNode node = (MethodInsnNode) n;
|
MethodInsnNode node = (MethodInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.desc) + " " + UnicodeUtils.escapeWithSpaces(node.owner) + "/"
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + UnicodeUtils.escapeWithSpaces(hs, node.owner)
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.name).replace("/", "\\u002F") + "\n";
|
+ "/" + UnicodeUtils.escapeWithSpaces(hs, node.name).replace("/", "\\u002F") + "\n";
|
||||||
} else if (TypeInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(TypeInsnNode.class, (n, labels, hs) -> {
|
||||||
TypeInsnNode node = (TypeInsnNode) n;
|
TypeInsnNode node = (TypeInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.desc) + "\n";
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + "\n";
|
||||||
} else if (MultiANewArrayInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(MultiANewArrayInsnNode.class, (n, labels, hs) -> {
|
||||||
MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
|
MultiANewArrayInsnNode node = (MultiANewArrayInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
||||||
+ UnicodeUtils.escapeWithSpaces(node.desc) + " " + node.dims + "\n";
|
+ UnicodeUtils.escapeWithSpaces(hs, node.desc) + " " + node.dims + "\n";
|
||||||
} else if (LdcInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(LdcInsnNode.class, (n, labels, hs) -> {
|
||||||
LdcInsnNode node = (LdcInsnNode) n;
|
LdcInsnNode node = (LdcInsnNode) n;
|
||||||
switch (node.cst.getClass().getSimpleName()) {
|
if (node.cst instanceof Type) {
|
||||||
case "String":
|
|
||||||
case "Double":
|
|
||||||
case "Integer":
|
|
||||||
case "Float":
|
|
||||||
case "Long": {
|
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
|
||||||
+ ClassUtil.getDecompiledValue(node.cst, "") + "\n";
|
|
||||||
}
|
|
||||||
case "Type": {
|
|
||||||
Type type = (Type) node.cst;
|
Type type = (Type) node.cst;
|
||||||
int valueBegin = type.valueBegin;
|
int valueBegin = type.valueBegin;
|
||||||
int valueEnd = type.valueEnd;
|
int valueEnd = type.valueEnd;
|
||||||
@@ -540,22 +637,29 @@ public class Disassembler {
|
|||||||
// Reflection
|
// Reflection
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type: [\n\t\t\ttype: "
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " Type: [\n\t\t\ttype: "
|
||||||
+ ClassUtil.getClassNameFromType(type) + "\n\t\t\tstart: " + valueBegin + "\n\t\t\tend: "
|
+ ClassUtil.getClassNameFromType(type) + "\n\t\t\tstart: " + valueBegin + "\n\t\t\tend: "
|
||||||
+ valueEnd + "\n\t\t\tbuf: " + ClassUtil.getDecompiledValue(buf, "");
|
+ valueEnd + "\n\t\t\tbuf: " + ClassUtil.getDecompiledValue(buf, "", hs);
|
||||||
s += "\n\t\t]\n";
|
s += "\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
|
} else {
|
||||||
|
String decomp = ClassUtil.getDecompiledValue(node.cst, "", hs);
|
||||||
|
if (node.cst instanceof String) {
|
||||||
|
if (decomp.startsWith("\"#") && decomp.endsWith("\""))
|
||||||
|
decomp = decomp.substring(1, decomp.length() - 1);
|
||||||
|
else if (decomp.startsWith("\"\\u0023"))
|
||||||
|
decomp = "\"#" + decomp.substring(7);
|
||||||
}
|
}
|
||||||
default: {
|
return "\t\t" + OpcodesReverse.reverseOpcode(node.getOpcode()) + " " + decomp + "\n";
|
||||||
return "\t\tUNRESOLVED TYPE! " + OpcodesReverse.reverseOpcode(node.getOpcode()) + " "
|
|
||||||
+ node.cst.getClass().getName().replace(".", "/") + " " + node.cst + "\n";
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
} else if (VarInsnNode.class.isInstance(n)) {
|
iiMap.put(VarInsnNode.class, (n, labels, hs) -> {
|
||||||
VarInsnNode node = (VarInsnNode) n;
|
VarInsnNode node = (VarInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + "\n";
|
||||||
} else if (InsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(InsnNode.class, (n, labels, hs) -> {
|
||||||
InsnNode node = (InsnNode) n;
|
InsnNode node = (InsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + "\n";
|
||||||
} else if (IntInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(IntInsnNode.class, (n, labels, hs) -> {
|
||||||
IntInsnNode node = (IntInsnNode) n;
|
IntInsnNode node = (IntInsnNode) n;
|
||||||
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
if (n.getOpcode() == Opcodes.NEWARRAY) {
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
||||||
@@ -563,11 +667,13 @@ public class Disassembler {
|
|||||||
} else {
|
} else {
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.operand + "\n";
|
||||||
}
|
}
|
||||||
} else if (JumpInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(JumpInsnNode.class, (n, labels, hs) -> {
|
||||||
JumpInsnNode node = (JumpInsnNode) n;
|
JumpInsnNode node = (JumpInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel())
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + labels.get(node.label.getLabel())
|
||||||
+ "\n";
|
+ "\n";
|
||||||
} else if (TableSwitchInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(TableSwitchInsnNode.class, (n, labels, hs) -> {
|
||||||
TableSwitchInsnNode node = (TableSwitchInsnNode) n;
|
TableSwitchInsnNode node = (TableSwitchInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tmin: " + node.min
|
||||||
+ "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel())
|
+ "\n\t\t\tmax: " + node.max + "\n\t\t\tdefault: " + labels.get(node.dflt.getLabel())
|
||||||
@@ -577,7 +683,8 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
} else if (LookupSwitchInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(LookupSwitchInsnNode.class, (n, labels, hs) -> {
|
||||||
LookupSwitchInsnNode node = (LookupSwitchInsnNode) n;
|
LookupSwitchInsnNode node = (LookupSwitchInsnNode) n;
|
||||||
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: "
|
String s = "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " [\n\t\t\tdefault: "
|
||||||
+ labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n";
|
+ labels.get(node.dflt.getLabel()) + "\n\t\t\tkeys: [\n";
|
||||||
@@ -590,13 +697,24 @@ public class Disassembler {
|
|||||||
}
|
}
|
||||||
s += "\t\t\t]\n\t\t]\n";
|
s += "\t\t\t]\n\t\t]\n";
|
||||||
return s;
|
return s;
|
||||||
} else if (IincInsnNode.class.isInstance(n)) {
|
});
|
||||||
|
iiMap.put(IincInsnNode.class, (n, labels, hs) -> {
|
||||||
IincInsnNode node = (IincInsnNode) n;
|
IincInsnNode node = (IincInsnNode) n;
|
||||||
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
|
return "\t\t" + OpcodesReverse.reverseOpcode(n.getOpcode()) + " " + node.var + " " + node.incr + "\n";
|
||||||
} else {
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static interface InstructionInterface {
|
||||||
|
String apply(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String disassembleInstruction(AbstractInsnNode n, HashMap<Label, Integer> labels, HugeStrings hs) {
|
||||||
|
InstructionInterface ii = iiMap.get(n.getClass());
|
||||||
|
if (ii != null)
|
||||||
|
return ii.apply(n, labels, hs);
|
||||||
|
else
|
||||||
return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
return "\t\tNOT HANDLED! " + OpcodesReverse.reverseOpcode(n.getOpcode()) + " "
|
||||||
+ n.getClass().getSimpleName() + "\n";
|
+ n.getClass().getSimpleName() + "\n";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
|
|
||||||
|
public class HugeStrings {
|
||||||
|
|
||||||
|
public static int THRESHOLD = 1000;
|
||||||
|
private final HashMap<String, HugeData> map = new HashMap<>();
|
||||||
|
|
||||||
|
public String onString(String s) {
|
||||||
|
synchronized (map) {
|
||||||
|
HugeData i = map.get(s);
|
||||||
|
if (i == null)
|
||||||
|
map.put(s, i = new HugeData(map.size(), UnicodeUtils.escape(this, s, true)));
|
||||||
|
return "#" + Integer.toString(i.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return map.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String makeStringsList() {
|
||||||
|
StringContext ctx = new StringContext(map.size());
|
||||||
|
List<HugeData> list = new ArrayList<>(map.values());
|
||||||
|
list.sort((o1, o2) -> Integer.compare(o1.id, o2.id));
|
||||||
|
for (HugeData hd : list) {
|
||||||
|
StringBuilder sb = new StringBuilder(20 + hd.escaped.length());
|
||||||
|
sb.append('#');
|
||||||
|
sb.append(Integer.toString(hd.id));
|
||||||
|
sb.append(": ");
|
||||||
|
sb.append(hd.escaped);
|
||||||
|
sb.append('\n');
|
||||||
|
ctx.next(sb.toString());
|
||||||
|
}
|
||||||
|
return ctx.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HugeData {
|
||||||
|
int id;
|
||||||
|
String escaped;
|
||||||
|
|
||||||
|
public HugeData(int id, String escaped) {
|
||||||
|
this.id = id;
|
||||||
|
this.escaped = escaped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class HugeStringsRev {
|
||||||
|
|
||||||
|
private final HashMap<Integer, String> map = new HashMap<>();
|
||||||
|
|
||||||
|
public void add(int i, String s) {
|
||||||
|
map.put(Integer.valueOf(i), s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String get(int i) {
|
||||||
|
String s = map.get(Integer.valueOf(i));
|
||||||
|
if (s == null)
|
||||||
|
s = "#" + Integer.toString(i);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2857,8 +2857,8 @@ public class JavaAssemblyTokenMaker extends AbstractJFlexCTokenMaker {
|
|||||||
* @see #addToken(int, int, int)
|
* @see #addToken(int, int, int)
|
||||||
*/
|
*/
|
||||||
private void addHyperlinkToken(int start, int end, int tokenType) {
|
private void addHyperlinkToken(int start, int end, int tokenType) {
|
||||||
int so = start + offsetShift;
|
super.addToken(zzBuffer, start, end, tokenType, start + offsetShift, true);
|
||||||
addToken(zzBuffer, start, end, tokenType, so, true);
|
zzStartRead = zzMarkedPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2867,7 +2867,8 @@ public class JavaAssemblyTokenMaker extends AbstractJFlexCTokenMaker {
|
|||||||
* @param tokenType The token's type.
|
* @param tokenType The token's type.
|
||||||
*/
|
*/
|
||||||
private void addToken(int tokenType) {
|
private void addToken(int tokenType) {
|
||||||
addToken(zzStartRead, zzMarkedPos - 1, tokenType);
|
super.addToken(zzBuffer, zzStartRead, zzMarkedPos - 1, tokenType, zzStartRead + offsetShift, false);
|
||||||
|
zzStartRead = zzMarkedPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2877,8 +2878,8 @@ public class JavaAssemblyTokenMaker extends AbstractJFlexCTokenMaker {
|
|||||||
* @see #addHyperlinkToken(int, int, int)
|
* @see #addHyperlinkToken(int, int, int)
|
||||||
*/
|
*/
|
||||||
private void addToken(int start, int end, int tokenType) {
|
private void addToken(int start, int end, int tokenType) {
|
||||||
int so = start + offsetShift;
|
super.addToken(zzBuffer, start, end, tokenType, start + offsetShift, false);
|
||||||
addToken(zzBuffer, start, end, tokenType, so, false);
|
zzStartRead = zzMarkedPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,693 @@
|
|||||||
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
import java.util.EmptyStackException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||||
|
import org.objectweb.asm.tree.InsnList;
|
||||||
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
|
import org.objectweb.asm.tree.IntInsnNode;
|
||||||
|
import org.objectweb.asm.tree.LabelNode;
|
||||||
|
import org.objectweb.asm.tree.LdcInsnNode;
|
||||||
|
|
||||||
|
public class StackBasedCalculator implements Opcodes, Runnable {
|
||||||
|
|
||||||
|
private final InsnList insns;
|
||||||
|
private final Stack<Number> stack = new Stack<>();
|
||||||
|
private AbstractInsnNode start;
|
||||||
|
private int startIdx = -1;
|
||||||
|
private boolean isAtEnd = false;
|
||||||
|
|
||||||
|
public StackBasedCalculator(InsnList insns) {
|
||||||
|
this.insns = new InsnList();
|
||||||
|
|
||||||
|
HashMap<LabelNode, LabelNode> labelMap = new HashMap<>();
|
||||||
|
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
|
||||||
|
if (node.getType() == 8) {
|
||||||
|
labelMap.put((LabelNode) node, new LabelNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (AbstractInsnNode node = insns.getFirst(); node != null; node = node.getNext()) {
|
||||||
|
this.insns.add(node.clone(labelMap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InsnList get() {
|
||||||
|
return insns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!isAtEnd) {
|
||||||
|
out: {
|
||||||
|
AbstractInsnNode[] arr = insns.toArray();
|
||||||
|
for (int i = startIdx == -1 ? 0 : startIdx; i < arr.length; i++) {
|
||||||
|
if (!handle(arr[i]))
|
||||||
|
break out;
|
||||||
|
}
|
||||||
|
isAtEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean handle(AbstractInsnNode node) {
|
||||||
|
try {
|
||||||
|
switch (node.getOpcode()) {
|
||||||
|
case ICONST_0:
|
||||||
|
stack.push(Integer.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_1:
|
||||||
|
stack.push(Integer.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_2:
|
||||||
|
stack.push(Integer.valueOf(2));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_3:
|
||||||
|
stack.push(Integer.valueOf(3));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_4:
|
||||||
|
stack.push(Integer.valueOf(4));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_5:
|
||||||
|
stack.push(Integer.valueOf(5));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case ICONST_M1:
|
||||||
|
stack.push(Integer.valueOf(-1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case DCONST_0:
|
||||||
|
stack.push(Double.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case DCONST_1:
|
||||||
|
stack.push(Double.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_0:
|
||||||
|
stack.push(Float.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_1:
|
||||||
|
stack.push(Float.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case FCONST_2:
|
||||||
|
stack.push(Float.valueOf(2));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case LCONST_0:
|
||||||
|
stack.push(Long.valueOf(0));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case LCONST_1:
|
||||||
|
stack.push(Long.valueOf(1));
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case BIPUSH:
|
||||||
|
case SIPUSH:
|
||||||
|
stack.push(((IntInsnNode) node).operand);
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
break;
|
||||||
|
case D2F:
|
||||||
|
stack.push(((Double) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case D2I:
|
||||||
|
stack.push(((Double) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case D2L:
|
||||||
|
stack.push(((Double) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2D:
|
||||||
|
stack.push(((Float) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2I:
|
||||||
|
stack.push(((Float) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case F2L:
|
||||||
|
stack.push(((Float) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2D:
|
||||||
|
stack.push(((Long) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2F:
|
||||||
|
stack.push(((Long) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case L2I:
|
||||||
|
stack.push(((Long) stack.pop()).intValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2B:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case I2C:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case I2D:
|
||||||
|
stack.push(((Integer) stack.pop()).doubleValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2F:
|
||||||
|
stack.push(((Integer) stack.pop()).floatValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2L:
|
||||||
|
stack.push(((Integer) stack.pop()).longValue());
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case I2S:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
case NOP:
|
||||||
|
break;
|
||||||
|
case LDC:
|
||||||
|
LdcInsnNode ldc = (LdcInsnNode) node;
|
||||||
|
if (ldc.cst instanceof Number) {
|
||||||
|
stack.push((Number) ldc.cst);
|
||||||
|
if (start == null)
|
||||||
|
start = node;
|
||||||
|
} else {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// long
|
||||||
|
case LADD: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSUB: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LMUL: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LDIV: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LREM: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LNEG: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LAND: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom & top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LOR: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom | top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LXOR: {
|
||||||
|
long top = ((Long) stack.pop()).longValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom ^ top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom >> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LSHL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom << top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case LUSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
long bottom = ((Long) stack.pop()).longValue();
|
||||||
|
stack.push(bottom >>> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// int
|
||||||
|
case IADD: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISUB: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IMUL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IDIV: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IREM: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case INEG: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IAND: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom & top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IOR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom | top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IXOR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom ^ top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom >> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case ISHL: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom << top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case IUSHR: {
|
||||||
|
int top = ((Integer) stack.pop()).intValue();
|
||||||
|
int bottom = ((Integer) stack.pop()).intValue();
|
||||||
|
stack.push(bottom >>> top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// double
|
||||||
|
case DADD: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DSUB: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DMUL: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DDIV: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DREM: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
double bottom = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DNEG: {
|
||||||
|
double top = ((Double) stack.pop()).doubleValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// float
|
||||||
|
case FADD: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom + top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FSUB: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom - top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FMUL: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom * top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FDIV: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom / top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FREM: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
float bottom = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(bottom % top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case FNEG: {
|
||||||
|
float top = ((Float) stack.pop()).floatValue();
|
||||||
|
stack.push(-top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// dup
|
||||||
|
case DUP: {
|
||||||
|
Number num = stack.pop();
|
||||||
|
if (num instanceof Double || num instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(num);
|
||||||
|
stack.push(num);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP_X1: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|
||||||
|
|| top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP_X2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (top instanceof Double || top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Number bottom2 = null;
|
||||||
|
if (!(bottom instanceof Double || bottom instanceof Long)) {
|
||||||
|
bottom2 = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom2 != null)
|
||||||
|
stack.push(bottom2);
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2_X1: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number bottom2 = stack.pop();
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom2);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case DUP2_X2: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = null;
|
||||||
|
if (!(top instanceof Double || top instanceof Long)) {
|
||||||
|
bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number top2 = stack.pop();
|
||||||
|
Number bottom2 = null;
|
||||||
|
if (!(top2 instanceof Double || top2 instanceof Long)) {
|
||||||
|
bottom2 = stack.pop();
|
||||||
|
if (bottom2 instanceof Double || bottom2 instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
if (bottom2 != null)
|
||||||
|
stack.push(bottom2);
|
||||||
|
stack.push(top2);
|
||||||
|
if (bottom != null)
|
||||||
|
stack.push(bottom);
|
||||||
|
stack.push(top);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// stack
|
||||||
|
case POP:
|
||||||
|
stack.pop();
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case POP2:
|
||||||
|
stack.pop();
|
||||||
|
stack.pop();
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
case SWAP: {
|
||||||
|
Number top = stack.pop();
|
||||||
|
Number bottom = stack.pop();
|
||||||
|
if (bottom instanceof Double || bottom instanceof Long || top instanceof Double
|
||||||
|
|| top instanceof Long) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
stack.push(top);
|
||||||
|
stack.push(bottom);
|
||||||
|
change(node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (ClassCastException | EmptyStackException ex) {
|
||||||
|
error(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void error(AbstractInsnNode node) {
|
||||||
|
change(node.getPrevious());
|
||||||
|
stack.clear();
|
||||||
|
start = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void change(AbstractInsnNode node) {
|
||||||
|
if (start == null)
|
||||||
|
return;
|
||||||
|
int idx = insns.indexOf(start);
|
||||||
|
startIdx = idx;
|
||||||
|
int idx2 = insns.indexOf(node);
|
||||||
|
if (idx != idx2) {
|
||||||
|
for (int i = 0; i <= idx2 - idx; i++) {
|
||||||
|
insns.remove(insns.get(idx));
|
||||||
|
}
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
addNode(idx, stack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.clear();
|
||||||
|
start = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addNode(int idx, Number n) {
|
||||||
|
if (n instanceof Double) {
|
||||||
|
double val = n.doubleValue();
|
||||||
|
if (val == 0.0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_0));
|
||||||
|
else if (val == 1.0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(DCONST_1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Float) {
|
||||||
|
float val = n.floatValue();
|
||||||
|
if (val == 0.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_0));
|
||||||
|
else if (val == 1.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_1));
|
||||||
|
else if (val == 2.0f)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(FCONST_2));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Long) {
|
||||||
|
long val = n.longValue();
|
||||||
|
if (val == 0l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_0));
|
||||||
|
else if (val == 1l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Integer) {
|
||||||
|
int val = n.intValue();
|
||||||
|
if (val == 0)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_0));
|
||||||
|
else if (val == 1)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_1));
|
||||||
|
else if (val == 2)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_2));
|
||||||
|
else if (val == 3)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_3));
|
||||||
|
else if (val == 4)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_4));
|
||||||
|
else if (val == 5)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_5));
|
||||||
|
else if (val == -1)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(ICONST_M1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else if (n instanceof Long) {
|
||||||
|
long val = n.longValue();
|
||||||
|
if (val == 0l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_0));
|
||||||
|
else if (val == 1l)
|
||||||
|
insns.insertBefore(insns.get(idx), new InsnNode(LCONST_1));
|
||||||
|
else
|
||||||
|
insns.insertBefore(insns.get(idx), new LdcInsnNode(val));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unexpected number: " + n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package me.ByteEdit.edit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a quiet fast String concatenation helper class. It appears to be a
|
||||||
|
* lot faster than Java's StringBuilder class, especially for very large
|
||||||
|
* Strings, which will be made by the Disassembler.
|
||||||
|
*/
|
||||||
|
public class StringContext {
|
||||||
|
|
||||||
|
private String[] arrs;
|
||||||
|
private int idx;
|
||||||
|
private int len;
|
||||||
|
|
||||||
|
public StringContext(int amt) {
|
||||||
|
if (amt > 0)
|
||||||
|
arrs = new String[amt];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int next(String s) {
|
||||||
|
int i = idx;
|
||||||
|
len += (arrs[idx++] = s).length();
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int i, String s) {
|
||||||
|
if (arrs[i] != null)
|
||||||
|
len -= arrs[i].length();
|
||||||
|
len += (arrs[i] = s).length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String finish() {
|
||||||
|
if (arrs == null)
|
||||||
|
return "";
|
||||||
|
char[] full = new char[len];
|
||||||
|
int off = 0;
|
||||||
|
for (int i = 0; i < idx; i++) {
|
||||||
|
int len = arrs[i].length();
|
||||||
|
arrs[i].getChars(0, len, full, off);
|
||||||
|
off += len;
|
||||||
|
arrs[i] = null;
|
||||||
|
}
|
||||||
|
String s = new String(full);
|
||||||
|
arrs = null;
|
||||||
|
full = null;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+450
-164
@@ -1,6 +1,5 @@
|
|||||||
package me.ByteEdit.main;
|
package me.ByteEdit.main;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
@@ -18,18 +17,20 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
@@ -39,17 +40,22 @@ import java.util.regex.Matcher;
|
|||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
import javax.swing.JMenuBar;
|
||||||
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JRadioButtonMenuItem;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JSplitPane;
|
import javax.swing.JSplitPane;
|
||||||
import javax.swing.JTree;
|
import javax.swing.JTree;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.UIManager;
|
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.event.TreeExpansionEvent;
|
import javax.swing.event.TreeExpansionEvent;
|
||||||
import javax.swing.event.TreeExpansionListener;
|
import javax.swing.event.TreeExpansionListener;
|
||||||
@@ -70,10 +76,11 @@ import org.fife.ui.autocomplete.DefaultCompletionProvider;
|
|||||||
import org.fife.ui.autocomplete.ShorthandCompletion;
|
import org.fife.ui.autocomplete.ShorthandCompletion;
|
||||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||||
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
||||||
import org.fife.ui.rsyntaxtextarea.Theme;
|
|
||||||
import org.fife.ui.rsyntaxtextarea.folding.CurlyFoldParser;
|
import org.fife.ui.rsyntaxtextarea.folding.CurlyFoldParser;
|
||||||
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
|
import org.fife.ui.rsyntaxtextarea.folding.FoldParserManager;
|
||||||
|
import org.fife.ui.rtextarea.RTextArea;
|
||||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||||
|
import org.fife.ui.rtextarea.ToolTipSupplier;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
@@ -82,14 +89,15 @@ import org.objectweb.asm.tree.MethodNode;
|
|||||||
|
|
||||||
import me.ByteEdit.boxes.CompilationBox;
|
import me.ByteEdit.boxes.CompilationBox;
|
||||||
import me.ByteEdit.boxes.GlobalSearchBox;
|
import me.ByteEdit.boxes.GlobalSearchBox;
|
||||||
import me.ByteEdit.boxes.OptionBox;
|
|
||||||
import me.ByteEdit.boxes.RenameBox;
|
import me.ByteEdit.boxes.RenameBox;
|
||||||
import me.ByteEdit.boxes.SearchBox;
|
import me.ByteEdit.boxes.SearchBox;
|
||||||
|
import me.ByteEdit.boxes.ThemeBox;
|
||||||
import me.ByteEdit.boxes.TypeOpenBox;
|
import me.ByteEdit.boxes.TypeOpenBox;
|
||||||
import me.ByteEdit.boxes.UnicodeBox;
|
import me.ByteEdit.boxes.UnicodeBox;
|
||||||
import me.ByteEdit.edit.Assembler;
|
import me.ByteEdit.edit.Assembler;
|
||||||
import me.ByteEdit.edit.Disassembler;
|
import me.ByteEdit.edit.Disassembler;
|
||||||
import me.ByteEdit.edit.Disassembler.DisassembleTuple;
|
import me.ByteEdit.edit.Disassembler.DisassembleTuple;
|
||||||
|
import me.ByteEdit.edit.HugeStrings;
|
||||||
import me.ByteEdit.utils.ClassUtil;
|
import me.ByteEdit.utils.ClassUtil;
|
||||||
import me.ByteEdit.utils.OpcodesReverse;
|
import me.ByteEdit.utils.OpcodesReverse;
|
||||||
import me.ByteEdit.utils.UnicodeUtils;
|
import me.ByteEdit.utils.UnicodeUtils;
|
||||||
@@ -98,7 +106,7 @@ public class Main extends JFrame {
|
|||||||
|
|
||||||
public static Main INSTANCE;
|
public static Main INSTANCE;
|
||||||
private JPanel contentPane;
|
private JPanel contentPane;
|
||||||
private boolean isChangingFile;
|
private volatile boolean isChangingFile;
|
||||||
public static File jarFile;
|
public static File jarFile;
|
||||||
public static HashMap<String, byte[]> OTHER_FILES = new HashMap<>();
|
public static HashMap<String, byte[]> OTHER_FILES = new HashMap<>();
|
||||||
public static HashMap<String, ClassNode> classNodes = new HashMap<>();
|
public static HashMap<String, ClassNode> classNodes = new HashMap<>();
|
||||||
@@ -107,16 +115,43 @@ public class Main extends JFrame {
|
|||||||
public static GlobalSearchBox globalSearchBox;
|
public static GlobalSearchBox globalSearchBox;
|
||||||
public static SearchBox searchBox;
|
public static SearchBox searchBox;
|
||||||
public static TypeOpenBox typeOpenBox;
|
public static TypeOpenBox typeOpenBox;
|
||||||
public static OptionBox optionBox;
|
|
||||||
public static UnicodeBox unicodeBox;
|
public static UnicodeBox unicodeBox;
|
||||||
public static RenameBox renameBox;
|
public static RenameBox renameBox;
|
||||||
public static CompilationBox compilationBox;
|
public static CompilationBox compilationBox;
|
||||||
|
public static ThemeBox themeBox;
|
||||||
public static JTree tree;
|
public static JTree tree;
|
||||||
public static RTextScrollPane scrollPane_ByteEdit;
|
public static RTextScrollPane scrollPane_ByteEdit;
|
||||||
public static Theme theme;
|
|
||||||
public static File saveFolder;
|
public static File saveFolder;
|
||||||
|
|
||||||
public static HashSet<String> fakedFolders = new HashSet<>();
|
private static final Pattern SLASH = Pattern.compile("/");
|
||||||
|
private JMenuBar menuBar;
|
||||||
|
private JMenu mnFile;
|
||||||
|
private JMenuItem mntmOpenJar;
|
||||||
|
private JMenuItem mntmSaveBytecode;
|
||||||
|
private JMenuItem mntmSaveJar;
|
||||||
|
private JMenu mnWindow;
|
||||||
|
private JMenuItem mntmThemes;
|
||||||
|
private JMenuItem mntmSearchMembers;
|
||||||
|
private JMenuItem mntmSearch;
|
||||||
|
private JMenuItem mntmOpenType;
|
||||||
|
private JMenuItem mntmUnicode;
|
||||||
|
private JMenuItem mntmCompiler;
|
||||||
|
private JMenu mnSearch;
|
||||||
|
private JMenu mnOptions;
|
||||||
|
private JCheckBoxMenuItem mntmComputeFrames;
|
||||||
|
private JCheckBoxMenuItem mntmComputeMax;
|
||||||
|
private JMenu mnStringLimit;
|
||||||
|
private JRadioButtonMenuItem rdbtnmntm0;
|
||||||
|
private JMenuItem rdbtnmntm100;
|
||||||
|
private JMenuItem rdbtnmntm1000;
|
||||||
|
private JMenuItem rdbtnmntm500;
|
||||||
|
private JMenuItem rdbtnmntm5000;
|
||||||
|
private JMenuItem rdbtnmntm10000;
|
||||||
|
public JCheckBoxMenuItem mntmMultithreaded;
|
||||||
|
private JMenu mnDeobfuscation;
|
||||||
|
public JCheckBoxMenuItem mntmNumbers;
|
||||||
|
|
||||||
|
public static final Object treeLock = new Object();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launch the application.
|
* Launch the application.
|
||||||
@@ -128,11 +163,13 @@ public class Main extends JFrame {
|
|||||||
try {
|
try {
|
||||||
Main frame = new Main();
|
Main frame = new Main();
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
|
ThemeManager.applyRSTATheme();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,46 +235,200 @@ public class Main extends JFrame {
|
|||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean dark = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the frame.
|
* Create the frame.
|
||||||
*/
|
*/
|
||||||
public Main() {
|
public Main() {
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
File light = new File(System.getProperty("java.io.tmpdir") + File.pathSeparator + "ByteEditLight.conf");
|
ThemeManager.registerFrames(this);
|
||||||
if (light.exists()) {
|
|
||||||
dark = false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
theme = Theme.load(getClass().getClassLoader()
|
|
||||||
.getResourceAsStream(dark ? "org/fife/eclipse_dark.xml" : "org/fife/eclipse.xml"));
|
|
||||||
} catch (IOException e2) {
|
|
||||||
e2.printStackTrace();
|
|
||||||
}
|
|
||||||
globalSearchBox = new GlobalSearchBox();
|
globalSearchBox = new GlobalSearchBox();
|
||||||
searchBox = new SearchBox();
|
searchBox = new SearchBox();
|
||||||
typeOpenBox = new TypeOpenBox();
|
typeOpenBox = new TypeOpenBox();
|
||||||
optionBox = new OptionBox();
|
|
||||||
unicodeBox = new UnicodeBox();
|
unicodeBox = new UnicodeBox();
|
||||||
renameBox = new RenameBox();
|
renameBox = new RenameBox();
|
||||||
compilationBox = new CompilationBox();
|
compilationBox = new CompilationBox();
|
||||||
|
themeBox = new ThemeBox();
|
||||||
|
ThemeManager.registerFrames(globalSearchBox);
|
||||||
|
ThemeManager.registerFrames(searchBox);
|
||||||
|
ThemeManager.registerFrames(typeOpenBox);
|
||||||
|
ThemeManager.registerFrames(unicodeBox);
|
||||||
|
ThemeManager.registerFrames(renameBox);
|
||||||
|
ThemeManager.registerFrames(compilationBox);
|
||||||
|
ThemeManager.registerFrames(themeBox);
|
||||||
|
ThemeManager.load();
|
||||||
setTitle("ByteEdit");
|
setTitle("ByteEdit");
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 407),
|
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 407),
|
||||||
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 237), 814, 474);
|
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 237), 814, 474);
|
||||||
|
|
||||||
|
menuBar = new JMenuBar();
|
||||||
|
setJMenuBar(menuBar);
|
||||||
|
|
||||||
|
mnFile = new JMenu("File");
|
||||||
|
menuBar.add(mnFile);
|
||||||
|
|
||||||
|
mntmOpenJar = new JMenuItem("Open Jar");
|
||||||
|
mntmOpenJar.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent arg0) {
|
||||||
|
final JFileChooser fileChooser = new JFileChooser(saveFolder) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JDialog createDialog(final Component parent) throws HeadlessException {
|
||||||
|
final JDialog dialog = super.createDialog(parent);
|
||||||
|
dialog.setAlwaysOnTop(true);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fileChooser.setDialogTitle("Open File");
|
||||||
|
fileChooser.setFileSelectionMode(0);
|
||||||
|
fileChooser.setAcceptAllFileFilterUsed(false);
|
||||||
|
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter("Jar File", "jar"));
|
||||||
|
final int action = fileChooser.showOpenDialog(Main.this);
|
||||||
|
if (action == 0) {
|
||||||
|
final File file = fileChooser.getSelectedFile();
|
||||||
|
saveFolder = file.getParentFile();
|
||||||
|
boolean shouldSave = false;
|
||||||
|
if (file.exists()) {
|
||||||
|
synchronized (treeLock) {
|
||||||
|
jarFile = file;
|
||||||
|
saveFolder = file.getParentFile();
|
||||||
|
isChangingFile = true;
|
||||||
try {
|
try {
|
||||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
Main.this.setTitle("ByteEdit - Loading '" + jarFile.getCanonicalPath() + "'");
|
||||||
} catch (Exception e) {
|
} catch (IOException ex) {
|
||||||
|
Main.this.setTitle("ByteEdit - Loading '" + jarFile.getAbsolutePath() + "'");
|
||||||
|
}
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile));
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (treeLock) {
|
||||||
|
tree.setModel(model);
|
||||||
|
txtByteEditView.setText("");
|
||||||
|
currentNodeName = null;
|
||||||
|
globalSearchBox.setVisible(false);
|
||||||
|
searchBox.setVisible(false);
|
||||||
|
typeOpenBox.setVisible(false);
|
||||||
|
unicodeBox.setVisible(false);
|
||||||
|
renameBox.setVisible(false);
|
||||||
|
compilationBox.setVisible(false);
|
||||||
|
isChangingFile = false;
|
||||||
|
Main.this.setTitle("ByteEdit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mnFile.add(mntmOpenJar);
|
||||||
|
|
||||||
|
mntmSaveBytecode = new JMenuItem("Save Bytecode");
|
||||||
|
mntmSaveBytecode.addActionListener(e -> saveCurrentClassNode());
|
||||||
|
mnFile.add(mntmSaveBytecode);
|
||||||
|
|
||||||
|
mntmSaveJar = new JMenuItem("Save Jar");
|
||||||
|
mntmSaveJar.addActionListener(e -> save());
|
||||||
|
mnFile.add(mntmSaveJar);
|
||||||
|
|
||||||
|
mnSearch = new JMenu("Search");
|
||||||
|
menuBar.add(mnSearch);
|
||||||
|
|
||||||
|
mntmSearchMembers = new JMenuItem("Search Members");
|
||||||
|
mnSearch.add(mntmSearchMembers);
|
||||||
|
|
||||||
|
mntmSearch = new JMenuItem("Search");
|
||||||
|
mnSearch.add(mntmSearch);
|
||||||
|
mntmSearch.addActionListener(e -> searchBox.setVisible(true));
|
||||||
|
mntmSearchMembers.addActionListener(e -> globalSearchBox.setVisible(true));
|
||||||
|
|
||||||
|
mnWindow = new JMenu("Window");
|
||||||
|
menuBar.add(mnWindow);
|
||||||
|
|
||||||
|
mntmThemes = new JMenuItem("Themes");
|
||||||
|
mntmThemes.addActionListener(e -> themeBox.setVisible(true));
|
||||||
|
mnWindow.add(mntmThemes);
|
||||||
|
|
||||||
|
mntmOpenType = new JMenuItem("Open Type");
|
||||||
|
mntmOpenType.addActionListener(e -> typeOpenBox.setVisible(true));
|
||||||
|
mnWindow.add(mntmOpenType);
|
||||||
|
|
||||||
|
mntmUnicode = new JMenuItem("Unicode Helper");
|
||||||
|
mntmUnicode.addActionListener(e -> unicodeBox.setVisible(true));
|
||||||
|
mnWindow.add(mntmUnicode);
|
||||||
|
|
||||||
|
mntmCompiler = new JMenuItem("Compiler");
|
||||||
|
mntmCompiler.addActionListener(e -> compilationBox.setVisible(true));
|
||||||
|
mnWindow.add(mntmCompiler);
|
||||||
|
|
||||||
|
mnOptions = new JMenu("Options");
|
||||||
|
menuBar.add(mnOptions);
|
||||||
|
|
||||||
|
mntmComputeFrames = new JCheckBoxMenuItem("Compute Frames");
|
||||||
|
mnOptions.add(mntmComputeFrames);
|
||||||
|
|
||||||
|
mntmComputeMax = new JCheckBoxMenuItem("Compute Max");
|
||||||
|
mnOptions.add(mntmComputeMax);
|
||||||
|
|
||||||
|
mntmMultithreaded = new JCheckBoxMenuItem("Multithreaded");
|
||||||
|
mntmMultithreaded.setSelected(true);
|
||||||
|
mnOptions.add(mntmMultithreaded);
|
||||||
|
|
||||||
|
mnStringLimit = new JMenu("Huge String Limit");
|
||||||
|
mnOptions.add(mnStringLimit);
|
||||||
|
|
||||||
|
rdbtnmntm0 = new JRadioButtonMenuItem("0");
|
||||||
|
rdbtnmntm0.addActionListener(e -> HugeStrings.THRESHOLD = 0);
|
||||||
|
mnStringLimit.add(rdbtnmntm0);
|
||||||
|
|
||||||
|
rdbtnmntm100 = new JRadioButtonMenuItem("100");
|
||||||
|
rdbtnmntm100.addActionListener(e -> HugeStrings.THRESHOLD = 100);
|
||||||
|
mnStringLimit.add(rdbtnmntm100);
|
||||||
|
|
||||||
|
rdbtnmntm500 = new JRadioButtonMenuItem("500");
|
||||||
|
rdbtnmntm500.addActionListener(e -> HugeStrings.THRESHOLD = 500);
|
||||||
|
mnStringLimit.add(rdbtnmntm500);
|
||||||
|
|
||||||
|
rdbtnmntm1000 = new JRadioButtonMenuItem("1000");
|
||||||
|
rdbtnmntm1000.addActionListener(e -> HugeStrings.THRESHOLD = 1000);
|
||||||
|
rdbtnmntm1000.setSelected(true);
|
||||||
|
mnStringLimit.add(rdbtnmntm1000);
|
||||||
|
|
||||||
|
rdbtnmntm5000 = new JRadioButtonMenuItem("5000");
|
||||||
|
rdbtnmntm5000.addActionListener(e -> HugeStrings.THRESHOLD = 5000);
|
||||||
|
mnStringLimit.add(rdbtnmntm5000);
|
||||||
|
|
||||||
|
rdbtnmntm10000 = new JRadioButtonMenuItem("10000");
|
||||||
|
rdbtnmntm10000.addActionListener(e -> HugeStrings.THRESHOLD = 10000);
|
||||||
|
mnStringLimit.add(rdbtnmntm10000);
|
||||||
|
|
||||||
|
ButtonGroup group = new ButtonGroup();
|
||||||
|
group.add(rdbtnmntm0);
|
||||||
|
group.add(rdbtnmntm100);
|
||||||
|
group.add(rdbtnmntm500);
|
||||||
|
group.add(rdbtnmntm1000);
|
||||||
|
group.add(rdbtnmntm5000);
|
||||||
|
group.add(rdbtnmntm10000);
|
||||||
|
|
||||||
|
mnDeobfuscation = new JMenu("Deobfuscation");
|
||||||
|
menuBar.add(mnDeobfuscation);
|
||||||
|
|
||||||
|
mntmNumbers = new JCheckBoxMenuItem("Numbers");
|
||||||
|
mnDeobfuscation.add(mntmNumbers);
|
||||||
|
|
||||||
contentPane = new JPanel();
|
contentPane = new JPanel();
|
||||||
contentPane.setBackground(dark ? new Color(0x2F2F2F) : Color.GRAY);
|
|
||||||
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||||
setContentPane(contentPane);
|
setContentPane(contentPane);
|
||||||
contentPane.setLayout(new GridLayout(0, 1, 0, 0));
|
contentPane.setLayout(new GridLayout(0, 1, 0, 0));
|
||||||
JSplitPane splitPane = new JSplitPane();
|
JSplitPane splitPane = new JSplitPane();
|
||||||
splitPane.setBackground(dark ? new Color(0x2F2F2F) : Color.GRAY);
|
|
||||||
splitPane.setResizeWeight(0.2);
|
splitPane.setResizeWeight(0.2);
|
||||||
contentPane.add(splitPane);
|
contentPane.add(splitPane);
|
||||||
JScrollPane scrollPane = new JScrollPane();
|
JScrollPane scrollPane = new JScrollPane();
|
||||||
@@ -255,18 +446,36 @@ public class Main extends JFrame {
|
|||||||
@Override
|
@Override
|
||||||
public void keyReleased(KeyEvent e) {
|
public void keyReleased(KeyEvent e) {
|
||||||
if (e.getKeyCode() == 116 && jarFile != null) { // F5
|
if (e.getKeyCode() == 116 && jarFile != null) { // F5
|
||||||
|
synchronized (treeLock) {
|
||||||
|
if (isChangingFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
isChangingFile = true;
|
isChangingFile = true;
|
||||||
|
Main.this.setTitle("ByteEdit - Reloading...");
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
try {
|
try {
|
||||||
tree.setModel(new ArchiveTreeModel(new JarFile(jarFile)));
|
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile));
|
||||||
} catch (IOException e1) {
|
EventQueue.invokeLater(new Runnable() {
|
||||||
e1.printStackTrace();
|
public void run() {
|
||||||
}
|
synchronized (treeLock) {
|
||||||
|
tree.setModel(model);
|
||||||
isChangingFile = false;
|
isChangingFile = false;
|
||||||
|
Main.this.setTitle("ByteEdit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
showError(t);
|
showError(t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else if (e.getKeyCode() == 127) { // del
|
} else if (e.getKeyCode() == 127) { // del
|
||||||
if (tree.getSelectionPath() == null)
|
if (tree.getSelectionPath() == null)
|
||||||
return;
|
return;
|
||||||
@@ -296,29 +505,31 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
tree.setFont(new Font("Verdana", Font.PLAIN, 11));
|
tree.setFont(new Font("Verdana", Font.PLAIN, 11));
|
||||||
tree.setBackground(dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
tree.setCellRenderer(new DefaultTreeCellRenderer() {
|
tree.setCellRenderer(new DefaultTreeCellRenderer() {
|
||||||
{
|
{
|
||||||
putClientProperty("html.disable", Boolean.TRUE);
|
putClientProperty("html.disable", Boolean.TRUE);
|
||||||
setBackgroundNonSelectionColor(dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
setBackgroundSelectionColor(Color.GRAY);
|
|
||||||
setTextNonSelectionColor(dark ? new Color(0xeeeeee) : Color.BLACK);
|
|
||||||
setTextSelectionColor(dark ? new Color(0xeeeeee) : Color.BLACK);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
scrollPane.setViewportView(tree);
|
scrollPane.setViewportView(tree);
|
||||||
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
tree.addTreeSelectionListener(new TreeSelectionListener() {
|
||||||
|
|
||||||
public void valueChanged(TreeSelectionEvent e) {
|
public void valueChanged(TreeSelectionEvent e) {
|
||||||
|
synchronized (treeLock) {
|
||||||
if (!isChangingFile) {
|
if (!isChangingFile) {
|
||||||
selectFile(((ByteEditTreeNode) e.getPath().getLastPathComponent()).path);
|
selectFile(((ByteEditTreeNode) e.getPath().getLastPathComponent()).path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
new DropTarget(tree, new DropTargetListener() {
|
new DropTarget(tree, new DropTargetListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drop(DropTargetDropEvent dtde) {
|
public void drop(DropTargetDropEvent dtde) {
|
||||||
|
synchronized (treeLock) {
|
||||||
|
if (isChangingFile) {
|
||||||
|
dtde.rejectDrop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Transferable tr = dtde.getTransferable();
|
Transferable tr = dtde.getTransferable();
|
||||||
DataFlavor[] flavors = tr.getTransferDataFlavors();
|
DataFlavor[] flavors = tr.getTransferDataFlavors();
|
||||||
@@ -332,22 +543,39 @@ public class Main extends JFrame {
|
|||||||
saveFolder = file.getParentFile();
|
saveFolder = file.getParentFile();
|
||||||
isChangingFile = true;
|
isChangingFile = true;
|
||||||
try {
|
try {
|
||||||
tree.setModel(new ArchiveTreeModel(new JarFile(jarFile)));
|
Main.this.setTitle("ByteEdit - Loading '" + jarFile.getCanonicalPath() + "'");
|
||||||
} catch (IOException e1) {
|
} catch (IOException ex) {
|
||||||
e1.printStackTrace();
|
Main.this.setTitle("ByteEdit - Loading '" + jarFile.getAbsolutePath() + "'");
|
||||||
}
|
}
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
ArchiveTreeModel model = new ArchiveTreeModel(new JarFile(jarFile));
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (treeLock) {
|
||||||
|
tree.setModel(model);
|
||||||
txtByteEditView.setText("");
|
txtByteEditView.setText("");
|
||||||
currentNodeName = null;
|
currentNodeName = null;
|
||||||
globalSearchBox.setVisible(false);
|
globalSearchBox.setVisible(false);
|
||||||
searchBox.setVisible(false);
|
searchBox.setVisible(false);
|
||||||
typeOpenBox.setVisible(false);
|
typeOpenBox.setVisible(false);
|
||||||
optionBox.setVisible(false);
|
|
||||||
unicodeBox.setVisible(false);
|
unicodeBox.setVisible(false);
|
||||||
renameBox.setVisible(false);
|
renameBox.setVisible(false);
|
||||||
compilationBox.setVisible(false);
|
compilationBox.setVisible(false);
|
||||||
isChangingFile = false;
|
isChangingFile = false;
|
||||||
|
Main.this.setTitle("ByteEdit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
dtde.dropComplete(true);
|
dtde.dropComplete(true);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -355,6 +583,7 @@ public class Main extends JFrame {
|
|||||||
t.printStackTrace();
|
t.printStackTrace();
|
||||||
showError(t);
|
showError(t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
dtde.rejectDrop();
|
dtde.rejectDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,6 +607,84 @@ public class Main extends JFrame {
|
|||||||
txtByteEditView = new RSyntaxTextArea();
|
txtByteEditView = new RSyntaxTextArea();
|
||||||
ac.install(txtByteEditView);
|
ac.install(txtByteEditView);
|
||||||
txtByteEditView.setCodeFoldingEnabled(true);
|
txtByteEditView.setCodeFoldingEnabled(true);
|
||||||
|
// ToolTips for HugeStrings
|
||||||
|
txtByteEditView.setToolTipSupplier(new ToolTipSupplier() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getToolTipText(RTextArea textArea, MouseEvent e) {
|
||||||
|
int idx = textArea.viewToModel(e.getPoint());
|
||||||
|
if (idx < 0)
|
||||||
|
return null;
|
||||||
|
int subIdx = Math.max(idx - 15, 0);
|
||||||
|
int subLen = Math.min(30, textArea.getDocument().getLength() - subIdx);
|
||||||
|
if (subLen <= 0)
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
String cut = textArea.getText(subIdx, subLen);
|
||||||
|
int hashIdx = -1;
|
||||||
|
for (int off = idx - subIdx; off >= 0; off--) {
|
||||||
|
if (cut.charAt(off) == '#') {
|
||||||
|
hashIdx = off;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashIdx < 0) {
|
||||||
|
for (int off = idx - subIdx; off < cut.length(); off++) {
|
||||||
|
if (cut.charAt(off) == '#') {
|
||||||
|
hashIdx = off;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hashIdx < 0)
|
||||||
|
return null;
|
||||||
|
if (hashIdx >= 5 && cut.substring(hashIdx - 5, hashIdx).equals("ldc \"")) // ldc "#..."
|
||||||
|
return null;
|
||||||
|
int numLen = 1;
|
||||||
|
for (int i = hashIdx + 1; i < cut.length(); i++) {
|
||||||
|
if (!(cut.charAt(i) - '0' >= 0 && cut.charAt(i) - '0' <= 9)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
numLen++;
|
||||||
|
}
|
||||||
|
if (numLen < 2 || hashIdx > idx - subIdx || idx - subIdx - numLen >= hashIdx)
|
||||||
|
return null;
|
||||||
|
String hashNum = cut.substring(hashIdx, hashIdx + numLen);
|
||||||
|
|
||||||
|
String txt = txtByteEditView.getText();
|
||||||
|
int len = 0;
|
||||||
|
for (String asm : txt.split("\\/\\/ #Annotations:\n")) {
|
||||||
|
len += 19; // "\\/\\/ #Annotations:\n".length()
|
||||||
|
if (asm.isEmpty())
|
||||||
|
continue;
|
||||||
|
if (idx >= len && idx < len + asm.length()) {
|
||||||
|
try (BufferedReader reader = new BufferedReader(new StringReader(asm))) {
|
||||||
|
String s;
|
||||||
|
while (!(s = reader.readLine()).startsWith("// #SourceFile: ")) {
|
||||||
|
}
|
||||||
|
while (!(s = reader.readLine()).equals("// #Fields")) {
|
||||||
|
if (s.startsWith("#")) {
|
||||||
|
String[] split = Assembler.SPACE.split(s, 2);
|
||||||
|
if (hashNum.equals(split[0].substring(0, split[0].length() - 1))) {
|
||||||
|
String toolTip = split[1];
|
||||||
|
if (toolTip.length() > 500)
|
||||||
|
toolTip = toolTip.substring(0, 500) + "...";
|
||||||
|
return toolTip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e1) {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
len += asm.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (BadLocationException e1) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
txtByteEditView.addKeyListener(new KeyAdapter() {
|
txtByteEditView.addKeyListener(new KeyAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -397,6 +704,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
txtByteEditView.setText(dis);
|
txtByteEditView.setText(dis);
|
||||||
|
if (dis.length() > prev)
|
||||||
txtByteEditView.setCaretPosition(prev);
|
txtByteEditView.setCaretPosition(prev);
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
e2.printStackTrace();
|
e2.printStackTrace();
|
||||||
@@ -408,126 +716,59 @@ public class Main extends JFrame {
|
|||||||
KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlT = KeyStroke.getKeyStroke(KeyEvent.VK_T, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlG = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlG = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlO = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK);
|
|
||||||
KeyStroke ctrlU = KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlU = KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlR = KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlE = KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlE = KeyStroke.getKeyStroke(KeyEvent.VK_E, KeyEvent.CTRL_DOWN_MASK);
|
||||||
KeyStroke ctrlB = KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_DOWN_MASK);
|
KeyStroke ctrlB = KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_DOWN_MASK);
|
||||||
// global
|
// global
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
txtByteEditView.registerKeyboardAction(e -> themeBox.setVisible(true), ctrlB,
|
||||||
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
@Override
|
txtByteEditView.registerKeyboardAction(e -> {
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
if (light.exists())
|
|
||||||
light.delete();
|
|
||||||
else
|
|
||||||
try {
|
|
||||||
light.createNewFile();
|
|
||||||
} catch (IOException e1) {
|
|
||||||
}
|
|
||||||
dark = !dark;
|
|
||||||
JOptionPane.showMessageDialog(Main.this,
|
|
||||||
"Theme switched to " + (dark ? "Dark" : "Light") + ".\nPlease restart ByteEdit.",
|
|
||||||
"Theme changed", JOptionPane.INFORMATION_MESSAGE);
|
|
||||||
}
|
|
||||||
}, ctrlB, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
globalSearchBox.setVisible(true);
|
globalSearchBox.setVisible(true);
|
||||||
globalSearchBox.txtString.requestFocusInWindow();
|
globalSearchBox.txtString.requestFocusInWindow();
|
||||||
globalSearchBox.txtString.select(0, globalSearchBox.txtString.getText().length());
|
globalSearchBox.txtString.select(0, globalSearchBox.txtString.getText().length());
|
||||||
}
|
|
||||||
}, ctrlG, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
}, ctrlG, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
txtByteEditView.registerKeyboardAction(e -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
searchBox.setVisible(true);
|
searchBox.setVisible(true);
|
||||||
searchBox.txtFind.requestFocusInWindow();
|
searchBox.txtFind.requestFocusInWindow();
|
||||||
searchBox.txtFind.select(0, searchBox.txtFind.getText().length());
|
searchBox.txtFind.select(0, searchBox.txtFind.getText().length());
|
||||||
}
|
|
||||||
}, ctrlF, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
}, ctrlF, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
txtByteEditView.registerKeyboardAction(e -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
typeOpenBox.setVisible(true);
|
typeOpenBox.setVisible(true);
|
||||||
typeOpenBox.txtSearch.requestFocusInWindow();
|
typeOpenBox.txtSearch.requestFocusInWindow();
|
||||||
typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length());
|
typeOpenBox.txtSearch.select(0, typeOpenBox.txtSearch.getText().length());
|
||||||
}
|
|
||||||
}, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
}, ctrlT, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
txtByteEditView.registerKeyboardAction(e -> unicodeBox.setVisible(true), ctrlU,
|
||||||
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
@Override
|
txtByteEditView.registerKeyboardAction(e -> compilationBox.setVisible(true), ctrlE,
|
||||||
public void actionPerformed(ActionEvent e) {
|
JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||||
optionBox.setVisible(true);
|
|
||||||
}
|
|
||||||
}, ctrlO, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
unicodeBox.setVisible(true);
|
|
||||||
}
|
|
||||||
}, ctrlU, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
compilationBox.setVisible(true);
|
|
||||||
}
|
|
||||||
}, ctrlE, JComponent.WHEN_IN_FOCUSED_WINDOW);
|
|
||||||
// specific
|
// specific
|
||||||
tree.registerKeyboardAction(new ActionListener() {
|
tree.registerKeyboardAction(e -> save(), ctrlS, JComponent.WHEN_FOCUSED);
|
||||||
|
txtByteEditView.registerKeyboardAction(e -> saveCurrentClassNode(), ctrlS, JComponent.WHEN_FOCUSED);
|
||||||
@Override
|
txtByteEditView.registerKeyboardAction(e -> {
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
}, ctrlS, JComponent.WHEN_FOCUSED);
|
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
saveCurrentClassNode();
|
|
||||||
}
|
|
||||||
}, ctrlS, JComponent.WHEN_FOCUSED);
|
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
try {
|
try {
|
||||||
goToSelected();
|
goToSelected();
|
||||||
} catch (BadLocationException e1) {
|
} catch (BadLocationException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, ctrlG, JComponent.WHEN_FOCUSED);
|
}, ctrlG, JComponent.WHEN_FOCUSED);
|
||||||
txtByteEditView.registerKeyboardAction(new ActionListener() {
|
txtByteEditView.registerKeyboardAction(e -> {
|
||||||
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
try {
|
try {
|
||||||
renameSelected();
|
renameSelected();
|
||||||
} catch (BadLocationException e1) {
|
} catch (BadLocationException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, ctrlR, JComponent.WHEN_FOCUSED);
|
}, ctrlR, JComponent.WHEN_FOCUSED);
|
||||||
txtByteEditView.setEditable(true);
|
txtByteEditView.setEditable(true);
|
||||||
txtByteEditView.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE);
|
txtByteEditView.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA_DISASSEMBLE);
|
||||||
txtByteEditView.setCodeFoldingEnabled(true);
|
txtByteEditView.setCodeFoldingEnabled(true);
|
||||||
scrollPane_ByteEdit = new RTextScrollPane();
|
scrollPane_ByteEdit = new RTextScrollPane();
|
||||||
theme.apply(txtByteEditView);
|
ThemeManager.registerTextArea(txtByteEditView);
|
||||||
|
|
||||||
splitPane.setRightComponent(scrollPane_ByteEdit);
|
splitPane.setRightComponent(scrollPane_ByteEdit);
|
||||||
txtByteEditView.setBackground(dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
scrollPane_ByteEdit.setViewportView(txtByteEditView);
|
scrollPane_ByteEdit.setViewportView(txtByteEditView);
|
||||||
scrollPane_ByteEdit.setLineNumbersEnabled(true);
|
scrollPane_ByteEdit.setLineNumbersEnabled(true);
|
||||||
scrollPane_ByteEdit.setFoldIndicatorEnabled(true);
|
scrollPane_ByteEdit.setFoldIndicatorEnabled(true);
|
||||||
scrollPane_ByteEdit.getGutter().setBackground(dark ? new Color(0x2F2F2F) : Color.LIGHT_GRAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Pattern jumpableInstructionPattern = Pattern.compile("^\t\t(?!//|\t+).+ .+");
|
private final Pattern jumpableInstructionPattern = Pattern.compile("^\t\t(?!//|\t+).+ .+");
|
||||||
@@ -542,15 +783,11 @@ public class Main extends JFrame {
|
|||||||
line = line.substring(2);
|
line = line.substring(2);
|
||||||
if (line.startsWith("invoke")) {
|
if (line.startsWith("invoke")) {
|
||||||
String[] split = line.split(" ");
|
String[] split = line.split(" ");
|
||||||
String desc = UnicodeUtils.unescape(split[1]);
|
String desc = UnicodeUtils.unescape(null, split[1], true);
|
||||||
String className = UnicodeUtils.unescape(split[2]);
|
String target = split[2];
|
||||||
String[] nameSplit = className.split("/");
|
int index = target.lastIndexOf("/");
|
||||||
String methodName = nameSplit[nameSplit.length - 1];
|
String className = UnicodeUtils.unescape(null, target.substring(0, index), true);
|
||||||
className = className.substring(0, className.length() - methodName.length() - 1);
|
String methodName = UnicodeUtils.unescape(null, target.substring(index + 1), true);
|
||||||
while (className.endsWith("/")) {
|
|
||||||
methodName = "/" + methodName;
|
|
||||||
className = className.substring(0, className.length() - 1);
|
|
||||||
}
|
|
||||||
ClassNode classNode = classNodes.get(getFullName(className));
|
ClassNode classNode = classNodes.get(getFullName(className));
|
||||||
if (classNode == null) {
|
if (classNode == null) {
|
||||||
return;
|
return;
|
||||||
@@ -569,7 +806,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
} else if (line.startsWith("new ")) {
|
} else if (line.startsWith("new ")) {
|
||||||
String[] split = line.split(" ");
|
String[] split = line.split(" ");
|
||||||
String className = UnicodeUtils.unescape(split[1]);
|
String className = UnicodeUtils.unescape(null, split[1], true);
|
||||||
ClassNode classNode = classNodes.get(getFullName(className));
|
ClassNode classNode = classNodes.get(getFullName(className));
|
||||||
if (classNode == null) {
|
if (classNode == null) {
|
||||||
return;
|
return;
|
||||||
@@ -578,15 +815,11 @@ public class Main extends JFrame {
|
|||||||
} else if (line.startsWith("getstatic ") || line.startsWith("putstatic ") || line.startsWith("getfield ")
|
} else if (line.startsWith("getstatic ") || line.startsWith("putstatic ") || line.startsWith("getfield ")
|
||||||
|| line.startsWith("putfield ")) {
|
|| line.startsWith("putfield ")) {
|
||||||
String[] split = line.split(" ");
|
String[] split = line.split(" ");
|
||||||
String desc = UnicodeUtils.unescape(split[1]);
|
String desc = UnicodeUtils.unescape(null, split[1], true);
|
||||||
String className = UnicodeUtils.unescape(split[2]);
|
String target = split[2];
|
||||||
String[] nameSplit = className.split("/");
|
int index = target.lastIndexOf("/");
|
||||||
String fieldName = nameSplit[nameSplit.length - 1];
|
String className = UnicodeUtils.unescape(null, target.substring(0, index), true);
|
||||||
className = className.substring(0, className.length() - fieldName.length() - 1);
|
String fieldName = UnicodeUtils.unescape(null, target.substring(index + 1), true);
|
||||||
while (className.endsWith("/")) {
|
|
||||||
fieldName = "/" + fieldName;
|
|
||||||
className = className.substring(0, className.length() - 1);
|
|
||||||
}
|
|
||||||
ClassNode classNode = classNodes.get(getFullName(className));
|
ClassNode classNode = classNodes.get(getFullName(className));
|
||||||
if (classNode == null) {
|
if (classNode == null) {
|
||||||
return;
|
return;
|
||||||
@@ -650,10 +883,12 @@ public class Main extends JFrame {
|
|||||||
if (s.contains(" extends "))
|
if (s.contains(" extends "))
|
||||||
s = s.substring(0, s.lastIndexOf(" extends "));
|
s = s.substring(0, s.lastIndexOf(" extends "));
|
||||||
String[] split = s.split(" ");
|
String[] split = s.split(" ");
|
||||||
String className = UnicodeUtils.unescape(split[split.length - 1]);
|
String className = UnicodeUtils.unescape(null, split[split.length - 1], true);
|
||||||
renameBox.className = className;
|
renameBox.className = className;
|
||||||
String name = UnicodeUtils.unescape(m.pattern() == renameableFieldPattern ? m.group(2) : m.group(1));
|
String name = UnicodeUtils.unescape(null, m.pattern() == renameableFieldPattern ? m.group(2) : m.group(1),
|
||||||
String desc = UnicodeUtils.unescape(m.pattern() == renameableFieldPattern ? m.group(1) : m.group(2));
|
true);
|
||||||
|
String desc = UnicodeUtils.unescape(null, m.pattern() == renameableFieldPattern ? m.group(1) : m.group(2),
|
||||||
|
true);
|
||||||
renameBox.name = name;
|
renameBox.name = name;
|
||||||
renameBox.desc = desc;
|
renameBox.desc = desc;
|
||||||
renameBox.txtName.setText(name);
|
renameBox.txtName.setText(name);
|
||||||
@@ -694,8 +929,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static int selectFileWithSearch(String s, Object nodeToFind) {
|
public static int selectFileWithSearch(String s, Object nodeToFind) {
|
||||||
if (s != null && (s.endsWith(".class")
|
if (s != null && s.endsWith(".class")) {
|
||||||
|| (s.endsWith(".class/") && fakedFolders.contains(s.substring(0, s.length() - 7))))) {
|
|
||||||
currentNodeName = s;
|
currentNodeName = s;
|
||||||
int lineFound = -1;
|
int lineFound = -1;
|
||||||
ClassNode classNode = classNodes.get(s);
|
ClassNode classNode = classNodes.get(s);
|
||||||
@@ -749,14 +983,49 @@ public class Main extends JFrame {
|
|||||||
if (action == 0) {
|
if (action == 0) {
|
||||||
final File file = fileChooser.getSelectedFile();
|
final File file = fileChooser.getSelectedFile();
|
||||||
saveFolder = file.getParentFile();
|
saveFolder = file.getParentFile();
|
||||||
|
boolean shouldSave = false;
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
int dialogResult = JOptionPane.showConfirmDialog(null, "This file already exists! Overwrite it?",
|
int dialogResult = JOptionPane.showConfirmDialog(null, "This file already exists! Overwrite it?",
|
||||||
"Warning", JOptionPane.YES_NO_OPTION);
|
"Warning", JOptionPane.YES_NO_OPTION);
|
||||||
if (dialogResult == JOptionPane.YES_OPTION) {
|
if (dialogResult == JOptionPane.YES_OPTION) {
|
||||||
save(file, classNodes.values());
|
save(file, classNodes.values());
|
||||||
|
shouldSave = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
shouldSave = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSave)
|
||||||
|
synchronized (treeLock) {
|
||||||
|
if (isChangingFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
isChangingFile = true;
|
||||||
|
try {
|
||||||
|
Main.this.setTitle("ByteEdit - Saving '" + file.getCanonicalPath() + "'");
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Main.this.setTitle("ByteEdit - Saving '" + file.getAbsolutePath() + "'");
|
||||||
|
}
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (treeLock) {
|
||||||
save(file, classNodes.values());
|
save(file, classNodes.values());
|
||||||
|
EventQueue.invokeLater(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (treeLock) {
|
||||||
|
isChangingFile = false;
|
||||||
|
Main.this.setTitle("ByteEdit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
showError(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -794,16 +1063,16 @@ public class Main extends JFrame {
|
|||||||
output.closeEntry();
|
output.closeEntry();
|
||||||
}
|
}
|
||||||
int computeFlags = 0;
|
int computeFlags = 0;
|
||||||
if (optionBox.chckbxComputeFrames.isSelected()) {
|
if (mntmComputeFrames.isSelected()) {
|
||||||
computeFlags |= ClassWriter.COMPUTE_FRAMES;
|
computeFlags |= ClassWriter.COMPUTE_FRAMES;
|
||||||
}
|
}
|
||||||
if (optionBox.chckbxComputeMax.isSelected()) {
|
if (mntmComputeMax.isSelected()) {
|
||||||
computeFlags |= ClassWriter.COMPUTE_MAXS;
|
computeFlags |= ClassWriter.COMPUTE_MAXS;
|
||||||
}
|
}
|
||||||
for (ClassNode element : classes) {
|
for (ClassNode node : classes) {
|
||||||
ClassWriter writer = new ClassWriter(computeFlags);
|
ClassWriter writer = new ClassWriter(computeFlags);
|
||||||
element.accept(writer);
|
node.accept(writer);
|
||||||
output.putNextEntry(new JarEntry(getFullName(element.name)));
|
output.putNextEntry(new JarEntry(getFullName(node.name)));
|
||||||
output.write(writer.toByteArray());
|
output.write(writer.toByteArray());
|
||||||
output.closeEntry();
|
output.closeEntry();
|
||||||
}
|
}
|
||||||
@@ -831,9 +1100,6 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getFullName(String s) {
|
public static String getFullName(String s) {
|
||||||
if (fakedFolders.contains(s))
|
|
||||||
return s + ".class/";
|
|
||||||
else
|
|
||||||
return s + ".class";
|
return s + ".class";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -860,20 +1126,20 @@ public class Main extends JFrame {
|
|||||||
byte[] data = toByteArray(jar.getInputStream(next));
|
byte[] data = toByteArray(jar.getInputStream(next));
|
||||||
if (next.getSize() != 0 && !next.getName().startsWith("META-INF")
|
if (next.getSize() != 0 && !next.getName().startsWith("META-INF")
|
||||||
&& (next.getName().endsWith(".class") || next.getName().endsWith(".class/"))) {
|
&& (next.getName().endsWith(".class") || next.getName().endsWith(".class/"))) {
|
||||||
if ((next.getName().contains("/")
|
|
||||||
? (!next.getName().split("/")[next.getName().split("/").length - 1].contains("$"))
|
|
||||||
: (!next.getName().contains("$")))
|
|
||||||
|| (next.getName().startsWith("$") || next.getName().contains("$$")
|
|
||||||
|| next.getName().endsWith("$"))) {
|
|
||||||
paths.add(next.getName());
|
|
||||||
if (next.getName().endsWith(".class/") && next.getSize() != 0)
|
|
||||||
fakedFolders.add(next.getName().substring(0, next.getName().length() - 7));
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
ClassReader reader = new ClassReader(data);
|
ClassReader reader = new ClassReader(data);
|
||||||
ClassNode node = new ClassNode();
|
ClassNode node = new ClassNode();
|
||||||
reader.accept(node, 0);
|
reader.accept(node, 0);
|
||||||
classNodes.put(next.getName(), node);
|
classNodes.put(getFullName(node.name), node);
|
||||||
|
|
||||||
|
if ((next.getName().contains("/")
|
||||||
|
? (!SLASH.split(next.getName())[SLASH.split(next.getName()).length - 1]
|
||||||
|
.contains("$"))
|
||||||
|
: (!next.getName().contains("$")))
|
||||||
|
|| (next.getName().startsWith("$") || next.getName().contains("$$")
|
||||||
|
|| next.getName().endsWith("$"))) {
|
||||||
|
paths.add(getFullName(node.name));
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
OTHER_FILES.put(next.getName(), data);
|
OTHER_FILES.put(next.getName(), data);
|
||||||
}
|
}
|
||||||
@@ -909,9 +1175,13 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Windows-like sorting (like file explorer)
|
||||||
List<String> tmp = new ArrayList<>(paths);
|
List<String> tmp = new ArrayList<>(paths);
|
||||||
|
|
||||||
List<String> folders = tmp.stream().map(s -> {
|
List<String> folders = tmp.stream().filter(s -> {
|
||||||
|
int c = countSlashes(s, 50);
|
||||||
|
return c > 0 && c < 50;
|
||||||
|
}).map(s -> {
|
||||||
int idx = s.lastIndexOf('/');
|
int idx = s.lastIndexOf('/');
|
||||||
if (idx == s.length() - 1)
|
if (idx == s.length() - 1)
|
||||||
idx = s.lastIndexOf('/', idx - 1);
|
idx = s.lastIndexOf('/', idx - 1);
|
||||||
@@ -943,7 +1213,10 @@ public class Main extends JFrame {
|
|||||||
tmp.addAll(0, folders);
|
tmp.addAll(0, folders);
|
||||||
|
|
||||||
for (String s : tmp) {
|
for (String s : tmp) {
|
||||||
String[] elements = s.split("/");
|
String[] elements = SLASH.split(s, 50);
|
||||||
|
if (elements.length >= 50) {
|
||||||
|
((ByteEditTreeNode) getRoot()).add(new ByteEditTreeNode(s, s));
|
||||||
|
} else {
|
||||||
ByteEditTreeNode currentNode = (ByteEditTreeNode) getRoot();
|
ByteEditTreeNode currentNode = (ByteEditTreeNode) getRoot();
|
||||||
for (int i = 0; i < elements.length; i++) {
|
for (int i = 0; i < elements.length; i++) {
|
||||||
String token = elements[i];
|
String token = elements[i];
|
||||||
@@ -956,6 +1229,7 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ByteEditTreeNode findNode(ByteEditTreeNode parent, String name) {
|
private ByteEditTreeNode findNode(ByteEditTreeNode parent, String name) {
|
||||||
Enumeration<?> e = parent.children();
|
Enumeration<?> e = parent.children();
|
||||||
@@ -967,6 +1241,18 @@ public class Main extends JFrame {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int countSlashes(String s, int max) {
|
||||||
|
int count = 0;
|
||||||
|
for (char c : s.toCharArray()) {
|
||||||
|
if (c == '/') {
|
||||||
|
count++;
|
||||||
|
if (count == max)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FurtherExpandingTreeExpansionListener implements TreeExpansionListener {
|
private static class FurtherExpandingTreeExpansionListener implements TreeExpansionListener {
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
package me.ByteEdit.main;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||||
|
import org.fife.ui.rsyntaxtextarea.Theme;
|
||||||
|
|
||||||
|
import com.formdev.flatlaf.IntelliJTheme;
|
||||||
|
import com.formdev.flatlaf.intellijthemes.FlatArcDarkIJTheme;
|
||||||
|
|
||||||
|
public class ThemeManager {
|
||||||
|
|
||||||
|
private static boolean dark = true;
|
||||||
|
|
||||||
|
private static File file;
|
||||||
|
|
||||||
|
private static Theme rstaThemeDark, rstaThemeLight;
|
||||||
|
|
||||||
|
private static List<RSyntaxTextArea> textAreas = new ArrayList();
|
||||||
|
private static List<JFrame> frames = new ArrayList();
|
||||||
|
|
||||||
|
static {
|
||||||
|
String s = System.getenv("APPDATA");
|
||||||
|
if (s == null)
|
||||||
|
s = System.getProperty("user.home");
|
||||||
|
file = new File(s, "ByteEditTheme.conf");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void save() {
|
||||||
|
try (BufferedWriter wr = new BufferedWriter(new FileWriter(file))) {
|
||||||
|
wr.write(UIManager.getLookAndFeel().getClass().getName() + "\n");
|
||||||
|
wr.write(Boolean.toString(dark));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void load() {
|
||||||
|
try {
|
||||||
|
rstaThemeDark = Theme
|
||||||
|
.load(ThemeManager.class.getClassLoader().getResourceAsStream("org/fife/eclipse_dark.xml"));
|
||||||
|
rstaThemeLight = Theme
|
||||||
|
.load(ThemeManager.class.getClassLoader().getResourceAsStream("org/fife/eclipse.xml"));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
String theme = null;
|
||||||
|
if (file.exists()) {
|
||||||
|
try (BufferedReader read = new BufferedReader(new FileReader(file))) {
|
||||||
|
theme = read.readLine();
|
||||||
|
boolean dark = Boolean.parseBoolean(read.readLine());
|
||||||
|
changeUIManager(theme, dark);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
theme = FlatArcDarkIJTheme.class.getName();
|
||||||
|
changeUIManager(theme, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void changeUIManager(String clazz, Boolean isDark) {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(clazz);
|
||||||
|
LookAndFeel laf = UIManager.getLookAndFeel();
|
||||||
|
boolean nextDark = false;
|
||||||
|
if (laf instanceof IntelliJTheme.ThemeLaf) {
|
||||||
|
IntelliJTheme.ThemeLaf t = (IntelliJTheme.ThemeLaf) laf;
|
||||||
|
nextDark = t.isDark();
|
||||||
|
} else if (isDark != null) {
|
||||||
|
nextDark = isDark.booleanValue();
|
||||||
|
}
|
||||||
|
if (nextDark != dark) {
|
||||||
|
dark = nextDark;
|
||||||
|
applyRSTATheme();
|
||||||
|
}
|
||||||
|
frames.forEach(SwingUtilities::updateComponentTreeUI);
|
||||||
|
save();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyRSTATheme() {
|
||||||
|
Theme theme = dark ? rstaThemeDark : rstaThemeLight;
|
||||||
|
textAreas.forEach(theme::apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerFrames(JFrame frame) {
|
||||||
|
frames.add(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerTextArea(RSyntaxTextArea textArea) {
|
||||||
|
textAreas.add(textArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,8 @@ import java.util.HashSet;
|
|||||||
|
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import me.ByteEdit.edit.HugeStrings;
|
||||||
|
|
||||||
public class ClassUtil {
|
public class ClassUtil {
|
||||||
|
|
||||||
public static final int ACC_PUBLIC = 0x0001;
|
public static final int ACC_PUBLIC = 0x0001;
|
||||||
@@ -522,31 +524,32 @@ public class ClassUtil {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDecompiledValue(Object o, String desc, boolean escapeSpaces) {
|
public static final HashMap<Class, DecompilationInterface> diMap = new HashMap<>();
|
||||||
switch (o.getClass().getName()) {
|
|
||||||
case "java.lang.String": {
|
static {
|
||||||
return "\"" + (escapeSpaces ? UnicodeUtils.escapeWithSpaces((String) o) : UnicodeUtils.escape((String) o))
|
diMap.put(String.class, (o, desc, escapeSpaces, hs) -> "\""
|
||||||
+ "\"";
|
+ (escapeSpaces ? UnicodeUtils.escapeWithSpaces(hs, (String) o) : UnicodeUtils.escape(hs, (String) o))
|
||||||
}
|
+ "\"");
|
||||||
case "java.lang.Integer": {
|
diMap.put(Integer.class,
|
||||||
if (desc.equals("Z")) {
|
(o, desc, escape, hs) -> desc.equals("Z") ? (((int) o) == 0 ? "false" : "true") : o.toString());
|
||||||
return ((int) o) == 0 ? "false" : "true";
|
diMap.put(Long.class, (o, desc, escape, hs) -> o.toString() + "l");
|
||||||
}
|
diMap.put(Float.class, (o, desc, escape, hs) -> o.toString() + "f");
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
case "java.lang.Long": {
|
|
||||||
return o.toString() + "l";
|
|
||||||
}
|
|
||||||
case "java.lang.Float": {
|
|
||||||
return o.toString() + "f";
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return o.toString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDecompiledValue(Object o, String desc) {
|
static interface DecompilationInterface {
|
||||||
return getDecompiledValue(o, desc, false);
|
String apply(Object o, String desc, boolean escape, HugeStrings hs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDecompiledValue(Object o, String desc, boolean escapeSpaces, HugeStrings hs) {
|
||||||
|
DecompilationInterface di = diMap.get(o.getClass());
|
||||||
|
if (di != null)
|
||||||
|
return di.apply(o, desc, escapeSpaces, hs);
|
||||||
|
else
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDecompiledValue(Object o, String desc, HugeStrings hs) {
|
||||||
|
return getDecompiledValue(o, desc, false, hs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getCastedValue(String o, String className) {
|
public static Object getCastedValue(String o, String className) {
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
package me.ByteEdit.utils;
|
package me.ByteEdit.utils;
|
||||||
|
|
||||||
|
import me.ByteEdit.edit.HugeStrings;
|
||||||
|
import me.ByteEdit.edit.HugeStringsRev;
|
||||||
|
|
||||||
public class UnicodeUtils {
|
public class UnicodeUtils {
|
||||||
|
|
||||||
public static String unescape(String s) {
|
public static String unescape(HugeStringsRev hsr, String s) {
|
||||||
|
return unescape(hsr, s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String unescape(HugeStringsRev hsr, String s, boolean force) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (!force && !s.isEmpty() && s.charAt(0) == '#' && s.length() < 12) {
|
||||||
|
try {
|
||||||
|
int id = Integer.parseInt(s.substring(1));
|
||||||
|
return hsr.get(id);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
// Doesn't seem like a HugeString
|
||||||
|
}
|
||||||
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
char unicodeBuffer = 0;
|
char unicodeBuffer = 0;
|
||||||
int stage = 0;
|
int stage = 0;
|
||||||
@@ -78,30 +93,56 @@ public class UnicodeUtils {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String escapeWithSpaces(String s) {
|
public static String escapeWithSpaces(HugeStrings hs, String s) {
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
s = escape(s).replace(" ", "\\u0020");
|
if (s.length() > HugeStrings.THRESHOLD) {
|
||||||
if (s.startsWith("/")) {
|
return hs.onString(s);
|
||||||
s = "\\u002F" + s.substring(1);
|
|
||||||
}
|
|
||||||
if (s.endsWith("/")) {
|
|
||||||
s = s.substring(0, s.length() - 1) + "\\u002F";
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String escape(String s) {
|
|
||||||
if (s == null) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (char c : s.toCharArray()) {
|
char[] arr = s.toCharArray();
|
||||||
if (isPrintable(c)) {
|
int i = 0;
|
||||||
sb.append(c);
|
int len = arr.length;
|
||||||
} else {
|
boolean addSlash = false;
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
if (arr[0] == '/') {
|
||||||
|
sb.append("\\u002F");
|
||||||
|
i++;
|
||||||
|
} else if (arr[0] == '#') {
|
||||||
|
sb.append("\\u0023");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (arr[len - 1] == '/') {
|
||||||
|
addSlash = true;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i < len; i++) {
|
||||||
|
char c = arr[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'Ä':
|
||||||
|
case 'ä':
|
||||||
|
case 'Ö':
|
||||||
|
case 'ö':
|
||||||
|
case 'Ü':
|
||||||
|
case 'ü':
|
||||||
|
case 'ß':
|
||||||
|
case '€':
|
||||||
|
case '©':
|
||||||
|
case '®':
|
||||||
|
case '«':
|
||||||
|
case '»':
|
||||||
|
case '§':
|
||||||
|
case '£':
|
||||||
|
case '¥':
|
||||||
|
sb.append(c);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
sb.append("\\u0020");
|
||||||
|
break;
|
||||||
case '\b':
|
case '\b':
|
||||||
sb.append("\\b");
|
sb.append("\\b");
|
||||||
break;
|
break;
|
||||||
@@ -124,14 +165,40 @@ public class UnicodeUtils {
|
|||||||
sb.append("\\\\");
|
sb.append("\\\\");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (c > ' ' && c <= '~') {
|
||||||
|
sb.append(c);
|
||||||
|
} else {
|
||||||
sb.append(String.format("\\u%04X", (int) c));
|
sb.append(String.format("\\u%04X", (int) c));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addSlash)
|
||||||
|
sb.append("\\u002F");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPrintable(char c) {
|
public static String escape(HugeStrings hs, String s) {
|
||||||
|
return escape(hs, s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escape(HugeStrings hs, String s, boolean force) {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (!force && s.length() > HugeStrings.THRESHOLD) {
|
||||||
|
return hs.onString(s);
|
||||||
|
}
|
||||||
|
char[] arr = s.toCharArray();
|
||||||
|
StringBuilder sb = new StringBuilder(arr.length);
|
||||||
|
int i = 0;
|
||||||
|
if (arr.length > 0 && arr[0] == '#') {
|
||||||
|
sb.append("\\u0023");
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
for (; i < arr.length; i++) {
|
||||||
|
char c = arr[i];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'Ä':
|
case 'Ä':
|
||||||
case 'ä':
|
case 'ä':
|
||||||
@@ -148,13 +215,39 @@ public class UnicodeUtils {
|
|||||||
case '§':
|
case '§':
|
||||||
case '£':
|
case '£':
|
||||||
case '¥':
|
case '¥':
|
||||||
return true;
|
sb.append(c);
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
sb.append("\\b");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
sb.append("\\t");
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
sb.append("\\n");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
sb.append("\\r");
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
sb.append("\\f");
|
||||||
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
|
sb.append("\\\"");
|
||||||
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
return false;
|
sb.append("\\\\");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return c >= ' ' && c <= '~';
|
if (c >= ' ' && c <= '~') {
|
||||||
|
sb.append(c);
|
||||||
|
} else {
|
||||||
|
sb.append(String.format("\\u%04X", (int) c));
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -403,6 +403,9 @@ public class TokenImpl implements Token {
|
|||||||
int last = getOffset();
|
int last = getOffset();
|
||||||
FontMetrics fm = null;
|
FontMetrics fm = null;
|
||||||
while (token != null && token.isPaintable()) {
|
while (token != null && token.isPaintable()) {
|
||||||
|
if (token.textCount > 10000) {
|
||||||
|
return getOffset() + (int) (x / 7);
|
||||||
|
}
|
||||||
fm = textArea.getFontMetricsForTokenType(token.getType());
|
fm = textArea.getFontMetricsForTokenType(token.getType());
|
||||||
char[] text = token.text;
|
char[] text = token.text;
|
||||||
int start = token.textOffset;
|
int start = token.textOffset;
|
||||||
@@ -786,6 +789,13 @@ public class TokenImpl implements Token {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
text = null;
|
||||||
|
offset = -1;
|
||||||
|
type = Token.NULL;
|
||||||
|
nextToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in new issue
Block a user