/*********************************************************************** * * $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 * */ /* * FragmentsPanel.java * * Created on 09 December 2004, 10:37 */ package org.owasp.webscarab.plugin.fragments.swing; import org.owasp.webscarab.model.ConversationID; import org.owasp.webscarab.model.HttpUrl; import org.owasp.webscarab.plugin.fragments.Fragments; import org.owasp.webscarab.plugin.fragments.FragmentsModel; import org.owasp.webscarab.plugin.fragments.FragmentListener; import org.owasp.webscarab.ui.swing.SwingPluginUI; import org.owasp.webscarab.ui.swing.ConversationTableModel; import org.owasp.webscarab.ui.swing.ColumnWidthTracker; import org.owasp.webscarab.util.swing.ColumnDataModel; import org.owasp.webscarab.util.swing.MultiLineCellRenderer; import org.owasp.webscarab.util.swing.ListComboBoxModel; import javax.swing.JPanel; import javax.swing.Action; import javax.swing.AbstractAction; import javax.swing.DefaultListModel; import javax.swing.SwingUtilities; import javax.swing.ListSelectionModel; import javax.swing.JList; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.util.Map; import java.util.HashMap; import javax.swing.AbstractListModel; /** * * @author rogan */ public class FragmentsPanel extends javax.swing.JPanel implements SwingPluginUI { /** * */ private static final long serialVersionUID = 383270526566796972L; private FragmentsModel _model = null; private String _type = null; private Action[] _conversationActions; private Action[] _urlActions; private Map<String, ColumnDataModel<ConversationID>> _conversationColumns = new HashMap<String, ColumnDataModel<ConversationID>>(); private Map<String, ColumnDataModel<HttpUrl>> _urlColumns = new HashMap<String, ColumnDataModel<HttpUrl>>(); private DefaultListModel _typeListModel = new DefaultListModel(); private FragmentListModel _flm = new FragmentListModel(); private Listener _listener = new Listener(); private static final ColumnDataModel[] CDM = new ColumnDataModel[0]; /** Creates new form FragmentsPanel */ public FragmentsPanel(Fragments fragments) { initComponents(); _model = fragments.getModel(); fragmentList.setCellRenderer(new FragmentRenderer()); fragmentList.setModel(_flm); fragmentList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); _typeListModel.addElement(FragmentsModel.KEY_COMMENTS); _typeListModel.addElement(FragmentsModel.KEY_SCRIPTS); _typeListModel.addElement(FragmentsModel.KEY_HIDDENFIELD); _typeListModel.addElement(FragmentsModel.KEY_FILEUPLOAD); _typeListModel.addElement(FragmentsModel.KEY_DOMXSS); _typeListModel.addElement(FragmentsModel.KEY_FORMS); typeComboBox.setModel(new ListComboBoxModel(_typeListModel)); typeComboBox.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { _type = (String) typeComboBox.getSelectedItem(); _flm.setFilter(null, _type); } }); fragmentList.addListSelectionListener(new FragmentsListListener()); conversationTable.setModel(new ConversationTableModel(_model.getConversationModel())); ColumnWidthTracker.getTracker("ConversationTable").addTable(conversationTable); createActions(); _model.addModelListener(_listener); } private void createActions() { _conversationActions = new Action[] { new FragmentsAction("CONVERSATION", FragmentsModel.KEY_SCRIPTS), new FragmentsAction("CONVERSATION",FragmentsModel.KEY_COMMENTS) }; _urlActions = new Action[] { new FragmentsAction("URL", FragmentsModel.KEY_SCRIPTS), new FragmentsAction("URL",FragmentsModel.KEY_COMMENTS) }; class ConversationCDM extends ColumnDataModel<ConversationID> { private String _key; public ConversationCDM(String key, String name) { super(name, Boolean.class); this._key = key; } public Object getValue(ConversationID key) { if (_model == null) return null; String[] value = _model.getConversationFragmentKeys(key, _key); return Boolean.valueOf(value != null && value.length > 0); } } class UrlCDM extends ColumnDataModel<HttpUrl> { private String _key; public UrlCDM(String key, String name) { super(name, Boolean.class); this._key = key; } public Object getValue(HttpUrl key) { if (_model == null) return null; String[] keys = _model.getUrlFragmentKeys(key, _key); return Boolean.valueOf(keys != null && keys.length > 0); } } _conversationColumns.put(FragmentsModel.KEY_COMMENTS, new ConversationCDM( FragmentsModel.KEY_COMMENTS, "Comments")); _urlColumns.put(FragmentsModel.KEY_COMMENTS, new UrlCDM( FragmentsModel.KEY_COMMENTS, "Comments")); _conversationColumns.put(FragmentsModel.KEY_SCRIPTS, new ConversationCDM( FragmentsModel.KEY_SCRIPTS, "Scripts")); _urlColumns.put(FragmentsModel.KEY_SCRIPTS, new UrlCDM( FragmentsModel.KEY_SCRIPTS, "Scripts")); _conversationColumns.put(FragmentsModel.KEY_FILEUPLOAD, new ConversationCDM( FragmentsModel.KEY_FILEUPLOAD, "File upload")); _urlColumns.put(FragmentsModel.KEY_FILEUPLOAD, new UrlCDM( FragmentsModel.KEY_FILEUPLOAD, "File upload")); _conversationColumns.put(FragmentsModel.KEY_DOMXSS, new ConversationCDM( FragmentsModel.KEY_DOMXSS, "DomXss")); _urlColumns.put(FragmentsModel.KEY_DOMXSS, new UrlCDM( FragmentsModel.KEY_DOMXSS, "DomXss")); _conversationColumns.put(FragmentsModel.KEY_FORMS, new ConversationCDM( FragmentsModel.KEY_FORMS, "Forms")); _urlColumns.put(FragmentsModel.KEY_FORMS, new UrlCDM( FragmentsModel.KEY_FORMS, "Forms")); _conversationColumns.put(FragmentsModel.KEY_HIDDENFIELD, new ConversationCDM( FragmentsModel.KEY_HIDDENFIELD, "Hidden fields")); _urlColumns.put(FragmentsModel.KEY_HIDDENFIELD, new UrlCDM( FragmentsModel.KEY_HIDDENFIELD, "Hidden fields")); } /** * 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. */ private void initComponents() {//GEN-BEGIN:initComponents jSplitPane1 = new javax.swing.JSplitPane(); jPanel1 = new javax.swing.JPanel(); jScrollPane1 = new javax.swing.JScrollPane(); fragmentList = new javax.swing.JList(); typeComboBox = new javax.swing.JComboBox(); jScrollPane2 = new javax.swing.JScrollPane(); conversationTable = new javax.swing.JTable(); setLayout(new java.awt.BorderLayout()); setPreferredSize(new java.awt.Dimension(602, 570)); jSplitPane1.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT); jSplitPane1.setResizeWeight(0.65); jSplitPane1.setOneTouchExpandable(true); jPanel1.setLayout(new java.awt.BorderLayout()); jPanel1.setMinimumSize(new java.awt.Dimension(400, 300)); jPanel1.setPreferredSize(new java.awt.Dimension(400, 300)); jScrollPane1.setViewportView(fragmentList); jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER); jPanel1.add(typeComboBox, java.awt.BorderLayout.NORTH); jSplitPane1.setLeftComponent(jPanel1); jScrollPane2.setPreferredSize(new java.awt.Dimension(200, 200)); conversationTable.setModel(new javax.swing.table.DefaultTableModel( new Object [][] { {null, null, null, null}, {null, null, null, null}, {null, null, null, null}, {null, null, null, null} }, new String [] { "Title 1", "Title 2", "Title 3", "Title 4" } )); conversationTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_OFF); jScrollPane2.setViewportView(conversationTable); jSplitPane1.setRightComponent(jScrollPane2); add(jSplitPane1, java.awt.BorderLayout.CENTER); }//GEN-END:initComponents public Action[] getConversationActions() { return _conversationActions; } public JPanel getPanel() { return this; } public String getPluginName() { return "Fragments"; } public Action[] getUrlActions() { return _urlActions; } public ColumnDataModel<ConversationID>[] getConversationColumns() { return _conversationColumns.values().toArray(CDM); } public ColumnDataModel<HttpUrl>[] getUrlColumns() { return _urlColumns.values().toArray(CDM); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTable conversationTable; private javax.swing.JList fragmentList; private javax.swing.JPanel jPanel1; private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JSplitPane jSplitPane1; private javax.swing.JComboBox typeComboBox; // End of variables declaration//GEN-END:variables private class FragmentsAction extends AbstractAction { /** * */ private static final long serialVersionUID = -4183487246345191629L; private String _type; private String _where; public FragmentsAction(String where, String type) { _where = where; _type = type; putValue(NAME, "Show " + _type.toLowerCase()); putValue(SHORT_DESCRIPTION, "Displays any " + _type.toLowerCase() + " seen in the " + _where.toLowerCase()); putValue(_where, null); } private String[] getFragments() { String[] fragments = new String[0]; Object o = getValue(_where); if (_where.equals("URL") && o instanceof HttpUrl) { HttpUrl url = (HttpUrl) o; fragments = _model.getUrlFragmentKeys(url, _type); } else if (_where.equals("CONVERSATION") && o instanceof ConversationID) { ConversationID id = (ConversationID) o; fragments = _model.getConversationFragmentKeys(id, _type); } // translate fragment keys into actual fragments for (int i=0; i<fragments.length; i++) { fragments[i] = _model.getFragment(fragments[i]); } return fragments; } public void actionPerformed(java.awt.event.ActionEvent e) { String[] fragments = getFragments(); if (fragments.length > 0) { FragmentsFrame ff = new FragmentsFrame(); ff.setFragments(fragments); ff.setTitle(_type + " in " + _where + " " + getValue(_where)); ff.setVisible(true); } } public void putValue(String key, Object value) { super.putValue(key, value); if (key != null && key.equals(_where)) { if (value != null && getFragments().length > 0) { setEnabled(true); } else { setEnabled(false); } } } } private class Listener implements FragmentListener { public void fragmentAdded(final HttpUrl url, final ConversationID id, final String type, String key) { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { ColumnDataModel<HttpUrl> ucdm = _urlColumns.get(type); if (ucdm != null) ucdm.fireValueChanged(url); ColumnDataModel<ConversationID> ccdm = _conversationColumns.get(type); if (ccdm != null) ccdm.fireValueChanged(id); } }); } catch (Exception e) { e.printStackTrace(); } } public void fragmentAdded(String type, String key, int position) { } public void fragmentsChanged() { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { _flm.fireContentsChanged(); } }); } catch (Exception e) { e.printStackTrace(); } } } private class FragmentListModel extends AbstractListModel implements FragmentListener { /** * */ private static final long serialVersionUID = -2253303710061129296L; private String _type = null; private int _size = 0; public FragmentListModel() { } public void setFilter(Object id, String type) { fireIntervalRemoved(this, 0, getSize()); _type = type; fireIntervalAdded(this, 0, getSize()); } public Object getElementAt(int index) { return _model.getFragmentKeyAt(_type, index); } public int getSize() { if (_type == null) return 0; _size = _model.getFragmentCount(_type); return _size; } protected void fireContentsChanged() { if (_size > 0) fireIntervalRemoved(this, 0, _size); if (getSize()>0) fireIntervalAdded(this, 0, getSize()); } public void fragmentAdded(HttpUrl url, ConversationID id, String type, String key) {} public void fragmentAdded(String type, String key, final int position) { if (_type == null || !_type.equals(type)) return; try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { fireIntervalAdded(this, position, position); } }); } catch (Exception e) { e.printStackTrace(); } } public void fragmentsChanged() { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { fireContentsChanged(); } }); } catch (Exception e) { e.printStackTrace(); } } } private class FragmentRenderer extends MultiLineCellRenderer { /** * */ private static final long serialVersionUID = -6061481472856144741L; public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { if (value instanceof String) { value = _model.getFragment((String) value); } return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); } } private class FragmentsListListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting()) return; if (_type == null) return; int selected = fragmentList.getSelectedIndex(); String key = null; if (selected > -1) key = (String) _flm.getElementAt(selected); _model.setSelectedFragment(_type, key); } } }