package me.grax.jbytemod.ui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import javax.swing.Box; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JFormattedTextField; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.filechooser.FileNameExtensionFilter; import org.apache.commons.io.IOUtils; import org.objectweb.asm.Opcodes; import org.objectweb.asm.tree.AbstractInsnNode; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldNode; import org.objectweb.asm.tree.LdcInsnNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.util.CheckClassAdapter; import com.sun.tools.attach.VirtualMachine; import com.sun.tools.attach.VirtualMachineDescriptor; import android.util.Patterns; import me.grax.jbytemod.JByteMod; import me.grax.jbytemod.plugin.Plugin; import me.grax.jbytemod.res.LanguageRes; import me.grax.jbytemod.res.Option; import me.grax.jbytemod.res.Options; import me.grax.jbytemod.ui.dialogue.ClassDialogue; import me.grax.jbytemod.ui.lists.entries.SearchEntry; import me.grax.jbytemod.utils.ErrorDisplay; import me.grax.jbytemod.utils.TextUtils; import me.grax.jbytemod.utils.attach.AttachUtils; import me.grax.jbytemod.utils.list.LazyListModel; import sun.tools.attach.WindowsAttachProvider; public class MyMenuBar extends JMenuBar { private JByteMod jbm; private File lastFile; private boolean agent; private static final Icon searchIcon = new ImageIcon(MyMenuBar.class.getResource("/resources/search.png")); public MyMenuBar(JByteMod jam, boolean agent) { this.jbm = jam; this.agent = agent; this.initFileMenu(); } private void initFileMenu() { JMenu file = new JMenu(JByteMod.res.getResource("file")); if (!agent) { JMenuItem save = new JMenuItem(JByteMod.res.getResource("save")); JMenuItem saveas = new JMenuItem(JByteMod.res.getResource("save_as")); JMenuItem load = new JMenuItem(JByteMod.res.getResource("load")); load.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { openLoadDialogue(); } }); save.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (lastFile != null) { jbm.saveFile(lastFile); } else { openSaveDialogue(); } } }); saveas.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { openSaveDialogue(); } }); save.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); load.setAccelerator(KeyStroke.getKeyStroke('N', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); file.add(save); file.add(saveas); file.add(load); } else { JMenuItem refresh = new JMenuItem(JByteMod.res.getResource("refresh")); refresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jbm.refreshAgentClasses(); } }); file.add(refresh); JMenuItem apply = new JMenuItem(JByteMod.res.getResource("apply")); apply.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jbm.applyChangesAgent(); } }); file.add(apply); } this.add(file); JMenu search = new JMenu(JByteMod.res.getResource("search")); JMenuItem ldc = new JMenuItem(JByteMod.res.getResource("search_ldc")); ldc.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { searchLDC(); } }); search.add(ldc); JMenuItem field = new JMenuItem(JByteMod.res.getResource("search_field")); field.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { searchField(); } }); search.add(field); JMenuItem method = new JMenuItem(JByteMod.res.getResource("search_method")); method.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { searchMethod(); } }); search.add(method); JMenuItem replace = new JMenuItem(JByteMod.res.getResource("replace_ldc")); replace.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { replaceLDC(); } }); search.add(replace); this.add(search); JMenu utils = new JMenu(JByteMod.res.getResource("utils")); JMenuItem accman = new JMenuItem("Access Helper"); accman.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new JAccessHelper().setVisible(true); } }); utils.add(accman); JMenuItem attach = new JMenuItem(JByteMod.res.getResource("attach")); attach.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { openProcessSelection(); } }); utils.add(attach); JMenu obf = new JMenu("Obfuscation Analysis"); utils.add(obf); JMenuItem nameobf = new JMenuItem("Name Obfuscation"); nameobf.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (jbm.getFile() != null) new JNameObfAnalysis(jbm.getFile().getClasses()).setVisible(true); } }); obf.add(nameobf); JMenuItem methodobf = new JMenuItem("Method Obfuscation"); methodobf.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (jbm.getFile() != null) new JMethodObfAnalysis(jbm.getFile().getClasses()).setVisible(true); } }); obf.add(methodobf); this.add(utils); JMenu tree = new JMenu("Tree"); utils.add(tree); JMenuItem rltree = new JMenuItem(JByteMod.res.getResource("tree_reload")); rltree.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jbm.getJarTree().refreshTree(jbm.getFile()); } }); tree.add(rltree); JMenuItem collapse = new JMenuItem(JByteMod.res.getResource("collapse_all")); collapse.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jbm.getJarTree().collapseAll(); } }); tree.add(collapse); JMenu searchUtils = new JMenu(JByteMod.res.getResource("search")); utils.add(searchUtils); JMenuItem url = new JMenuItem(JByteMod.res.getResource("url_search")); url.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jbm.getSearchList().searchForPatternRegex(Patterns.AUTOLINK_WEB_URL); } }); searchUtils.add(url); JMenuItem email = new JMenuItem(JByteMod.res.getResource("email_search")); email.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { jbm.getSearchList().searchForPatternRegex(Patterns.EMAIL_ADDRESS); } }); searchUtils.add(email); // Utils: JMenu deobfTools = new JMenu(JByteMod.res.getResource("deobf_tools")); utils.add(deobfTools); // From old version of JbyteMod by Grax JMenuItem sourceRename = new JMenuItem(JByteMod.res.getResource("rename_sourcefiles")); sourceRename.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile().getClasses() == null) return; if (JOptionPane.showConfirmDialog(null, JByteMod.res.getResource("rename_sourcefiles_warnning"), JByteMod.res.getResource("confirm"), 0) == 0) { int i = 0; for (final ClassNode c : jbm.getFile().getClasses().values()) { c.sourceFile = "Class" + i++ + ".java"; } } } }); deobfTools.add(sourceRename); JMenuItem findSF = new JMenuItem(JByteMod.res.getResource("find_sourcefiles")); findSF.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile() == null) { return; } final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); // panel.add(new JLabel(JByteMod.res.getResource("big_jar_warn")), "South"); labels.add(new JLabel(JByteMod.res.getResource("find_sourcefiles_input_name"))); final JTextField sf = new JTextField(); input.add(sf); if (JOptionPane.showConfirmDialog(JByteMod.instance, panel, JByteMod.res.getResource("find_sourcefiles"), 2) == 0 && !sf.getText().isEmpty()) { jbm.getSearchList().searchForSF(sf.getText()); } } }); search.add(findSF); JMenuItem findClass = new JMenuItem(JByteMod.res.getResource("find_class_by_name")); findClass.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile().getClasses() == null) { return; } final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); // panel.add(new JLabel(JByteMod.res.getResource("big_jar_warn")), "South"); labels.add(new JLabel(JByteMod.res.getResource("find_class_input_name"))); final JTextField cst = new JTextField(); input.add(cst); if (JOptionPane.showConfirmDialog(JByteMod.instance, panel, JByteMod.res.getResource("find_class_by_name"), 2) == 0 && !cst.getText().isEmpty()) { LazyListModel<SearchEntry> model = new LazyListModel<>(); for (final ClassNode cn : jbm.getFile().getClasses().values()) { if (cn.name != null && cn.name.contains(cst.getText())) { // TODO: task SearchEntry se = new SearchEntry(cn, cn.methods.get(0), TextUtils.escape(TextUtils.max(cn.name, 100))); se.setText(TextUtils.toHtml(TextUtils.escape(TextUtils.max(cn.name, 100)))); model.addElement(se); } } jbm.getSearchList().setModel(model); } } }); search.add(findClass); JMenuItem clazz_main = new JMenuItem(JByteMod.res.getResource("find_main_class")); clazz_main.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile().getClasses() == null) { return; } LazyListModel<SearchEntry> model = new LazyListModel<>(); for (final ClassNode c : jbm.getFile().getClasses().values()) { for (final MethodNode m : c.methods) { if (m.name.equals("main") && m.desc.equals("([Ljava/lang/String;)V")) { // TODO: task model.addElement(new SearchEntry(c, m, TextUtils.escape(TextUtils.max(c.name, 100)))); } } } jbm.getSearchList().setModel(model); } }); searchUtils.add(clazz_main); // From https://github.com/java-deobfuscator JMenuItem signatureFix = new JMenuItem(JByteMod.res.getResource("signaturefix")); signatureFix.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile().getClasses() == null) { return; } try { for (final ClassNode classNode : jbm.getFile().getClasses().values()) { if (classNode.signature != null) { try { CheckClassAdapter.checkClassSignature(classNode.signature); } catch (IllegalArgumentException IAE) { classNode.signature = null; } catch (Throwable x) { x.printStackTrace(); } } classNode.methods.forEach(methodNode -> { if (methodNode.signature != null) { try { CheckClassAdapter.checkMethodSignature(methodNode.signature); } catch (IllegalArgumentException IAE) { methodNode.signature = null; } catch (Throwable x) { x.printStackTrace(); } } }); classNode.fields.forEach(fieldNode -> { if (fieldNode.signature != null) { try { CheckClassAdapter.checkFieldSignature(fieldNode.signature); } catch (IllegalArgumentException IAE) { fieldNode.signature = null; } catch (Throwable x) { x.printStackTrace(); } } }); } } catch (Throwable x) { x.printStackTrace(); } JOptionPane.showMessageDialog(null, JByteMod.res.getResource("finish_tip"), JByteMod.res.getResource("signaturefix"), JOptionPane.INFORMATION_MESSAGE); } }); deobfTools.add(signatureFix); // From https://github.com/java-deobfuscator and https://github.com/ItzSomebody/Radon/ JMenuItem access_fix = new JMenuItem(JByteMod.res.getResource("accessfixer")); access_fix.addActionListener(new ActionListener() { @Override public void actionPerformed(final ActionEvent e) { if (jbm.getFile().getClasses() == null) { return; } try { for (final ClassNode classNode : jbm.getFile().getClasses().values()) { if (!hasAnnotations(classNode)) classNode.access &= ~(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE); classNode.methods.forEach(methodNode -> { if (!(methodNode == null) && !hasAnnotations(methodNode)) methodNode.access &= ~(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE); }); classNode.fields.forEach(fieldNode -> { if (!(fieldNode == null) && !hasAnnotations(fieldNode)) fieldNode.access &= ~(Opcodes.ACC_SYNTHETIC | Opcodes.ACC_BRIDGE); }); } } catch (Throwable x) { x.printStackTrace(); } JOptionPane.showMessageDialog(null, JByteMod.res.getResource("finish_tip"), JByteMod.res.getResource("accessfixer"), JOptionPane.INFORMATION_MESSAGE); } }); deobfTools.add(access_fix); this.add(getSettings()); JMenu help = new JMenu(JByteMod.res.getResource("help")); JMenuItem about = new JMenuItem(JByteMod.res.getResource("about")); about.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { new JAboutFrame(jbm).setVisible(true); } catch (Exception ex) { new ErrorDisplay(ex); } } }); help.add(about); JMenuItem licenses = new JMenuItem(JByteMod.res.getResource("licenses")); licenses.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { JFrame jf = new JFrame(); jf.setBounds(100, 100, 700, 800); jf.add(new JScrollPane( new JTextArea(IOUtils.toString(MyMenuBar.class.getResourceAsStream("/resources/LICENSES"))))); jf.setTitle(JByteMod.res.getResource("licenses")); jf.setVisible(true); } catch (Exception ex) { new ErrorDisplay(ex); } } }); help.add(licenses); this.add(help); } // From https://github.com/ItzSomebody/Radon/ public static boolean hasAnnotations(ClassNode classNode) { return (classNode.visibleAnnotations != null && !classNode.visibleAnnotations.isEmpty()) || (classNode.invisibleAnnotations != null && !classNode.invisibleAnnotations.isEmpty()); } // From https://github.com/ItzSomebody/Radon/ public static boolean hasAnnotations(MethodNode methodNode) { return (methodNode.visibleAnnotations != null && !methodNode.visibleAnnotations.isEmpty()) || (methodNode.invisibleAnnotations != null && !methodNode.invisibleAnnotations.isEmpty()); } // From https://github.com/ItzSomebody/Radon/ public static boolean hasAnnotations(FieldNode fieldNode) { return (fieldNode.visibleAnnotations != null && !fieldNode.visibleAnnotations.isEmpty()) || (fieldNode.invisibleAnnotations != null && !fieldNode.invisibleAnnotations.isEmpty()); } protected void openProcessSelection() { // I don't know why this can get none // List<VirtualMachineDescriptor> list = VirtualMachine.list(); // Windows Only.... List<VirtualMachineDescriptor> list = new WindowsAttachProvider().listVirtualMachines(); VirtualMachine vm = null; try { if (list.isEmpty()) { String pid = JOptionPane.showInputDialog(JByteMod.res.getResource("no_vm_found")); if (pid != null && !pid.isEmpty()) { vm = AttachUtils.getVirtualMachine(Integer.parseInt(pid)); } } else { JProcessSelection gui = new JProcessSelection(list); gui.setVisible(true); if (gui.getPid() != 0) { vm = AttachUtils.getVirtualMachine(gui.getPid()); } } if (vm != null) { jbm.attachTo(vm); } } catch (Throwable t) { if (t.getMessage() != null) { JOptionPane.showMessageDialog(null, "<" + t.getMessage() + "> " + JByteMod.res.getResource("attach_error")); } else { new ErrorDisplay(t); } } } private JMenu getSettings() { JMenu settings = new JMenu(JByteMod.res.getResource("settings")); LanguageRes lr = JByteMod.res; Options o = JByteMod.ops; HashMap<String, JMenu> menus = new LinkedHashMap<>(); HashMap<String, JMenu> roots = new LinkedHashMap<>(); for (Option op : o.bools) { String group = op.getGroup(); String[] groups = group.split("_"); JMenu menu = null; if (menus.containsKey(group)) { menu = menus.get(group); } else { String full = ""; for (String g : groups) { if (!full.isEmpty()) { full += "_"; } full += g; if (menus.containsKey(full)) { menu = menus.get(full); continue; } if (menu == null) { menu = new JMenu(lr.getResource(g + "_group")); roots.put(full, menu); menus.put(full, menu); } else { JMenu subMenu = new JMenu(lr.getResource(g + "_group")); menu.add(subMenu); menu = subMenu; menus.put(full, menu); } } } switch (op.getType()) { case BOOLEAN: JCheckBoxMenuItem jmi = new JCheckBoxMenuItem(lr.getResource(op.getName()), op.getBoolean()); jmi.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { op.setValue(jmi.isSelected()); o.save(); if (op.getName().equals("use_weblaf")) { JByteMod.resetLAF(); JByteMod.restartGUI(); } } }); menu.add(jmi); break; case STRING: JMenu jm = new JMenu(lr.getResource(op.getName())); JTextField jtf = new JTextField(op.getString()); jtf.setPreferredSize(new Dimension(Math.max((int) jtf.getPreferredSize().getWidth(), 128), (int) jtf.getPreferredSize().getHeight())); jm.add(Box.createHorizontalGlue()); jm.add(jtf); jtf.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { op.setValue(jtf.getText()); o.save(); } }); menu.add(jm); break; case INT: jm = new JMenu(lr.getResource(op.getName())); JFormattedTextField jnf = ClassDialogue.createNumberField(Integer.class, 0, Integer.MAX_VALUE); jnf.setValue(op.getInteger()); jnf.setPreferredSize(new Dimension(Math.max((int) jnf.getPreferredSize().getWidth(), 64), (int) jnf.getPreferredSize().getHeight())); jm.add(jnf); jnf.addFocusListener(new FocusAdapter() { public void focusLost(FocusEvent e) { op.setValue((int) jnf.getValue()); o.save(); } }); menu.add(jm); break; default: break; } } for (JMenu m : roots.values()) { settings.add(m); } return settings; } protected void searchLDC() { final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); panel.add(new JLabel(JByteMod.res.getResource("big_string_warn")), "South"); labels.add(new JLabel(JByteMod.res.getResource("find"))); JTextField cst = new JTextField(); input.add(cst); JCheckBox exact = new JCheckBox(JByteMod.res.getResource("exact")); JCheckBox regex = new JCheckBox("Regex"); JCheckBox snstv = new JCheckBox(JByteMod.res.getResource("case_sens")); labels.add(exact); labels.add(regex); input.add(snstv); input.add(new JPanel()); if (JOptionPane.showConfirmDialog(this.jbm, panel, "Search LDC", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, searchIcon) == JOptionPane.OK_OPTION && !cst.getText().isEmpty()) { jbm.getSearchList().searchForConstant(cst.getText(), exact.isSelected(), snstv.isSelected(), regex.isSelected()); } } protected void replaceLDC() { final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); panel.add(new JLabel(JByteMod.res.getResource("big_string_warn")), "South"); labels.add(new JLabel("Find: ")); JTextField find = new JTextField(); input.add(find); labels.add(new JLabel("Replace with: ")); JTextField with = new JTextField(); input.add(with); JComboBox<String> ldctype = new JComboBox<String>(new String[] { "String", "float", "double", "int", "long" }); ldctype.setSelectedIndex(0); labels.add(new JLabel("Ldc Type: ")); input.add(ldctype); JCheckBox exact = new JCheckBox(JByteMod.res.getResource("exact")); JCheckBox cases = new JCheckBox(JByteMod.res.getResource("case_sens")); labels.add(exact); input.add(cases); if (JOptionPane.showConfirmDialog(this.jbm, panel, "Replace LDC", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, searchIcon) == JOptionPane.OK_OPTION && !find.getText().isEmpty()) { int expectedType = ldctype.getSelectedIndex(); boolean equal = exact.isSelected(); boolean ignoreCase = !cases.isSelected(); String findCst = find.getText(); if (ignoreCase) { findCst = findCst.toLowerCase(); } String replaceWith = with.getText(); int i = 0; for (ClassNode cn : jbm.getFile().getClasses().values()) { for (MethodNode mn : cn.methods) { for (AbstractInsnNode ain : mn.instructions) { if (ain.getType() == AbstractInsnNode.LDC_INSN) { LdcInsnNode lin = (LdcInsnNode) ain; Object cst = lin.cst; int type; if (cst instanceof String) { type = 0; } else if (cst instanceof Float) { type = 1; } else if (cst instanceof Double) { type = 2; } else if (cst instanceof Long) { type = 3; } else if (cst instanceof Integer) { type = 4; } else { type = -1; } String cstStr = cst.toString(); if (ignoreCase) { cstStr = cstStr.toLowerCase(); } if (type == expectedType) { if (equal ? cstStr.equals(findCst) : cstStr.contains(findCst)) { switch (type) { case 0: lin.cst = replaceWith; break; case 1: lin.cst = Float.parseFloat(replaceWith); break; case 2: lin.cst = Double.parseDouble(replaceWith); break; case 3: lin.cst = Long.parseLong(replaceWith); break; case 4: lin.cst = Integer.parseInt(replaceWith); break; } i++; } } } } } } JByteMod.LOGGER.log(i + " ldc's replaced"); } } protected void searchField() { final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); panel.add(new JLabel(JByteMod.res.getResource("big_jar_warn")), "South"); labels.add(new JLabel("Owner:")); JTextField owner = new JTextField(); input.add(owner); labels.add(new JLabel("Name:")); JTextField name = new JTextField(); input.add(name); labels.add(new JLabel("Desc:")); JTextField desc = new JTextField(); input.add(desc); JCheckBox exact = new JCheckBox(JByteMod.res.getResource("exact")); labels.add(exact); input.add(new JPanel()); if (JOptionPane.showConfirmDialog(JByteMod.instance, panel, "Search FieldInsnNode", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, searchIcon) == JOptionPane.OK_OPTION && !(name.getText().isEmpty() && owner.getText().isEmpty() && desc.getText().isEmpty())) { jbm.getSearchList().searchForFMInsn(owner.getText(), name.getText(), desc.getText(), exact.isSelected(), true); } } protected void searchMethod() { final JPanel panel = new JPanel(new BorderLayout(5, 5)); final JPanel input = new JPanel(new GridLayout(0, 1)); final JPanel labels = new JPanel(new GridLayout(0, 1)); panel.add(labels, "West"); panel.add(input, "Center"); panel.add(new JLabel(JByteMod.res.getResource("big_jar_warn")), "South"); labels.add(new JLabel("Owner:")); JTextField owner = new JTextField(); input.add(owner); labels.add(new JLabel("Name:")); JTextField name = new JTextField(); input.add(name); labels.add(new JLabel("Desc:")); JTextField desc = new JTextField(); input.add(desc); JCheckBox exact = new JCheckBox(JByteMod.res.getResource("exact")); labels.add(exact); input.add(new JPanel()); if (JOptionPane.showConfirmDialog(JByteMod.instance, panel, "Search MethodInsnNode", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, searchIcon) == JOptionPane.OK_OPTION && !(name.getText().isEmpty() && owner.getText().isEmpty() && desc.getText().isEmpty())) { jbm.getSearchList().searchForFMInsn(owner.getText(), name.getText(), desc.getText(), exact.isSelected(), false); } } protected void openSaveDialogue() { if (jbm.getFile() != null) { boolean isClass = jbm.getFile().isSingleEntry(); JFileChooser jfc = new JFileChooser(new File(System.getProperty("user.home") + File.separator + "Desktop")); jfc.setAcceptAllFileFilterUsed(false); jfc.setDialogTitle("Save"); jfc.setFileFilter(new FileNameExtensionFilter(isClass ? "Java Class (*.class)" : "Java Package (*.jar)", isClass ? "class" : "jar")); int result = jfc.showSaveDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File output = jfc.getSelectedFile(); this.lastFile = output; JByteMod.LOGGER.log("Selected output file: " + output.getAbsolutePath()); jbm.saveFile(output); } } } protected void openLoadDialogue() { JFileChooser jfc = new JFileChooser(new File(System.getProperty("user.home") + File.separator + "Desktop")); jfc.setAcceptAllFileFilterUsed(false); jfc.setFileFilter(new FileNameExtensionFilter("Java Package (*.jar) or Java Class (*.class)", "jar", "class")); int result = jfc.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File input = jfc.getSelectedFile(); JByteMod.LOGGER.log("Selected input file: " + input.getAbsolutePath()); jbm.loadFile(input); } } public void addPluginMenu(ArrayList<Plugin> plugins) { if (!plugins.isEmpty()) { JMenu pluginMenu = new JMenu("Plugins"); for (Plugin p : plugins) { JMenuItem jmi = new JMenuItem(p.getName() + " " + p.getVersion()); jmi.setEnabled(p.isClickable()); jmi.addActionListener(e -> { p.menuClick(); }); pluginMenu.add(jmi); } this.add(pluginMenu); } } public boolean isAgent() { return agent; } public File getLastFile() { return lastFile; } public void setLastFile(File lastFile) { this.lastFile = lastFile; } }