package com.aionemu.packetsamurai.gui; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.BufferUnderflowException; import java.util.Set; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.filechooser.FileFilter; import javolution.util.FastList; import com.aionemu.packetsamurai.Captor; import com.aionemu.packetsamurai.IUserInterface; import com.aionemu.packetsamurai.PacketSamurai; import com.aionemu.packetsamurai.gui.logrepo.LogRepoTab; import com.aionemu.packetsamurai.gui.protocoleditor.ProtocolEditor; import com.aionemu.packetsamurai.logreaders.AbstractLogReader; import com.aionemu.packetsamurai.session.DataPacket; import com.aionemu.packetsamurai.session.GameSessionTable; import com.aionemu.packetsamurai.session.Session; import com.aionemu.packetsamurai.utils.NpcTitleExporter; /** * @author Ulysses R. Ribeiro */ public class Main implements IUserInterface { protected JFrame _frame; private JMenuBar _menuBar = new JMenuBar(); private JMenu _fileMenu = new JMenu("File"); private JMenu _editMenu = new JMenu("Edit"); private JMenu _utilsMenu = new JMenu("Utils"); private JMenu _toolsMenu = new JMenu("Tools"); private JMenu _helpMenu = new JMenu("Help"); private JMenuItem _itemClose; private JMenuItem _itemCloseAll; private JMenuItem _itemSearch; private JMenuItem _itemSearchNext; private JMenuItem _itemGoto; private JMenuItem _itemFilter; private ProtocolEditor _pEditor; private ActionListener _menuListener = new MenuActionListener(); private JTabbedPane _tabPane = new JTabbedPane(); private ConsoleTab _consoleTab; private ViewTab _viewerTab; private JDialog _selectInterfaceWindow; private SearchDlg _searchDlg; private JList _interfaceList; private LogRepoTab _logRepo; public Main() { } public void init() { _frame = new JFrame("Packet Samurai [aion-unique edition]"); _frame.setLayout(new BorderLayout()); _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Menu Bar Itens // File Menu JMenuItem itemOpen = new JMenuItem("Open"); itemOpen.setActionCommand("Open"); itemOpen.addActionListener(_menuListener); _itemClose = new JMenuItem("Close"); _itemClose.setEnabled(false); _itemClose.setActionCommand("Close"); _itemClose.addActionListener(_menuListener); _itemCloseAll = new JMenuItem("Close All"); _itemCloseAll.setEnabled(false); _itemCloseAll.setActionCommand("CloseAll"); _itemCloseAll.addActionListener(_menuListener); JMenuItem itemExit = new JMenuItem("Exit"); itemExit.setActionCommand("Exit"); itemExit.addActionListener(_menuListener); _fileMenu.add(itemOpen); _fileMenu.add(_itemClose); _fileMenu.add(_itemCloseAll); _fileMenu.add(itemExit); // Edit _itemSearch = new JMenuItem("Search"); _itemSearch.setEnabled(false); _itemSearch.setActionCommand("Search"); _itemSearch.setMnemonic(KeyEvent.VK_F); _itemSearch.addActionListener(_menuListener); _editMenu.add(_itemSearch); _itemSearchNext = new JMenuItem("Search Next"); _itemSearchNext.setEnabled(false); _itemSearchNext.setActionCommand("SearchNext"); _itemSearchNext.addActionListener(_menuListener); _editMenu.add(_itemSearchNext); _itemGoto = new JMenuItem("Go to..."); _itemGoto.setEnabled(false); _itemGoto.setActionCommand("GoTo"); _itemGoto.addActionListener(_menuListener); _editMenu.add(_itemGoto); _itemFilter = new JMenuItem("Filter"); _itemFilter.setEnabled(false); _itemFilter.setActionCommand("Filter"); _itemFilter.addActionListener(_menuListener); _editMenu.add(_itemFilter); // Utils JMenuItem exportTitles = new JMenuItem("Export Npc Titles"); exportTitles.setActionCommand("ExportNpcTitles"); exportTitles.addActionListener(_menuListener); _utilsMenu.add(exportTitles); // Tools JMenuItem itemSelectInterface = new JMenuItem("Select Interface"); itemSelectInterface.setActionCommand("SelectInterface"); itemSelectInterface.addActionListener(_menuListener); _toolsMenu.add(itemSelectInterface); JMenuItem itemEditProtocol = new JMenuItem("Edit Protocol"); itemEditProtocol.setActionCommand("EditProtocol"); itemEditProtocol.addActionListener(_menuListener); _toolsMenu.add(itemEditProtocol); JMenuItem itemSetActiveProtocols = new JMenuItem("Set Active Protocols"); itemSetActiveProtocols.setActionCommand("SetActiveProtocols"); itemSetActiveProtocols.addActionListener(_menuListener); _toolsMenu.add(itemSetActiveProtocols); // Help JMenuItem itemAbout = new JMenuItem("About"); itemAbout.setActionCommand("About"); itemAbout.addActionListener(_menuListener); _helpMenu.add(itemAbout); _menuBar.add(_fileMenu); _menuBar.add(_editMenu); _menuBar.add(_utilsMenu); _menuBar.add(_toolsMenu); _menuBar.add(_helpMenu); _frame.setJMenuBar(_menuBar); // Console Tab _consoleTab = new ConsoleTab(); // Viewer Tab _viewerTab = new ViewTab(); _logRepo = new LogRepoTab(); // hotkeys _tabPane.registerKeyboardAction(_menuListener, "Search", KeyStroke.getKeyStroke(KeyEvent.VK_F, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); _tabPane.registerKeyboardAction(_menuListener, "SearchNext", KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); _tabPane.registerKeyboardAction(_menuListener, "EditProtocol", KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); _tabPane.registerKeyboardAction(_menuListener, "Filter", KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_MASK), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); _tabPane.add("Console", _consoleTab); _tabPane.add("Viewer", _viewerTab); _tabPane.add("Log Repository", _logRepo); // build the frame _frame.add(_tabPane, BorderLayout.CENTER); // add the window listeners addListeners(); _frame.setMinimumSize(new Dimension(600, 400)); _frame.setExtendedState(JFrame.MAXIMIZED_HORIZ); _frame.setVisible(true); } public JTabbedPane getTabPane() { return _tabPane; } public LogRepoTab getLogRepoTab() { return _logRepo; } public void log(String text) { _consoleTab.addText(text); System.err.println(text); } private void addListeners() { // Window Closing /* * _frame.addWindowListener(new WindowAdapter() { public void * windowClosing(WindowEvent event) { close(); } }); */ } public void showInterfaceSelector(String[] interfaceNames) { _selectInterfaceWindow = new JDialog(_frame); _selectInterfaceWindow.setTitle("Double-Click to Select the Interface"); _selectInterfaceWindow.setLocationRelativeTo(_frame); _interfaceList = new JList(interfaceNames); _interfaceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane scrollPane = new JScrollPane(_interfaceList); MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { int index = _interfaceList.locationToIndex(e.getPoint()); if (Captor.getInstance().getCurrentDeviceId() == index) { _selectInterfaceWindow.dispose(); return; } Captor.getInstance().openDevice(index); PacketSamurai.setConfigProperty("NetworkInterface", Integer.toString(index)); _selectInterfaceWindow.dispose(); } } }; _interfaceList.addMouseListener(mouseListener); _selectInterfaceWindow.add(scrollPane); _selectInterfaceWindow.setSize(400, 350); _selectInterfaceWindow.setVisible(true); } public void showAboutDialog() { JOptionPane.showMessageDialog(this.getMainFrame(), "Packet Samurai v??\n\nGilles Duboscq\nUlysses R. Ribeiro", "About Packet Samurai", JOptionPane.PLAIN_MESSAGE); } public void close() { PacketSamurai.saveConfig(); } public void toggleSearchDialog() { if (getViewerTab().getComponentCount() > 0) { if (_searchDlg == null) { _searchDlg = new SearchDlg(_frame); _searchDlg.setVisible(true); } else { // toggle display _searchDlg.setVisible(!_searchDlg.isVisible()); } } } public void toggleFilterDialog() { if (getViewerTab().getComponentCount() > 0) { FilterDlg filterDlg = getViewerTab().getCurrentViewPane().getFilterDialog(); // toggle display filterDlg.setVisible(!filterDlg.isVisible()); } } public void searchNext() { if (getViewerTab().getComponentCount() > 0) { if (_searchDlg != null) { ViewPane pane = ((Main) PacketSamurai.getUserInterface()).getViewerTab().getCurrentViewPane(); if (pane != null) { int index = _searchDlg.search(pane.getSelectedPacketindex() + 1); if (index >= 0) { JTable pt = ((Main) PacketSamurai.getUserInterface()).getViewerTab().getCurrentViewPane().getPacketTable(); pt.setAutoscrolls(true); pt.getSelectionModel().setSelectionInterval(index, index); pt.scrollRectToVisible(pt.getCellRect(index, 0, true)); _searchDlg.setCurrentSearchIndex(index + 1); } } } else { toggleSearchDialog(); } } } public void toggleProtocolEditor() { if (_pEditor == null) { ProtocolEditor pe = new ProtocolEditor(_frame); _pEditor = pe; _pEditor.setLocationRelativeTo(_frame); // will make PE spawn // centered relatively to // the main frame } // toggle display _pEditor.setVisible(!_pEditor.isVisible()); } private void exportNpcTitles() { if (getViewerTab().getComponentCount() > 0) { ViewPane pane = ((Main) PacketSamurai.getUserInterface()).getViewerTab().getCurrentViewPane(); if (pane != null) { String sessionName = pane.getGameSessionViewer().getSession().getSessionName(); FastList<DataPacket> packets = pane.getGameSessionViewer().getSession().getPackets(); new NpcTitleExporter(packets, sessionName).parse(); } } } // MenuActions public class MenuActionListener implements ActionListener { public void actionPerformed(ActionEvent ev) { String actionCmd = ev.getActionCommand(); if (actionCmd.equals("Open")) { final JFileChooser chooser = new JFileChooser(PacketSamurai.getConfigProperty("lastLogDir", ".\\logs\\")); chooser.setFileFilter(new FileFilter() { @Override public boolean accept(File f) { return f.isDirectory() || f.isFile() && (f.getName().endsWith(".pcap") || f.getName().endsWith(".cap") || f.getName().endsWith(".bin") || f.getName().endsWith(".psl")); } @Override public String getDescription() { return "All supported formats (.cap .pcap .bin .psl)"; } }); final int returnVal = chooser.showOpenDialog(_frame); if (returnVal == JFileChooser.APPROVE_OPTION) { Thread t = new Thread() { public void run() { ((Main) PacketSamurai.getUserInterface()).openSession(chooser.getSelectedFile()); } }; t.start(); } } else if (actionCmd.equals("Close")) { Main.this.closeSessionTab(Main.this.getViewerTab().getCurrentViewPane()); } else if (actionCmd.equals("CloseAll")) { getViewerTab().removeAll(); Main.this.toggleSessionItems(false); } else if (actionCmd.equals("Search")) { toggleSearchDialog(); } else if (actionCmd.equals("SearchNext")) { searchNext(); } else if (actionCmd.equals("GoTo")) { String ret = JOptionPane.showInputDialog(null, "Enter the packet number", "Go to packet...", JOptionPane.INFORMATION_MESSAGE); if (ret != null) { try { int pn = Integer.parseInt(ret); if (pn >= 0 && pn < Main.this.getViewerTab().getCurrentViewPane().getPacketTable().getRowCount()) { Main.this.getViewerTab().getCurrentViewPane().setSelectedPacket(pn, pn); } else { JOptionPane.showMessageDialog(null, "Invalid value for packet number.", "ERROR", JOptionPane.ERROR_MESSAGE); } } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, "Invalid value for packet number.", "ERROR", JOptionPane.ERROR_MESSAGE); } } } else if (actionCmd.equals("Filter")) { toggleFilterDialog(); } else if (actionCmd.equals("SelectInterface")) { // must run asynchronously from Main UI new Thread(new Runnable() { public void run() { Captor.getInstance().selectNetWorkInterface(); } }).start(); } else if (actionCmd.equals("SetActiveProtocols")) { new Thread(new Runnable() { public void run() { Captor.showSetActiveProtocols(); } }).start(); } else if (actionCmd.equals("Exit")) { System.exit(0); } else if (actionCmd.equals("About")) { showAboutDialog(); } else if (actionCmd.equals("EditProtocol")) { toggleProtocolEditor(); } else if (actionCmd.equals("ExportNpcTitles")){ exportNpcTitles(); } } } public ProtocolEditor getProtocolEditor() { return _pEditor; } public ViewTab getViewerTab() { return _viewerTab; } public void openSession(File file) { Set<Session> sessions = null; try { sessions = Main.getSessionsFromFile(file); } catch (FileNotFoundException fnfe) { PacketSamurai.getUserInterface().log("ERROR: Opening (" + file.getAbsolutePath() + "), file was not found."); } catch (IOException ioe) { ioe.printStackTrace(); PacketSamurai.getUserInterface().log("ERROR: Opening (" + file.getAbsolutePath() + "), I/O error."); } catch (BufferUnderflowException e) { PacketSamurai.getUserInterface().log("ERROR: Opening (" + file.getAbsolutePath() + "), file format error."); e.printStackTrace(); } if (sessions != null) { PacketSamurai.setConfigProperty("lastLogDir", file.getParent()); for (Session s : sessions) { this.showSession(s, false); } } } /** * * @param file * The file to be opened * @return A set containing all session(s) stored on the file, or null if * there is no support for the file extension. * @throws IOException * if there was an I/O error. * @throws BufferUnderflowException * if there was insufficient data or a file format error. */ public static Set<Session> getSessionsFromFile(File file) throws IOException { Set<Session> sessions = null; String filename = file.getAbsolutePath(); // for now its hardcoded, maybe registering later AbstractLogReader reader = AbstractLogReader.getLogReaderForFile(filename); if (reader == null) return null; reader.parse(); sessions = reader.getSessions(); return sessions; } public JFrame getMainFrame() { return _frame; } public void showSessions() { for (Session s : GameSessionTable.getInstance().getSessions()) { if (!s.isShown()) this.showSession(s, true); } } public void showSession(Session s, boolean notify) { this.getViewerTab().showSession(s, notify); this.toggleSessionItems(true); } public void toggleSessionItems(boolean enabled) { _itemClose.setEnabled(enabled); _itemCloseAll.setEnabled(enabled); _itemSearch.setEnabled(enabled); _itemSearchNext.setEnabled(enabled); _itemGoto.setEnabled(enabled); _itemFilter.setEnabled(enabled); } public void closeSessionTab(ViewPane vp) { Session s = vp.getGameSessionViewer().getSession(); if (s != null) { s.setShown(false); } getViewerTab().remove(vp); if (getViewerTab().getComponentCount() == 0) { this.toggleSessionItems(false); } } }