/*********************************************************************** * * $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 * */ /* * SpiderPanel.java * * Created on August 6, 2003, 10:01 PM */ package org.owasp.webscarab.plugin.spider.swing; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import org.owasp.webscarab.model.ConversationID; import org.owasp.webscarab.model.HttpUrl; import org.owasp.webscarab.plugin.spider.Link; import org.owasp.webscarab.plugin.spider.Spider; import org.owasp.webscarab.plugin.spider.SpiderModel; import org.owasp.webscarab.plugin.spider.SpiderUI; import org.owasp.webscarab.ui.swing.HeaderPanel; import org.owasp.webscarab.ui.swing.SwingPluginUI; import org.owasp.webscarab.ui.swing.UrlTreeModelAdapter; import org.owasp.webscarab.ui.swing.UrlTreeRenderer; import org.owasp.webscarab.util.swing.ColumnDataModel; /** * * @author rdawes */ public class SpiderPanel extends javax.swing.JPanel implements SwingPluginUI, SpiderUI { /** * */ private static final long serialVersionUID = 8563871484142539698L; private SpiderModel _model; private Spider _spider; private Logger _logger = Logger.getLogger(this.getClass().getName()); private HeaderPanel _hp; /** Creates new form SpiderPanel */ public SpiderPanel(Spider spider) { initComponents(); _hp = new HeaderPanel(); _hp.setEditable(true); _spider = spider; _model = _spider.getModel(); TreeModel treeModel = new UrlTreeModelAdapter(_model.getUrlModel()); unseenLinkTree.setModel(treeModel); unseenLinkTree.setRootVisible(false); unseenLinkTree.setShowsRootHandles(true); unseenLinkTree.setCellRenderer(new UrlTreeRenderer()); configure(); } public javax.swing.JPanel getPanel() { return this; } public String getPluginName() { return new String("Spider"); } private void configure() { recursiveCheckBox.setSelected(_model.getRecursive()); cookieSyncCheckBox.setSelected(_model.getCookieSync()); domainRegexTextField.setText(_model.getAllowedDomains()); pathRegexTextField.setText(_model.getForbiddenPaths()); } /** 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 java.awt.GridBagConstraints gridBagConstraints; jLabel1 = new javax.swing.JLabel(); domainRegexTextField = new javax.swing.JTextField(); jLabel2 = new javax.swing.JLabel(); pathRegexTextField = new javax.swing.JTextField(); recursiveCheckBox = new javax.swing.JCheckBox(); stopButton = new javax.swing.JButton(); cookieSyncCheckBox = new javax.swing.JCheckBox(); linkTreePanel = new javax.swing.JPanel(); jScrollPane2 = new javax.swing.JScrollPane(); unseenLinkTree = new javax.swing.JTree(); linkTreeFetchSelectionButton = new javax.swing.JButton(); linkTreeFetchTreeButton = new javax.swing.JButton(); headerButton = new javax.swing.JButton(); setLayout(new java.awt.GridBagLayout()); jLabel1.setText("Allowed Domains"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; add(jLabel1, gridBagConstraints); domainRegexTextField.setToolTipText("A regular expression describing which domains to include"); domainRegexTextField.setMinimumSize(new java.awt.Dimension(60, 19)); domainRegexTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { domainRegexTextFieldActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; add(domainRegexTextField, gridBagConstraints); jLabel2.setText("Forbidden Paths"); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 0; add(jLabel2, gridBagConstraints); pathRegexTextField.setToolTipText("A regular expression describing which paths to exclude"); pathRegexTextField.setMinimumSize(new java.awt.Dimension(60, 19)); pathRegexTextField.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { pathRegexTextFieldActionPerformed(evt); } }); pathRegexTextField.addFocusListener(new java.awt.event.FocusAdapter() { public void focusLost(java.awt.event.FocusEvent evt) { pathRegexTextFieldFocusLost(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 3; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints.weightx = 1.0; add(pathRegexTextField, gridBagConstraints); recursiveCheckBox.setText("Fetch Recursively"); recursiveCheckBox.setToolTipText("Enables recursive fetching of Links"); recursiveCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); recursiveCheckBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { recursiveCheckBoxActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 2; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; add(recursiveCheckBox, gridBagConstraints); 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 = 2; gridBagConstraints.gridy = 3; add(stopButton, gridBagConstraints); cookieSyncCheckBox.setText("Synchronise cookies"); cookieSyncCheckBox.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); cookieSyncCheckBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { cookieSyncCheckBoxActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.gridwidth = 2; gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST; add(cookieSyncCheckBox, gridBagConstraints); linkTreePanel.setLayout(new java.awt.GridBagLayout()); jScrollPane2.setViewportView(unseenLinkTree); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; linkTreePanel.add(jScrollPane2, gridBagConstraints); linkTreeFetchSelectionButton.setText("Fetch Selection"); linkTreeFetchSelectionButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { linkTreeFetchSelectionButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 1; gridBagConstraints.weightx = 1.0; linkTreePanel.add(linkTreeFetchSelectionButton, gridBagConstraints); linkTreeFetchTreeButton.setText("Fetch Tree"); linkTreeFetchTreeButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { linkTreeFetchTreeButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 1; gridBagConstraints.weightx = 1.0; linkTreePanel.add(linkTreeFetchTreeButton, gridBagConstraints); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 2; gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; add(linkTreePanel, gridBagConstraints); headerButton.setText("Headers"); headerButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { headerButtonActionPerformed(evt); } }); gridBagConstraints = new java.awt.GridBagConstraints(); gridBagConstraints.gridx = 1; gridBagConstraints.gridy = 3; add(headerButton, gridBagConstraints); }//GEN-END:initComponents private void headerButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_headerButtonActionPerformed _hp.setHeaders(_model.getExtraHeaders()); JOptionPane.showMessageDialog(this, _hp, "Spider Extra Headers", JOptionPane.PLAIN_MESSAGE); _model.setExtraHeaders(_hp.getHeaders()); }//GEN-LAST:event_headerButtonActionPerformed private void cookieSyncCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cookieSyncCheckBoxActionPerformed _model.setCookieSync(cookieSyncCheckBox.isSelected()); }//GEN-LAST:event_cookieSyncCheckBoxActionPerformed private void linkTreeFetchTreeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_linkTreeFetchTreeButtonActionPerformed TreePath[] selection = unseenLinkTree.getSelectionPaths(); if (selection != null && selection.length==1) { if (_spider.isBusy()) { _logger.warning("Spider is still busy, please wait"); JOptionPane.showMessageDialog(SpiderPanel.this, "Spider is still busy, please wait"); return; } HttpUrl url = (HttpUrl) selection[0].getLastPathComponent(); _spider.requestLinksUnder(url); } else { _logger.info("Cannot fetch a tree if there are 0 or many paths selected!"); JOptionPane.showMessageDialog(SpiderPanel.this, "Cannot fetch a tree if there are 0 or many paths selected!"); } }//GEN-LAST:event_linkTreeFetchTreeButtonActionPerformed private void linkTreeFetchSelectionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_linkTreeFetchSelectionButtonActionPerformed TreePath[] selection = unseenLinkTree.getSelectionPaths(); if (selection == null || selection.length == 0) return; if (_spider.isBusy()) { _logger.warning("Spider is still busy, please wait"); // FIXME show a message return; } unseenLinkTree.clearSelection(); HttpUrl[] urls = new HttpUrl[selection.length]; for (int i=0; i<selection.length; i++) { urls[i] = (HttpUrl) selection[i].getLastPathComponent(); } _spider.requestLinks(urls); }//GEN-LAST:event_linkTreeFetchSelectionButtonActionPerformed private void pathRegexTextFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_pathRegexTextFieldFocusLost //_model.setForbiddenPaths(pathRegexTextField.getText()); }//GEN-LAST:event_pathRegexTextFieldFocusLost private void pathRegexTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pathRegexTextFieldActionPerformed _model.setForbiddenPaths(pathRegexTextField.getText()); }//GEN-LAST:event_pathRegexTextFieldActionPerformed private void domainRegexTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_domainRegexTextFieldActionPerformed _model.setAllowedDomains(domainRegexTextField.getText()); }//GEN-LAST:event_domainRegexTextFieldActionPerformed private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_stopButtonActionPerformed _spider.clearQueue(); }//GEN-LAST:event_stopButtonActionPerformed private void recursiveCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_recursiveCheckBoxActionPerformed _model.setRecursive(recursiveCheckBox.isSelected()); }//GEN-LAST:event_recursiveCheckBoxActionPerformed public Action[] getConversationActions() { return null; } public Action[] getUrlActions() { return new Action[] {new SpiderAction()}; } public void linkDequeued(final Link link, final int queueSize) { if (SwingUtilities.isEventDispatchThread()) { if (link != null) { // _logger.info(queueSize + " in queue, fetching " + link.getURL()); } else { // _logger.info("Cleared queue"); } } else { SwingUtilities.invokeLater(new Runnable() { public void run() { linkDequeued(link, queueSize); } }); } } public void linkQueued(final Link link, final int queueSize) { if (SwingUtilities.isEventDispatchThread()) { _logger.fine(queueSize + " in queue, adding: " + link.getURL()); } else { SwingUtilities.invokeLater(new Runnable() { public void run() { linkQueued(link, queueSize); } }); } } public void setEnabled(final boolean enabled) { if (SwingUtilities.isEventDispatchThread()) { cookieSyncCheckBox.setEnabled(enabled); domainRegexTextField.setEnabled(enabled); linkTreeFetchSelectionButton.setEnabled(enabled); linkTreeFetchTreeButton.setEnabled(enabled); pathRegexTextField.setEnabled(enabled); recursiveCheckBox.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.JCheckBox cookieSyncCheckBox; private javax.swing.JTextField domainRegexTextField; private javax.swing.JButton headerButton; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JScrollPane jScrollPane2; private javax.swing.JButton linkTreeFetchSelectionButton; private javax.swing.JButton linkTreeFetchTreeButton; private javax.swing.JPanel linkTreePanel; private javax.swing.JTextField pathRegexTextField; private javax.swing.JCheckBox recursiveCheckBox; private javax.swing.JButton stopButton; private javax.swing.JTree unseenLinkTree; // End of variables declaration//GEN-END:variables private class SpiderAction extends AbstractAction { /** * */ private static final long serialVersionUID = -2207351321290083769L; public SpiderAction() { putValue(NAME, "Spider tree"); putValue(SHORT_DESCRIPTION, "Fetches any unseen links below this point"); putValue("URL", null); } public void actionPerformed(java.awt.event.ActionEvent e) { Object o = getValue("URL"); if (o == null || !(o instanceof HttpUrl)) return; HttpUrl url = (HttpUrl) o; if (! _spider.isBusy()) { _spider.requestLinksUnder(url); } else { _logger.warning("Spider is still busy, please wait"); JOptionPane.showMessageDialog(SpiderPanel.this, "Spider is still busy, please wait"); } } public void putValue(String key, Object value) { super.putValue(key, value); if (key != null && key.equals("URL")) { if (value != null && value instanceof HttpUrl) { this.setEnabled(true); } else { this.setEnabled(false); } } } } }