/*
*
* Paros and its related class files.
*
* Paros is an HTTP/HTTPS proxy for assessing web application security.
* Copyright (C) 2003-2004 Chinotec Technologies Company
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Clarified Artistic License
* as published by the Free Software Foundation.
*
* 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
* Clarified Artistic License for more details.
*
* You should have received a copy of the Clarified Artistic License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.parosproxy.paros.extension.spider;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.Vector;
import javax.swing.JMenuItem;
import javax.swing.JTree;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.parosproxy.paros.core.spider.Spider;
import org.parosproxy.paros.core.spider.SpiderListener;
import org.parosproxy.paros.core.spider.SpiderParam;
import org.parosproxy.paros.extension.CommandLineArgument;
import org.parosproxy.paros.extension.CommandLineListener;
import org.parosproxy.paros.extension.ExtensionAdaptor;
import org.parosproxy.paros.extension.ExtensionHook;
import org.parosproxy.paros.extension.SessionChangedListener;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.model.Session;
import org.parosproxy.paros.model.SiteMap;
import org.parosproxy.paros.model.SiteNode;
import org.parosproxy.paros.network.HttpMessage;
/**
*
* To change the template for this generated type comment go to Window -
* Preferences - Java - Code Generation - Code and Comments
*/
public class ExtensionSpider extends ExtensionAdaptor implements SpiderListener, SessionChangedListener, CommandLineListener {
private static final int ARG_SPIDER_IDX = 0;
private static final int ARG_URL_IDX = 1;
private JMenuItem menuItemSpider = null;
private SpiderDialog dialog = null;
private Spider spider = null;
private SiteMap siteTree = null;
private SiteNode startNode = null;
private PopupMenuSpider popupMenuSpider = null;
private SpiderPanel spiderPanel = null;
private OptionsSpiderPanel optionsSpiderPanel = null;
private SpiderParam spiderParam = null;
private CommandLineArgument[] arguments = new CommandLineArgument[2];
// ZAP: Added logger
private static Log log = LogFactory.getLog(ExtensionSpider.class);
/**
*
*/
public ExtensionSpider() {
super();
initialize();
}
/**
* @param name
*/
public ExtensionSpider(String name) {
super(name);
}
/**
* This method initializes this
*
* @return void
*/
private void initialize() {
this.setName("ExtensionSpider");
}
/**
* This method initializes menuItemSpider
*
* @return javax.swing.JMenuItem
*/
JMenuItem getMenuItemSpider() {
if (menuItemSpider == null) {
menuItemSpider = new JMenuItem();
menuItemSpider.setText("Spider...");
menuItemSpider.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTree siteTree = getView().getSiteTreePanel().getTreeSite();
SiteNode node = (SiteNode) siteTree.getLastSelectedPathComponent();
HttpMessage msg = null;
if (node == null) {
getView().showWarningDialog("You need to visit the website via a browser first and select a URL/folder/node in the 'Sites' panel displayed.");
return;
}
setStartNode(node);
if (node.isRoot()) {
showDialog("All sites will be crawled");
} else {
try {
msg = node.getHistoryReference().getHttpMessage();
} catch (Exception e1) {
// ZAP: Log exceptions
log.warn(e1.getMessage(), e1);
return;
}
String tmp = msg.getRequestHeader().getURI().toString();
showDialog(tmp);
}
}
});
}
return menuItemSpider;
}
public void hook(ExtensionHook extensionHook) {
super.hook(extensionHook);
if (getView() != null) {
extensionHook.getHookMenu().addAnalyseMenuItem(getMenuItemSpider());
extensionHook.getHookMenu().addAnalyseMenuItem(extensionHook.getHookMenu().getMenuSeparator());
extensionHook.getHookMenu().addPopupMenuItem(getPopupMenuSpider());
extensionHook.getHookView().addStatusPanel(getSpiderPanel());
extensionHook.getHookView().addOptionPanel(getOptionsSpiderPanel());
}
extensionHook.addSessionListener(this);
extensionHook.addOptionsParamSet(getSpiderParam());
extensionHook.addCommandLine(getCommandLineArguments());
}
public void startSpider() {
siteTree = getModel().getSession().getSiteTree();
if (startNode == null) {
startNode = (SiteNode) siteTree.getRoot();
}
startSpider(startNode);
}
private void startSpider(SiteNode startNode) {
if (spider == null) {
try {
getModel().getDb().getTableHistory().deleteHistoryType(
getModel().getSession().getSessionId(),
HistoryReference.TYPE_SPIDER_SEED);
getModel().getDb().getTableHistory().deleteHistoryType(
getModel().getSession().getSessionId(),
HistoryReference.TYPE_SPIDER_VISITED);
} catch (SQLException e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
spider = new Spider(getSpiderParam(), getModel().getOptionsParam().getConnectionParam(), getModel());
spider.addSpiderListener(this);
inOrderSeed(spider, startNode);
}
getSpiderPanel().setTabFocus();
try {
spider.start();
} catch (NullPointerException e1) {
// ZAP: Log exceptions
log.warn(e1.getMessage(), e1);
}
}
private void inOrderSeed(Spider spider, SiteNode node) {
try {
if (!node.isRoot()) {
HttpMessage msg = node.getHistoryReference().getHttpMessage();
if (msg != null) {
if (!msg.getResponseHeader().isImage()) {
spider.addSeed(msg);
}
}
}
} catch (Exception e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
if (!node.isLeaf()) {
for (int i = 0; i < node.getChildCount(); i++) {
try {
inOrderSeed(spider, (SiteNode) node.getChildAt(i));
} catch (Exception e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
}
}
}
public void spiderComplete() {
try {
getModel().getDb().getTableHistory().deleteHistoryType(
getModel().getSession().getSessionId(),
HistoryReference.TYPE_SPIDER_SEED);
getModel().getDb().getTableHistory().deleteHistoryType(
getModel().getSession().getSessionId(),
HistoryReference.TYPE_SPIDER_VISITED);
} catch (SQLException e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
if (getView() != null) {
getMenuItemSpider().setEnabled(true);
getPopupMenuSpider().setEnabled(true);
}
try {
Thread.sleep(3000);
} catch (Exception e) {
}
if (getView() != null && dialog != null) {
if (EventQueue.isDispatchThread()) {
dialog.dispose();
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
dialog.dispose();
}
});
} catch (Exception e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
}
}
public void foundURI(HttpMessage msg, boolean isSkip) {
if (getView() != null) {
if (isSkip) {
getSpiderPanel().appendFoundButSkip(
msg.getRequestHeader().getURI().toString() + "\n");
} else {
getSpiderPanel().appendFound(
msg.getRequestHeader().getURI().toString() + "\n");
}
}
}
public void readURI(HttpMessage msg) {
SiteMap siteTree = getModel().getSession().getSiteTree();
HistoryReference historyRef = null;
try {
historyRef = new HistoryReference(getModel().getSession(),
HistoryReference.TYPE_SPIDER, msg);
} catch (Exception e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
siteTree.addPath(historyRef, msg);
}
public Spider getSpider() {
return spider;
}
public void spiderProgress(final URI uri, final int percentageComplete,
final int numberCrawled, final int numberToCrawl) {
String uriString = "";
if (dialog != null) {
if (EventQueue.isDispatchThread()) {
dialog.getTxtNumCrawled().setText(
Integer.toString(numberCrawled));
dialog.getTxtOutstandingCrawl().setText(
Integer.toString(numberToCrawl));
dialog.getProgressBar().setValue(percentageComplete);
uriString = "";
if (uri != null) {
uriString = uri.toString();
}
dialog.getTxtDisplay().setText(uriString);
// dialog.getTxtDisplay().setCaretPosition(0);
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
public void run() {
String uriString = "";
dialog.getTxtNumCrawled().setText(
Integer.toString(numberCrawled));
dialog.getTxtOutstandingCrawl().setText(
Integer.toString(numberToCrawl));
dialog.getProgressBar().setValue(percentageComplete);
if (uri != null) {
uriString = uri.toString();
}
dialog.getTxtDisplay().setText(uriString);
}
});
} catch (Exception e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
}
}
/**
* @return Returns the startNode.
*/
public SiteNode getStartNode() {
return startNode;
}
/**
* @param startNode
* The startNode to set.
*/
public void setStartNode(SiteNode startNode) {
this.startNode = startNode;
}
void showDialog(String msg) {
dialog = new SpiderDialog(getView().getMainFrame(), false);
dialog.setPlugin(ExtensionSpider.this);
dialog.setVisible(true);
dialog.getTxtDisplay().setText(msg);
spider = null;
}
/**
* This method initializes popupMenuSpider
*
* @return com.proofsecure.paros.plugin.Spider.PopupMenuSpider
*/
PopupMenuSpider getPopupMenuSpider() {
if (popupMenuSpider == null) {
popupMenuSpider = new PopupMenuSpider();
popupMenuSpider.setExtension(this);
}
return popupMenuSpider;
}
void clear() {
spider = null;
System.gc();
}
/**
* This method initializes spiderPanel
*
* @return org.parosproxy.paros.extension.spider.SpiderPanel
*/
private SpiderPanel getSpiderPanel() {
if (spiderPanel == null) {
spiderPanel = new SpiderPanel();
}
return spiderPanel;
}
/*
* (non-Javadoc)
*
* @see
* org.parosproxy.paros.extension.SessionChangedListener#sessionChanged(
* org.parosproxy.paros.model.Session)
*/
public void sessionChanged(Session session) {
getSpiderPanel().clear();
}
/**
* This method initializes optionsSpiderPanel
*
* @return org.parosproxy.paros.extension.spider.OptionsSpiderPanel
*/
private OptionsSpiderPanel getOptionsSpiderPanel() {
if (optionsSpiderPanel == null) {
optionsSpiderPanel = new OptionsSpiderPanel();
}
return optionsSpiderPanel;
}
/**
* This method initializes spiderParam
*
* @return org.parosproxy.paros.core.spider.SpiderParam
*/
private SpiderParam getSpiderParam() {
if (spiderParam == null) {
spiderParam = new SpiderParam();
}
return spiderParam;
}
/*
* (non-Javadoc)
*
* @see
* org.parosproxy.paros.extension.CommandLineListener#execute(org.parosproxy
* .paros.extension.CommandLineArgument[])
*/
public void execute(CommandLineArgument[] args) {
String uri = null;
if (!arguments[ARG_URL_IDX].isEnabled()
&& (arguments[ARG_SPIDER_IDX].isEnabled())) {
return;
}
spider = new Spider(getSpiderParam(), getModel().getOptionsParam()
.getConnectionParam(), getModel());
spider.addSpiderListener(this);
if (arguments[ARG_URL_IDX].isEnabled()) {
Vector<String> v = arguments[ARG_URL_IDX].getArguments();
for (int i = 0; i < v.size(); i++) {
uri = v.get(i);
try {
System.out.println("Adding seed " + uri);
spider.addSeed(new URI(uri, true));
} catch (URIException e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
}
}
if (arguments[ARG_SPIDER_IDX].isEnabled()) {
System.out.println("Starting spider...");
spider.start();
}
while (!spider.isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ZAP: Log exceptions
log.warn(e.getMessage(), e);
}
}
System.out.println("Spider completed.");
}
private CommandLineArgument[] getCommandLineArguments() {
arguments[ARG_SPIDER_IDX] = new CommandLineArgument("-spider", 0, null,
"", "-spider : run spider. See other parameters");
arguments[ARG_URL_IDX] = new CommandLineArgument("-seed", -1,
"https{0,1}://\\S+", "Seed should be a URL",
"-seed {URL1} {URL2} ... : Add seeds to the spider for crawling.");
return arguments;
}
} // @jve:decl-index=0: