Added renaming (CTRL + R) and field goto (CTRL + G)

This commit is contained in:
SuspiciousActivity committed 2018-11-24 14:08:54 +01:00
1 parent 30c6a7a69d
commit 1c887abb73
9 files changed
+436 -91

No files matched your search

+3 -1
View File
@@ -12,6 +12,8 @@ To open a class, press CTRL + T.
To change settings like auto-computation of stack frames and max locals/stack press CTRL + O. To change settings like auto-computation of stack frames and max locals/stack press CTRL + O.
To go to the method definition of the selected line's invoke-method press CTRL + G. To go to the field/method definition in the selected line press CTRL + G.
To (un-)escape unicode characters, press CTRL + U. To (un-)escape unicode characters, press CTRL + U.
To rename a field/method with attention to references in the selected line, press CTRL + R.
+2 -23
View File
@@ -1,6 +1,5 @@
package me.ByteEdit.boxes; package me.ByteEdit.boxes;
import java.awt.EventQueue;
import java.awt.Toolkit; import java.awt.Toolkit;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
@@ -10,31 +9,11 @@ import javax.swing.UIManager;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
public class OptionBox extends JFrame { public class OptionBox extends JFrame {
private JPanel contentPane; private JPanel contentPane;
public JCheckBox chckbxComputeFrames; public JCheckBox chckbxComputeFrames;
public JCheckBox chckbxComputeMax; public JCheckBox chckbxComputeMax;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
OptionBox frame = new OptionBox();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public OptionBox() { public OptionBox() {
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+232
View File
@@ -0,0 +1,232 @@
package me.ByteEdit.boxes;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import me.ByteEdit.edit.Disassembler;
import me.ByteEdit.main.Main;
import me.ByteEdit.utils.ClassUtil;
import me.ByteEdit.utils.UnicodeUtils;
public class RenameBox extends JFrame {
private JPanel contentPane;
public JTextField txtName;
public JTextField txtDesc;
public String className;
public String name;
public String desc;
public RenameBox() {
setResizable(false);
setTitle("Rename");
setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
setBounds((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 225),
(int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 150), 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JLabel lblName = new JLabel("Name");
lblName.setBounds(10, 11, 33, 14);
contentPane.add(lblName);
JLabel lblDesc = new JLabel("Desc");
lblDesc.setBounds(10, 36, 33, 14);
contentPane.add(lblDesc);
txtName = new JTextField();
txtName.setBounds(53, 8, 381, 20);
contentPane.add(txtName);
txtName.setColumns(10);
txtDesc = new JTextField();
txtDesc.setColumns(10);
txtDesc.setBounds(53, 36, 381, 20);
contentPane.add(txtDesc);
JButton btnRename = new JButton("Rename");
btnRename.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (className == null) {
JOptionPane.showMessageDialog(null, "ClassName not set!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
if (name == null) {
JOptionPane.showMessageDialog(null, "Name not set!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
if (desc == null) {
JOptionPane.showMessageDialog(null, "Desc not set!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
ClassNode clazz = Main.classNodes.get(className.replace("/", ".") + ".class");
if (clazz == null) {
JOptionPane.showMessageDialog(null, "ClassNode not found!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
String newName = UnicodeUtils.unescape(txtName.getText());
String newDesc = UnicodeUtils.unescape(txtDesc.getText());
if (ClassUtil.isObjectClassMethod(newName, newDesc, true)) {
JOptionPane.showMessageDialog(null, "Invalid name!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
if (desc.startsWith("(")) {
if (newDesc.startsWith("(")) { // method
ClassNode lastHit = clazz;
while (clazz != null && clazz.superName != null) {
ClassNode tmp = Main.classNodes.get(clazz.superName.replace("/", ".") + ".class");
if (tmp != null) {
boolean found = false;
for (MethodNode mn : clazz.methods) {
if (mn.name.equals(name) && mn.desc.equals(desc)) {
lastHit = clazz;
clazz = tmp;
found = true;
break;
}
}
if (!found) {
clazz = tmp;
lastHit = null;
}
} else {
break;
}
}
if (lastHit != null) {
clazz = lastHit;
}
LinkedList<MethodNode> methodsToRename = new LinkedList<>();
LinkedList<MethodInsnNode> minsToRename = new LinkedList<>();
for (ClassNode cn : Main.classNodes.values()) {
boolean extendsMyClass = cn == clazz;
if (!extendsMyClass) {
ClassNode checkCN = cn;
while (checkCN != null && checkCN.superName != null) {
if (clazz.name.equals(checkCN.superName)) {
extendsMyClass = true;
break;
}
ClassNode tmp = Main.classNodes.get(checkCN.superName.replace("/", ".") + ".class");
if (tmp != null) {
checkCN = tmp;
} else {
break;
}
}
}
for (MethodNode mn : cn.methods) {
if (extendsMyClass) {
if (mn.name.equals(newName) && mn.desc.equals(newDesc)) {
JOptionPane.showMessageDialog(null, "Method already exists in " + cn.name + "!", "Error!",
JOptionPane.ERROR_MESSAGE);
return;
}
if (mn.name.equals(name) && mn.desc.equals(desc)) {
methodsToRename.add(mn);
}
}
for (AbstractInsnNode ain : mn.instructions.toArray()) {
if (ain instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode) ain;
if (min.name.equals(name) && min.desc.equals(desc) && min.owner.equals(clazz.name)) {
minsToRename.add(min);
}
}
}
}
}
for (MethodNode mn : methodsToRename) {
mn.name = newName;
mn.desc = newDesc;
}
for (MethodInsnNode min : minsToRename) {
min.name = newName;
min.desc = newDesc;
}
} else {
JOptionPane.showMessageDialog(null, "New Desc is not a method desc!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
} else {
if (!newDesc.startsWith("(")) { // field
FieldNode currentFN = null;
for (FieldNode fn : clazz.fields) {
if (fn.name.equals(newName) && fn.desc.equals(newDesc)) {
JOptionPane.showMessageDialog(null, "Field already exists!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
if (fn.name.equals(name) && fn.desc.equals(desc)) {
currentFN = fn;
}
}
if (currentFN == null) {
JOptionPane.showMessageDialog(null, "Field not found?!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
currentFN.name = newName;
currentFN.desc = newDesc;
for (ClassNode cn : Main.classNodes.values()) {
for (MethodNode mn : cn.methods) {
for (AbstractInsnNode ain : mn.instructions.toArray()) {
if (ain instanceof FieldInsnNode) {
FieldInsnNode fin = (FieldInsnNode) ain;
if (fin.name.equals(name) && fin.desc.equals(desc) && fin.owner.equals(className)) {
fin.name = newName;
fin.desc = newDesc;
}
}
}
}
}
} else {
JOptionPane.showMessageDialog(null, "New Desc is not a field desc!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
}
try { // refresh
ClassNode classNode = Main.classNodes.get(Main.currentNodeName);
int prev = Main.txtByteEditView.getCaretPosition();
String dis = Disassembler.disassemble(classNode);
String substr = Main.currentNodeName.substring(0, Main.currentNodeName.length() - 6);
for (String key : Main.classNodes.keySet()) {
if (key.contains("$")) {
String[] split = key.split("\\$");
if (split[0].equals(substr)) {
dis += "\n" + Disassembler.disassemble(Main.classNodes.get(key));
}
}
}
Main.txtByteEditView.setText(dis);
Main.txtByteEditView.setCaretPosition(prev);
} catch (Exception e2) {
e2.printStackTrace();
}
name = newName;
desc = newDesc;
}
});
btnRename.setBounds(345, 237, 89, 23);
contentPane.add(btnRename);
}
}
+11 -14
View File
@@ -20,15 +20,12 @@ import javax.swing.border.EmptyBorder;
import me.ByteEdit.main.Main; import me.ByteEdit.main.Main;
public class SearchBox extends JFrame { public class SearchBox extends JFrame {
public JPanel contentPane; public JPanel contentPane;
public JTextField txtFind; public JTextField txtFind;
public JTextField txtReplace; public JTextField txtReplace;
public JCheckBox chckbxCaseSensitive; public JCheckBox chckbxCaseSensitive;
/**
* Create the frame.
*/
public SearchBox() { public SearchBox() {
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
@@ -50,7 +47,7 @@ public class SearchBox extends JFrame {
txtFind = new JTextField(); txtFind = new JTextField();
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
txtFind.registerKeyboardAction(new ActionListener() { txtFind.registerKeyboardAction(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
find(); find();
@@ -71,7 +68,7 @@ public class SearchBox extends JFrame {
contentPane.add(chckbxCaseSensitive); contentPane.add(chckbxCaseSensitive);
JButton btnFind = new JButton("Find"); JButton btnFind = new JButton("Find");
btnFind.addActionListener(new ActionListener() { btnFind.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
find(); find();
} }
@@ -80,7 +77,7 @@ public class SearchBox extends JFrame {
contentPane.add(btnFind); contentPane.add(btnFind);
JButton btnReplacefind = new JButton("Replace/Find"); JButton btnReplacefind = new JButton("Replace/Find");
btnReplacefind.addActionListener(new ActionListener() { btnReplacefind.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
replaceFind(); replaceFind();
} }
@@ -89,7 +86,7 @@ public class SearchBox extends JFrame {
contentPane.add(btnReplacefind); contentPane.add(btnReplacefind);
JButton btnReplace = new JButton("Replace"); JButton btnReplace = new JButton("Replace");
btnReplace.addActionListener(new ActionListener() { btnReplace.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
replace(); replace();
} }
@@ -98,7 +95,7 @@ public class SearchBox extends JFrame {
contentPane.add(btnReplace); contentPane.add(btnReplace);
JButton btnReplaceAll = new JButton("Replace All"); JButton btnReplaceAll = new JButton("Replace All");
btnReplaceAll.addActionListener(new ActionListener() { btnReplaceAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
replaceAll(); replaceAll();
} }
@@ -106,7 +103,7 @@ public class SearchBox extends JFrame {
btnReplaceAll.setBounds(130, 184, 110, 23); btnReplaceAll.setBounds(130, 184, 110, 23);
contentPane.add(btnReplaceAll); contentPane.add(btnReplaceAll);
} }
public void find() { public void find() {
int startPos = Main.txtByteEditView.getCaretPosition(); int startPos = Main.txtByteEditView.getCaretPosition();
String toFind = txtFind.getText(); String toFind = txtFind.getText();
@@ -123,19 +120,19 @@ public class SearchBox extends JFrame {
} }
Main.txtByteEditView.select(startPos + index, startPos + index + toFind.length()); Main.txtByteEditView.select(startPos + index, startPos + index + toFind.length());
} }
public void replaceFind() { public void replaceFind() {
replace(); replace();
find(); find();
} }
public void replace() { public void replace() {
String txt = Main.txtByteEditView.getText(); String txt = Main.txtByteEditView.getText();
int startPos = Main.txtByteEditView.getSelectionStart(); int startPos = Main.txtByteEditView.getSelectionStart();
Main.txtByteEditView.replaceSelection(txtReplace.getText()); Main.txtByteEditView.replaceSelection(txtReplace.getText());
Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length()); Main.txtByteEditView.select(startPos, startPos + txtReplace.getText().length());
} }
public void replaceAll() { public void replaceAll() {
String toFind = txtFind.getText(); String toFind = txtFind.getText();
String toReplace = txtReplace.getText(); String toReplace = txtReplace.getText();
+13 -16
View File
@@ -21,13 +21,10 @@ import javax.swing.event.ListSelectionListener;
import me.ByteEdit.main.Main; import me.ByteEdit.main.Main;
public class TypeOpenBox extends JFrame { public class TypeOpenBox extends JFrame {
public JPanel contentPane; public JPanel contentPane;
public JTextField txtSearch; public JTextField txtSearch;
/**
* Create the frame.
*/
public TypeOpenBox() { public TypeOpenBox() {
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
@@ -43,11 +40,11 @@ public class TypeOpenBox extends JFrame {
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane); setContentPane(contentPane);
contentPane.setLayout(null); contentPane.setLayout(null);
DefaultListModel<String> model = new DefaultListModel<>(); DefaultListModel<String> model = new DefaultListModel<>();
JList<String> list = new JList(model); JList<String> list = new JList(model);
list.addListSelectionListener(new ListSelectionListener() { list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) { public void valueChanged(ListSelectionEvent e) {
String val = list.getSelectedValue(); String val = list.getSelectedValue();
if (val != null && !val.equals(Main.currentNodeName)) { if (val != null && !val.equals(Main.currentNodeName)) {
@@ -55,10 +52,10 @@ public class TypeOpenBox extends JFrame {
} }
} }
}); });
txtSearch = new JTextField(); txtSearch = new JTextField();
txtSearch.addActionListener(new ActionListener() { txtSearch.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
if (model.size() == 1) { if (model.size() == 1) {
list.setSelectedIndex(0); list.setSelectedIndex(0);
@@ -66,19 +63,19 @@ public class TypeOpenBox extends JFrame {
} }
}); });
txtSearch.getDocument().addDocumentListener(new DocumentListener() { txtSearch.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) { public void changedUpdate(DocumentEvent e) {
updateList(); updateList();
} }
public void removeUpdate(DocumentEvent e) { public void removeUpdate(DocumentEvent e) {
updateList(); updateList();
} }
public void insertUpdate(DocumentEvent e) { public void insertUpdate(DocumentEvent e) {
updateList(); updateList();
} }
public void updateList() { public void updateList() {
model.clear(); model.clear();
if (txtSearch.getText().isEmpty()) { if (txtSearch.getText().isEmpty()) {
@@ -107,13 +104,13 @@ public class TypeOpenBox extends JFrame {
txtSearch.setBounds(10, 11, 374, 20); txtSearch.setBounds(10, 11, 374, 20);
contentPane.add(txtSearch); contentPane.add(txtSearch);
txtSearch.setColumns(10); txtSearch.setColumns(10);
JScrollPane scrollPane = new JScrollPane(); JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 46, 374, 194); scrollPane.setBounds(10, 46, 374, 194);
contentPane.add(scrollPane); contentPane.add(scrollPane);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane.setViewportView(list); scrollPane.setViewportView(list);
} }
} }
+9 -12
View File
@@ -16,12 +16,9 @@ import me.ByteEdit.main.Main;
import me.ByteEdit.utils.UnicodeUtils; import me.ByteEdit.utils.UnicodeUtils;
public class UnicodeBox extends JFrame { public class UnicodeBox extends JFrame {
private JPanel contentPane; private JPanel contentPane;
/**
* Create the frame.
*/
public UnicodeBox() { public UnicodeBox() {
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
@@ -37,12 +34,12 @@ public class UnicodeBox extends JFrame {
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane); setContentPane(contentPane);
contentPane.setLayout(null); contentPane.setLayout(null);
JTextArea textArea = new JTextArea(); JTextArea textArea = new JTextArea();
JButton btnEscape = new JButton("Escape"); JButton btnEscape = new JButton("Escape");
btnEscape.addActionListener(new ActionListener() { btnEscape.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try { try {
textArea.setText(UnicodeUtils.escape(textArea.getText())); textArea.setText(UnicodeUtils.escape(textArea.getText()));
@@ -53,10 +50,10 @@ public class UnicodeBox extends JFrame {
}); });
btnEscape.setBounds(10, 137, 89, 23); btnEscape.setBounds(10, 137, 89, 23);
contentPane.add(btnEscape); contentPane.add(btnEscape);
JButton btnUnescape = new JButton("Unescape"); JButton btnUnescape = new JButton("Unescape");
btnUnescape.addActionListener(new ActionListener() { btnUnescape.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
try { try {
textArea.setText(UnicodeUtils.unescape(textArea.getText())); textArea.setText(UnicodeUtils.unescape(textArea.getText()));
@@ -67,11 +64,11 @@ public class UnicodeBox extends JFrame {
}); });
btnUnescape.setBounds(195, 137, 89, 23); btnUnescape.setBounds(195, 137, 89, 23);
contentPane.add(btnUnescape); contentPane.add(btnUnescape);
JScrollPane scrollPane = new JScrollPane(); JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(10, 11, 274, 115); scrollPane.setBounds(10, 11, 274, 115);
contentPane.add(scrollPane); contentPane.add(scrollPane);
scrollPane.setViewportView(textArea); scrollPane.setViewportView(textArea);
} }
} }
+5 -2
View File
@@ -70,7 +70,7 @@ public class Disassembler {
} }
public static DisassembleTuple disassemble(ClassNode classNode, MethodNode methodToFind) { public static DisassembleTuple disassemble(ClassNode classNode, Object nodeToFind) {
if (classNode == null) { if (classNode == null) {
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!");
} }
@@ -228,6 +228,9 @@ public class Disassembler {
s += "\n"; s += "\n";
} }
} }
if (fn.equals(nodeToFind)) {
lineFound = s.split("\\n").length;
}
s += "\t" + ClassUtil.getAccessFlagsFull(fn.access).replace("varargs", "transient") + UnicodeUtils.escapeWithSpaces(fn.desc) + " " s += "\t" + ClassUtil.getAccessFlagsFull(fn.access).replace("varargs", "transient") + UnicodeUtils.escapeWithSpaces(fn.desc) + " "
+ UnicodeUtils.escapeWithSpaces(fn.name); + UnicodeUtils.escapeWithSpaces(fn.name);
if (fn.value != null) { if (fn.value != null) {
@@ -303,7 +306,7 @@ public class Disassembler {
s += "\n"; s += "\n";
} }
} }
if (mn.equals(methodToFind)) { if (mn.equals(nodeToFind)) {
lineFound = s.split("\\n").length; lineFound = s.split("\\n").length;
} }
s += "\t" + ClassUtil.getAccessFlagsFull(mn.access) + UnicodeUtils.escapeWithSpaces(mn.name) + " " s += "\t" + ClassUtil.getAccessFlagsFull(mn.access) + UnicodeUtils.escapeWithSpaces(mn.name) + " "
+109 -5
View File
@@ -30,6 +30,7 @@ import java.util.Map.Entry;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.swing.JComponent; import javax.swing.JComponent;
@@ -67,9 +68,11 @@ import org.fife.ui.rtextarea.RTextScrollPane;
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;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.MethodNode;
import me.ByteEdit.boxes.OptionBox; import me.ByteEdit.boxes.OptionBox;
import me.ByteEdit.boxes.RenameBox;
import me.ByteEdit.boxes.SearchBox; import me.ByteEdit.boxes.SearchBox;
import me.ByteEdit.boxes.TypeOpenBox; import me.ByteEdit.boxes.TypeOpenBox;
import me.ByteEdit.boxes.UnicodeBox; import me.ByteEdit.boxes.UnicodeBox;
@@ -94,6 +97,7 @@ public class Main extends JFrame {
public static TypeOpenBox typeOpenBox; public static TypeOpenBox typeOpenBox;
public static OptionBox optionBox; public static OptionBox optionBox;
public static UnicodeBox unicodeBox; public static UnicodeBox unicodeBox;
public static RenameBox renameBox;
public static JTree tree; public static JTree tree;
public static RTextScrollPane scrollPane_ByteEdit; public static RTextScrollPane scrollPane_ByteEdit;
public static Theme theme; public static Theme theme;
@@ -169,6 +173,7 @@ public class Main extends JFrame {
typeOpenBox = new TypeOpenBox(); typeOpenBox = new TypeOpenBox();
optionBox = new OptionBox(); optionBox = new OptionBox();
unicodeBox = new UnicodeBox(); unicodeBox = new UnicodeBox();
renameBox = new RenameBox();
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),
@@ -267,6 +272,13 @@ public class Main extends JFrame {
} catch (IOException e1) { } catch (IOException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
txtByteEditView.setText("");
currentNodeName = null;
searchBox.setVisible(false);
typeOpenBox.setVisible(false);
optionBox.setVisible(false);
unicodeBox.setVisible(false);
renameBox.setVisible(false);
isChangingFile = false; isChangingFile = false;
} }
dtde.dropComplete(true); dtde.dropComplete(true);
@@ -300,7 +312,7 @@ public class Main extends JFrame {
@Override @Override
public void keyReleased(KeyEvent e) { public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == 116 && currentNodeName != null) { if (e.getKeyCode() == 116 && currentNodeName != null) { // F5
try { try {
ClassNode classNode = classNodes.get(currentNodeName); ClassNode classNode = classNodes.get(currentNodeName);
int prev = txtByteEditView.getCaretPosition(); int prev = txtByteEditView.getCaretPosition();
@@ -316,7 +328,9 @@ public class Main extends JFrame {
} }
txtByteEditView.setText(dis); txtByteEditView.setText(dis);
txtByteEditView.setCaretPosition(prev); txtByteEditView.setCaretPosition(prev);
} catch (Exception e2) {} } catch (Exception e2) {
e2.printStackTrace();
}
} }
} }
}); });
@@ -326,6 +340,7 @@ public class Main extends JFrame {
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 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);
// global // global
txtByteEditView.registerKeyboardAction(new ActionListener() { txtByteEditView.registerKeyboardAction(new ActionListener() {
@@ -385,6 +400,17 @@ public class Main extends JFrame {
} }
} }
}, ctrlG, JComponent.WHEN_FOCUSED); }, ctrlG, JComponent.WHEN_FOCUSED);
txtByteEditView.registerKeyboardAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
renameSelected();
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}, 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);
@@ -445,6 +471,84 @@ public class Main extends JFrame {
return; return;
} }
selectFile(className + ".class"); selectFile(className + ".class");
} else if (line.startsWith("getstatic ") || line.startsWith("putstatic ") || line.startsWith("getfield ") || line.startsWith("putfield ")) {
String[] split = line.split(" ");
String desc = UnicodeUtils.unescape(split[1]);
String className = UnicodeUtils.unescape(split[2]);
String[] nameSplit = className.split("/");
String fieldName = nameSplit[nameSplit.length - 1];
className = className.substring(0, className.length() - fieldName.length() - 1);
ClassNode classNode = classNodes.get(className + ".class");
if (classNode == null) {
return;
}
for (FieldNode fn : classNode.fields) {
if (fn.name.equals(fieldName) && fn.desc.equals(desc)) {
while (classNode.outerClass != null) {
classNode = classNodes.get(classNode.outerClass + ".class");
}
int lineFound = selectFileWithSearch(classNode.name + ".class", fn);
if (lineFound != -1) {
Main.txtByteEditView.setCaretPosition(Main.txtByteEditView.getLineStartOffset(lineFound));
}
break;
}
}
}
}
private final Pattern renameableFieldPattern = Pattern.compile("^\t(?:[a-z]+ |0x[0-9a-fA-F]+ )*?(\\[*(?:V|Z|C|B|S|I|F|J|D|L.+?;)) ([^ ]+) ?.*");
private final Pattern renameableMethodPattern = Pattern
.compile("^\t(?:[a-z]+ |0x[0-9a-fA-F]+ )*?([^ ]+) (\\((?:\\[*(?:V|Z|C|B|S|I|F|J|D|L.+?;))*\\)[^ ]+) .*\\{");
public void renameSelected() throws BadLocationException {
int lineStart = txtByteEditView.getLineStartOffsetOfCurrentLine();
int lineEnd = txtByteEditView.getLineEndOffsetOfCurrentLine() - 1;
String line = txtByteEditView.getText(lineStart, lineEnd - lineStart);
Matcher m = renameableFieldPattern.matcher(line);
if (m.find()) {
setRenameInfo(m, lineEnd);
} else {
m = renameableMethodPattern.matcher(line);
if (m.find()) {
if (ClassUtil.isObjectClassMethod(m.group(1), m.group(2), false)) {
JOptionPane.showMessageDialog(null, "This method can not be renamed!", "Error!", JOptionPane.ERROR_MESSAGE);
return;
}
setRenameInfo(m, lineEnd);
}
}
}
public void setRenameInfo(Matcher m, int lineEnd) throws BadLocationException {
String[] arr = txtByteEditView.getText(0, lineEnd).split("\n");
int lastClassLine = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i].startsWith("// #Class")) {
lastClassLine = i;
}
}
while (lastClassLine < arr.length && arr[lastClassLine].startsWith("// ")) {
lastClassLine++;
}
if (lastClassLine < arr.length) {
String s = arr[lastClassLine];
s = s.substring(0, s.length() - 2);
if (s.contains(" implements "))
s = s.substring(0, s.lastIndexOf(" implements "));
if (s.contains(" extends "))
s = s.substring(0, s.lastIndexOf(" extends "));
String[] split = s.split(" ");
String className = UnicodeUtils.unescape(split[split.length - 1]);
renameBox.className = className;
String name = m.pattern() == renameableFieldPattern ? m.group(2) : m.group(1);
String desc = m.pattern() == renameableFieldPattern ? m.group(1) : m.group(2);
renameBox.name = name;
renameBox.desc = desc;
renameBox.txtName.setText(name);
renameBox.txtDesc.setText(desc);
renameBox.setVisible(true);
renameBox.txtName.requestFocusInWindow();
} }
} }
@@ -463,13 +567,13 @@ public class Main extends JFrame {
} }
} }
public static int selectFileWithSearch(String s, MethodNode methodToFind) { public static int selectFileWithSearch(String s, Object nodeToFind) {
if (s.endsWith(".class")) { if (s.endsWith(".class")) {
currentNodeName = s; currentNodeName = s;
int lineFound = -1; int lineFound = -1;
ClassNode classNode = classNodes.get(s); ClassNode classNode = classNodes.get(s);
String dis = ""; String dis = "";
DisassembleTuple tuple = Disassembler.disassemble(classNode, methodToFind); DisassembleTuple tuple = Disassembler.disassemble(classNode, nodeToFind);
if (tuple.getLine() != -1) { if (tuple.getLine() != -1) {
lineFound = dis.split("\\n").length + tuple.getLine() - 1; lineFound = dis.split("\\n").length + tuple.getLine() - 1;
} }
@@ -479,7 +583,7 @@ public class Main extends JFrame {
if (key.contains("$")) { if (key.contains("$")) {
String[] split = key.split("\\$"); String[] split = key.split("\\$");
if (split[0].equals(substr)) { if (split[0].equals(substr)) {
tuple = Disassembler.disassemble(classNodes.get(key), methodToFind); tuple = Disassembler.disassemble(classNodes.get(key), nodeToFind);
if (tuple.getLine() != -1) { if (tuple.getLine() != -1) {
lineFound = dis.split("\\n").length + tuple.getLine() + 1; lineFound = dis.split("\\n").length + tuple.getLine() + 1;
} }
+52 -18
View File
@@ -7,7 +7,7 @@ import java.util.HashSet;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
public class ClassUtil { public class ClassUtil {
public static final int ACC_PUBLIC = 0x0001; public static final int ACC_PUBLIC = 0x0001;
public static final int ACC_PRIVATE = 0x0002; public static final int ACC_PRIVATE = 0x0002;
public static final int ACC_PROTECTED = 0x0004; public static final int ACC_PROTECTED = 0x0004;
@@ -25,7 +25,41 @@ public class ClassUtil {
public static final int ACC_ANNOTATION = 0x2000; public static final int ACC_ANNOTATION = 0x2000;
public static final int ACC_ENUM = 0x4000; public static final int ACC_ENUM = 0x4000;
public static final int ACC_MANDATED = 0x8000; public static final int ACC_MANDATED = 0x8000;
public static boolean isObjectClassMethod(String name, String desc, boolean forbidInits) {
switch (name) {
case "<init>":
case "<clinit>":
if (forbidInits) {
return true;
}
case "notifyAll":
case "notify":
if (desc.equals("()V")) {
return true;
}
break;
case "wait":
if (desc.equals("()V") || desc.equals("(J)V") || desc.equals("(JI)V")) {
return true;
}
break;
case "equals":
if (desc.equals("(Ljava/lang/Object;)Z")) {
return true;
}
break;
case "hashCode":
if (desc.equals("()I")) {
return true;
}
break;
default:
break;
}
return false;
}
public static int getIDFromClassNameForType(String s) { public static int getIDFromClassNameForType(String s) {
s = s.toUpperCase(); s = s.toUpperCase();
switch (s) { switch (s) {
@@ -64,7 +98,7 @@ public class ClassUtil {
} }
} }
} }
public static String getClassNameFromType(Type type) { public static String getClassNameFromType(Type type) {
switch (type.getSort()) { switch (type.getSort()) {
case 0: { case 0: {
@@ -103,7 +137,7 @@ public class ClassUtil {
} }
return Integer.toString(type.getSort()); return Integer.toString(type.getSort());
} }
public static String getArrayTypeByID(int id) { public static String getArrayTypeByID(int id) {
switch (id) { switch (id) {
case 4: case 4:
@@ -126,7 +160,7 @@ public class ClassUtil {
return Integer.toString(id); return Integer.toString(id);
} }
} }
public static int getArrayIDByType(String type) { public static int getArrayIDByType(String type) {
switch (type) { switch (type) {
case "Z": case "Z":
@@ -149,7 +183,7 @@ public class ClassUtil {
return Integer.parseInt(type); return Integer.parseInt(type);
} }
} }
public static String getAccessFlagsClass(int access) { public static String getAccessFlagsClass(int access) {
String s = ""; String s = "";
if ((ACC_PUBLIC & access) != 0) { if ((ACC_PUBLIC & access) != 0) {
@@ -175,7 +209,7 @@ public class ClassUtil {
} }
return s; return s;
} }
public static String getAccessFlagsFull(int access) { public static String getAccessFlagsFull(int access) {
int acc = 0; int acc = 0;
String s = ""; String s = "";
@@ -249,7 +283,7 @@ public class ClassUtil {
return "0x" + Integer.toHexString(access) + " "; return "0x" + Integer.toHexString(access) + " ";
} }
} }
/** /**
* @return { JavaType, Import } * @return { JavaType, Import }
*/ */
@@ -308,7 +342,7 @@ public class ClassUtil {
} }
return new String[] { type, importName }; return new String[] { type, importName };
} }
/** /**
* @return { ReturnValue, ParameterValues, Imports } getrennt durch ";" * @return { ReturnValue, ParameterValues, Imports } getrennt durch ";"
*/ */
@@ -411,7 +445,7 @@ public class ClassUtil {
} }
return new String[] { returnType[0], parameterStr, importStr }; return new String[] { returnType[0], parameterStr, importStr };
} }
public static int countMethodParams(String desc) { public static int countMethodParams(String desc) {
int count = 0; int count = 0;
String parameterType = desc.split("\\)")[0].substring(1); String parameterType = desc.split("\\)")[0].substring(1);
@@ -446,7 +480,7 @@ public class ClassUtil {
} }
return count; return count;
} }
public static String getDecompiledValue(Object o, String desc, boolean escapeSpaces) { public static String getDecompiledValue(Object o, String desc, boolean escapeSpaces) {
switch (o.getClass().getName()) { switch (o.getClass().getName()) {
case "java.lang.String": { case "java.lang.String": {
@@ -468,11 +502,11 @@ public class ClassUtil {
return o.toString(); return o.toString();
} }
} }
public static String getDecompiledValue(Object o, String desc) { public static String getDecompiledValue(Object o, String desc) {
return getDecompiledValue(o, desc, false); return getDecompiledValue(o, desc, false);
} }
public static Object getCastedValue(String o, String className) { public static Object getCastedValue(String o, String className) {
switch (className) { switch (className) {
case "java/lang/String": { case "java/lang/String": {
@@ -503,7 +537,7 @@ public class ClassUtil {
return o.toString(); return o.toString();
} }
} }
public static String getSimpleDesc(String type) { public static String getSimpleDesc(String type) {
String desc = ""; String desc = "";
for (int i = 0; i < countArraySize(type); i++) { for (int i = 0; i < countArraySize(type); i++) {
@@ -517,7 +551,7 @@ public class ClassUtil {
} }
return desc; return desc;
} }
private static int countArraySize(String type) { private static int countArraySize(String type) {
int size = 0; int size = 0;
for (byte b : type.getBytes()) { for (byte b : type.getBytes()) {
@@ -527,7 +561,7 @@ public class ClassUtil {
} }
return size; return size;
} }
public static final HashMap<String, String> VARS = new HashMap<>(); public static final HashMap<String, String> VARS = new HashMap<>();
static { static {
VARS.put("byte", "B"); VARS.put("byte", "B");
@@ -540,7 +574,7 @@ public class ClassUtil {
VARS.put("boolean", "Z"); VARS.put("boolean", "Z");
VARS.put("void", "V"); VARS.put("void", "V");
} }
public static int externalArrayTypeDimensionCount(String s) { public static int externalArrayTypeDimensionCount(String s) {
int i = 0; int i = 0;
int j = "[]".length(); int j = "[]".length();
@@ -551,7 +585,7 @@ public class ClassUtil {
} }
return i; return i;
} }
public static String internalMethodDescriptor(String returnType, String methodArgs) { public static String internalMethodDescriptor(String returnType, String methodArgs) {
returnType = returnType.replace(".", "/"); returnType = returnType.replace(".", "/");
methodArgs = methodArgs.replace(".", "/"); methodArgs = methodArgs.replace(".", "/");