/*********************************************************************** * * $CVSHeader$ * * This file is part of WebScarab, an Open Web Application Security * Project utility. For details, please see http://www.owasp.org/ * * Copyright (c) 2002 - 2004 Rogan Dawes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Getting Source * ============== * * Source for this application is maintained at Sourceforge.net, a * repository for free software projects. * * For details, please see http://www.sourceforge.net/projects/owasp * */ /* * ProxyPanel.java * * Created on July 25, 2003, 11:07 PM */ package org.owasp.webscarab.plugin.proxy.swing; import org.owasp.webscarab.model.ConversationID; import org.owasp.webscarab.model.HttpUrl; import org.owasp.webscarab.ui.swing.SwingPluginUI; import org.owasp.webscarab.plugin.proxy.ListenerSpec; import org.owasp.webscarab.plugin.proxy.Proxy; import org.owasp.webscarab.plugin.proxy.ProxyUI; import org.owasp.webscarab.util.swing.ColumnDataModel; import org.owasp.webscarab.util.W32WinInet; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.logging.Logger; import javax.swing.ListSelectionModel; import javax.swing.DefaultComboBoxModel; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.table.AbstractTableModel; import java.util.Timer; import java.util.TimerTask; /** * * @author rdawes */ public class ProxyPanel extends javax.swing.JPanel implements SwingPluginUI, ProxyUI { /** * */ private static final long serialVersionUID = -3557927604958599392L; private Proxy _proxy; private ListenerTableModel _ltm; private MessageTableModel _mtm; private ArrayList<ProxyPluginUI> _plugins; private ProxyPluginUI[] _pluginArray = new ProxyPluginUI[0]; private Logger _logger = Logger.getLogger(getClass().getName()); /** Creates new form ProxyPanel */ public ProxyPanel(Proxy proxy) { initComponents(); _proxy = proxy; _ltm = new ListenerTableModel(_proxy); listenerTable.setModel(_ltm); listenerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); _mtm = new MessageTableModel(); messageTable.setModel(_mtm); int[][] columnWidths = { {200, 200, 200}, {50, 50, 50}, {50, 50, 50}, {250, 250, 250}, }; javax.swing.table.TableColumnModel columnModel = messageTable.getColumnModel(); for (int i=0; i<columnWidths.length; i++) { columnModel.getColumn(i).setMinWidth(columnWidths[i][0]); columnModel.getColumn(i).setMaxWidth(columnWidths[i][1]); columnModel.getColumn(i).setPreferredWidth(columnWidths[i][2]); } networkComboBox.setModel(new DefaultComboBoxModel(new String[] { "Unlimited" })); networkComboBox.setSelectedItem("Unlimited"); ListenerSpec[] proxies = _proxy.getProxies(); for (int i=0; i<proxies.length; i++) _ltm.proxyAdded(proxies[i]); proxy.setUI(this); if (!W32WinInet.isAvailable()) { primaryLabel.setEnabled(false); primaryCheckBox.setEnabled(false); } } public javax.swing.JPanel getPanel() { return this; } public String getPluginName() { return new String("Proxy"); } public void addPlugin(ProxyPluginUI plugin) { if (_plugins == null) { _plugins = new ArrayList<ProxyPluginUI>(); } _plugins.add(plugin); _pluginArray = _plugins.toArray(_pluginArray); mainTabbedPane.add(plugin.getPanel(), plugin.getPluginName()); if (plugin instanceof ManualEditPanel) mainTabbedPane.setSelectedIndex(mainTabbedPane.getTabCount()-1); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents private void initComponents() { java.awt.GridBagConstraints gridBagConstraints; mainTabbedPane = new javax.swing.JTabbedPane(); jSplitPane1 = new javax.swing.JSplitPane(); jPanel1 = new javax.swing.JPanel(); jPanel2 = new javax.swing.JPanel(); stopButton = new javax.swing.JButton(); startButton = new javax.swing.JButton(); jScrollPane1 = new javax.swing.JScrollPane(); listenerTable = new javax.swing.JTable(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); addressTextField = new javax.swing.JTextField(); portTextField = new javax.swing.JTextField(); baseTextField = new javax.swing.JTextField(); jLabel5 = new javax.swing.JLabel(); networkComboBox = new javax.swing.JComboBox(); primaryLabel = new javax.swing.JLabel(); primaryCheckBox = new javax.swing.JCheckBox(); jPanel3 = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); messageTable = new javax.swing.JTable(); setLayout(new java.awt.GridBagLayout()); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setResizeWeight(0.9); jPanel1.setLayout(new java.awt.GridBagLayout()); jPanel2.setLayout(new java.awt.GridBagLayout()); stopButton.setText("Stop"); stopButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { stopButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.SOUTH; gridBagConstraints.weighty = 1.0; jPanel2.add(stopButton, gridBagConstraints); startButton.setText("Start"); startButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { startButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH; gridBagConstraints.weighty = 1.0; jPanel2.add(startButton, gridBagConstraints); listenerTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { }, new String [] { } )); jScrollPane1.setViewportView(listenerTable); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridheight = 3; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; jPanel2.add(jScrollPane1, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; jPanel1.add(jPanel2, gridBagConstraints); jLabel1.setFont(new java.awt.Font("Dialog", 0, 12)); jLabel1.setText("Address"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; jPanel1.add(jLabel1, gridBagConstraints); jLabel2.setFont(new java.awt.Font("Dialog", 0, 12)); jLabel2.setText("Port"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; jPanel1.add(jLabel2, gridBagConstraints); jLabel3.setFont(new java.awt.Font("Dialog", 0, 12)); jLabel3.setText("Base URL"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; jPanel1.add(jLabel3, gridBagConstraints); addressTextField.setToolTipText("Blank or \"*\" means all interfaces"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; jPanel1.add(addressTextField, gridBagConstraints); portTextField.setToolTipText("integer between 0 and 65536"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 0.5; jPanel1.add(portTextField, gridBagConstraints); baseTextField.setToolTipText("Blank for a conventional proxy, or http://host:port for a reverse proxy."); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; jPanel1.add(baseTextField, gridBagConstraints); jLabel5.setFont(new java.awt.Font("Dialog", 0, 12)); jLabel5.setText("Speed"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; jPanel1.add(jLabel5, gridBagConstraints); networkComboBox.setFont(new java.awt.Font("Dialog", 0, 12)); networkComboBox.setMinimumSize(new java.awt.Dimension(32, 19)); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 2; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 1.0; jPanel1.add(networkComboBox, gridBagConstraints); primaryLabel.setFont(new java.awt.Font("Dialog", 0, 12)); primaryLabel.setText("Primary?"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 5; gridBagConstraints.gridy = 1; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 0); jPanel1.add(primaryLabel, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 5; gridBagConstraints.gridy = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; gridBagConstraints.weightx = 0.2; gridBagConstraints.insets = new java.awt.Insets(0, 2, 0, 0); jPanel1.add(primaryCheckBox, gridBagConstraints); jSplitPane1.setLeftComponent(jPanel1); jPanel3.setLayout(new java.awt.BorderLayout()); messageTable.setBackground(new java.awt.Color(204, 204, 204)); messageTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { }, new String [] { "Time", "ID", "Method", "URL", "Status" } )); messageTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN); messageTable.setShowHorizontalLines(false); messageTable.setShowVerticalLines(false); jScrollPane2.setViewportView(messageTable); jPanel3.add(jScrollPane2, java.awt.BorderLayout.CENTER); jSplitPane1.setRightComponent(jPanel3); mainTabbedPane.addTab("Listeners", jSplitPane1); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; add(mainTabbedPane, gridBagConstraints); }// </editor-fold>//GEN-END:initComponents private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed try { String address = addressTextField.getText(); int port = Integer.parseInt(portTextField.getText().trim()); HttpUrl base = null; if (!baseTextField.getText().equals("")) { base = new HttpUrl(baseTextField.getText()); } boolean primary = primaryCheckBox.isSelected(); ListenerSpec spec = new ListenerSpec(address, port, base, primary); spec.verifyAvailable(); _proxy.addListener(spec); addressTextField.setText(""); portTextField.setText(""); baseTextField.setText(""); } catch (Exception e) { _logger.severe("Error starting the listener : " + e); JOptionPane.showMessageDialog(null, new String[] {"Error starting proxy listener: ", e.toString()}, "Error", JOptionPane.ERROR_MESSAGE); } }//GEN-LAST:event_startButtonActionPerformed private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed int row = listenerTable.getSelectedRow(); if (row<0) return; ListenerSpec spec = _ltm.getListener(row); if (!_proxy.removeListener(spec)) { _logger.severe("Failed to stop " + spec); } else { addressTextField.setText(spec.getAddress()); portTextField.setText(Integer.toString(spec.getPort())); baseTextField.setText(spec.getBase() == null ? "" : spec.getBase().toString()); primaryCheckBox.setSelected(spec.isPrimaryProxy()); } }//GEN-LAST:event_stopButtonActionPerformed public javax.swing.Action[] getConversationActions() { return null; } public javax.swing.Action[] getUrlActions() { return null; } public void proxyAdded(final ListenerSpec spec) { if (SwingUtilities.isEventDispatchThread()) { _ltm.proxyAdded(spec); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { proxyAdded(spec); } }); } } public void proxyRemoved(final ListenerSpec spec) { if (SwingUtilities.isEventDispatchThread()) { _ltm.proxyRemoved(spec); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { proxyRemoved(spec); } }); } } public void proxyStarted(ListenerSpec spec) { } public void proxyStartError(final ListenerSpec spec, final IOException ioe) { if (SwingUtilities.isEventDispatchThread()) { JOptionPane.showMessageDialog(this, new String[] {"Error starting proxy listener: ", spec.toString(), ioe.toString()}, "Error", JOptionPane.ERROR_MESSAGE); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { proxyStartError(spec, ioe); } }); } } public void proxyStopped(ListenerSpec spec) { } public void requested(final ConversationID id, final String method, final HttpUrl url) { if (SwingUtilities.isEventDispatchThread()) { _mtm.addRow(id, method, url); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { requested(id, method, url); } }); } } public void received(final ConversationID id, final String status) { if (SwingUtilities.isEventDispatchThread()) { _mtm.updateRow(id, status); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { received(id, status); } }); } } public void aborted(final ConversationID id, final String reason) { if (SwingUtilities.isEventDispatchThread()) { _mtm.updateRow(id, reason); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { aborted(id, reason); } }); } } public void setEnabled(final boolean enabled) { if (SwingUtilities.isEventDispatchThread()) { startButton.setEnabled(enabled); stopButton.setEnabled(enabled); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { setEnabled(enabled); } }); } } public ColumnDataModel<ConversationID>[] getConversationColumns() { return null; } public ColumnDataModel<HttpUrl>[] getUrlColumns() { return null; } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField addressTextField; private javax.swing.JTextField baseTextField; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel5; private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel2; private javax.swing.JPanel jPanel3; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JTable listenerTable; private javax.swing.JTabbedPane mainTabbedPane; private javax.swing.JTable messageTable; private javax.swing.JComboBox networkComboBox; private javax.swing.JTextField portTextField; private javax.swing.JCheckBox primaryCheckBox; private javax.swing.JLabel primaryLabel; private javax.swing.JButton startButton; private javax.swing.JButton stopButton; // End of variables declaration//GEN-END:variables private class MessageTableModel extends AbstractTableModel { /** * */ private static final long serialVersionUID = 3090029861017879230L; private ArrayList<Object[]> _rows = new ArrayList<Object[]>(); private Timer _timer = new Timer(true); private String[] _columns = new String [] { "Time", "ID", "Method", "URL", "Status" }; public String getColumnName(int columnIndex) { return _columns[columnIndex]; } public int getColumnCount() { return _columns.length; } public int getRowCount() { return _rows.size(); } public Object getValueAt(int rowIndex, int columnIndex) { Object[] row = _rows.get(rowIndex); return row[columnIndex]; } public void addRow(ConversationID id, String method, HttpUrl url) { Object[] row = new Object[] {new Date(), id, method, url, null}; _rows.add(row); fireTableRowsInserted(_rows.size()-1, _rows.size()-1); } public void updateRow(final ConversationID id, String status) { for (int i=0; i<_rows.size(); i++) { Object[] row = (Object[]) _rows.get(i); if (row[1].equals(id)) { row[4] = status; fireTableCellUpdated(i, 4); _timer.schedule(new TimerTask() { public void run() { removeRow(id); } }, 5000); return; } } } public void removeRow(final ConversationID id) { if (SwingUtilities.isEventDispatchThread()) { for (int i=0; i<_rows.size(); i++) { Object[] row = (Object[]) _rows.get(i); if (row[1].equals(id)) { _rows.remove(i); fireTableRowsDeleted(i, i); return; } } } else { SwingUtilities.invokeLater(new Runnable() { public void run() { removeRow(id); } }); } } } }