All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.parosproxy.paros.view.SiteMapPanel Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

There is a newer version: 2.16.0
Show newest version
/*
 *
 * 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.
 */
// ZAP: 2012/03/03 Moved popups to stdmenus extension
// ZAP: 2012/03/15 Changed to initiate the tree with a default model. Changed to
// clear the http panels when the root node is selected.
// ZAP: 2012/04/23 Added @Override annotation to all appropriate methods.
// ZAP: 2012/06/13 Added custom tree cell renderer to treeSite in getTreeSite().
// ZAP: 2013/01/25 Added method for removing listener.
// ZAP: 2013/11/16 Issue 886: Main pop up menu invoked twice on some components
// ZAP: 2014/01/28 Issue 207: Support keyboard shortcuts 
// ZAP: 2014/03/23 Tidy up, removed the instance variable rootTreePath, no need to
// cache the path
// ZAP: 2014/03/23 Issue 609: Provide a common interface to query the state and 
// access the data (HttpMessage and HistoryReference) displayed in the tabs
// ZAP: 2014/10/07 Issue 1357: Hide unused tabs
// ZAP: 2014/12/17 Issue 1174: Support a Site filter
// ZAP: 2014/12/22 Issue 1476: Display contexts in the Sites tree
// ZAP: 2015/02/09 Issue 1525: Introduce a database interface layer to allow for alternative implementations
// ZAP: 2015/02/10 Issue 1528: Support user defined font size
// ZAP: 2015/06/01 Issue 1653: Support context menu key for trees
// ZAP: 2016/04/14 Use View to display the HTTP messages
// ZAP: 2016/07/01 Issue 2642: Slow mouse wheel scrolling in site tree

package org.parosproxy.paros.view;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import javax.swing.JTree;
import javax.swing.KeyStroke;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.db.DatabaseException;
import org.parosproxy.paros.extension.AbstractPanel;
import org.parosproxy.paros.extension.history.LogPanel;
import org.parosproxy.paros.model.HistoryReference;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.model.SiteMap;
import org.parosproxy.paros.model.SiteNode;
import org.parosproxy.paros.network.HttpMessage;
import org.zaproxy.zap.extension.history.HistoryFilterPlusDialog;
import org.zaproxy.zap.model.Context;
import org.zaproxy.zap.model.Target;
import org.zaproxy.zap.utils.DisplayUtils;
import org.zaproxy.zap.view.ContextCreateDialog;
import org.zaproxy.zap.view.ContextGeneralPanel;
import org.zaproxy.zap.view.ContextsSitesPanel;
import org.zaproxy.zap.view.ContextsTreeCellRenderer;
import org.zaproxy.zap.view.LayoutHelper;
import org.zaproxy.zap.view.SiteMapListener;
import org.zaproxy.zap.view.SiteMapTreeCellRenderer;
import org.zaproxy.zap.view.SiteTreeFilter;
import org.zaproxy.zap.view.ZapToggleButton;
import org.zaproxy.zap.view.messagecontainer.http.DefaultSelectableHistoryReferencesContainer;
import org.zaproxy.zap.view.messagecontainer.http.SelectableHistoryReferencesContainer;


public class SiteMapPanel extends AbstractPanel {

	public static final String CONTEXT_TREE_COMPONENT_NAME	= "ContextTree";
	
	private static final long serialVersionUID = -3161729504065679088L;

	// ZAP: Added logger
    private static Logger log = Logger.getLogger(SiteMapPanel.class);

	private JTree treeSite = null;
	private JTree treeContext = null;
	private DefaultTreeModel contextTree = null;
	private View view = null;

	private javax.swing.JToolBar panelToolbar = null;
	private ZapToggleButton scopeButton = null;
	private JButton filterButton = null;
	private JLabel filterStatus = null;
	private HistoryFilterPlusDialog filterPlusDialog = null;
	private JButton createContextButton = null;
	private JButton importContextButton = null;
	private JButton exportContextButton = null;

	// ZAP: Added SiteMapListenners
	private List listeners = new ArrayList<>();
	
	/**
	 * This is the default constructor
	 */
	public SiteMapPanel() {
		super();
		initialize();
	}

	private View getView() {
	    if (view == null) {
	        view = View.getSingleton();
	    }
	    
	    return view;
	}
	/**
	 * This method initializes this
	 */
	private  void initialize() {
		this.setHideable(false);
	    this.setIcon(new ImageIcon(View.class.getResource("/resource/icon/16/094.png")));
	    this.setName(Constant.messages.getString("sites.panel.title"));
		this.setDefaultAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | Event.SHIFT_MASK, false));
		this.setMnemonic(Constant.messages.getChar("sites.panel.mnemonic"));

	    if (Model.getSingleton().getOptionsParam().getViewParam().getWmUiHandlingOption() == 0) {
	    	this.setSize(300,200);
	    }
		
		this.setLayout(new GridBagLayout());
		this.add(this.getPanelToolbar(), LayoutHelper.getGBC(0, 0, 1, 0, new Insets(2,2,2,2)));
		this.add(new ContextsSitesPanel(getTreeContext(), getTreeSite(), "sitesPanelScrollPane"), 
				LayoutHelper.getGBC(0, 1, 1, 1.0, 1.0, GridBagConstraints.BOTH, new Insets(2,2,2,2)));

        expandRoot();
	}
	
	private javax.swing.JToolBar getPanelToolbar() {
		if (panelToolbar == null) {
			
			panelToolbar = new javax.swing.JToolBar();
			panelToolbar.setLayout(new GridBagLayout());
			panelToolbar.setEnabled(true);
			panelToolbar.setFloatable(false);
			panelToolbar.setRollover(true);
			panelToolbar.setPreferredSize(new Dimension(800,30));
			panelToolbar.setName("ScriptsListToolbar");
			
			int i = 1;
			panelToolbar.add(getScopeButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			panelToolbar.add(getCreateContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			panelToolbar.add(getImportContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			panelToolbar.add(getExportContextButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			
			// TODO Disabled for now due to problems with scrolling with sparcely populated filtered trees
			//panelToolbar.add(getFilterButton(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			//panelToolbar.add(getFilterStatus(), LayoutHelper.getGBC(i++, 0, 1, 0.0D));
			panelToolbar.add(new JLabel(), LayoutHelper.getGBC(20, 0, 1, 1.0D));	// spacer
		}
		return panelToolbar;
	}

	private HistoryFilterPlusDialog getFilterPlusDialog() {
		if (filterPlusDialog == null) {
			filterPlusDialog = new HistoryFilterPlusDialog(getView().getMainFrame(), true);
			// Override the title as we're reusing the history filter dialog
			filterPlusDialog.setTitle(Constant.messages.getString("sites.filter.title"));
		}
		return filterPlusDialog;
	}
	
	private JLabel getFilterStatus() {
		filterStatus = new JLabel(Constant.messages.getString("history.filter.label.filter") + 
				Constant.messages.getString("history.filter.label.off"));
		return filterStatus;
	}

	private JButton getFilterButton() {
		if (filterButton == null) {
			filterButton = new JButton();
			filterButton.setIcon(DisplayUtils.getScaledIcon(
					new ImageIcon(LogPanel.class.getResource("/resource/icon/16/054.png"))));	// 'filter' icon
			filterButton.setToolTipText(Constant.messages.getString("history.filter.button.filter"));

			filterButton.addActionListener(new java.awt.event.ActionListener() { 

				@Override
				public void actionPerformed(java.awt.event.ActionEvent e) {
					showFilterPlusDialog();
				}
			});
		}
		return filterButton;
	}
	
	private JButton getCreateContextButton() {
		if (createContextButton == null) {
			createContextButton = new JButton();
			createContextButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(
					LogPanel.class.getResource("/resource/icon/fugue/application-blue-plus.png"))));
			createContextButton.setToolTipText(Constant.messages.getString("menu.file.context.create"));
			createContextButton.addActionListener(new java.awt.event.ActionListener() { 
				@Override
				public void actionPerformed(java.awt.event.ActionEvent e) {
					ContextCreateDialog ccd = new ContextCreateDialog(View.getSingleton().getMainFrame());
					ccd.setVisible(true);
				}
			});
		}
		return createContextButton;
	}

	private JButton getImportContextButton() {
		if (importContextButton == null) {
			importContextButton = new JButton();
			importContextButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(
					LogPanel.class.getResource("/resource/icon/fugue/application-blue-import.png"))));
			importContextButton.setToolTipText(Constant.messages.getString("menu.file.context.import"));
			importContextButton.addActionListener(new java.awt.event.ActionListener() { 
				@Override
				public void actionPerformed(java.awt.event.ActionEvent e) {
					Control.getSingleton().getMenuFileControl().importContext();
				}
			});
		}
		return importContextButton;
	}

	private JButton getExportContextButton() {
		if (exportContextButton == null) {
			exportContextButton = new JButton();
			exportContextButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(
					LogPanel.class.getResource("/resource/icon/fugue/application-blue-export.png"))));
			exportContextButton.setToolTipText(Constant.messages.getString("menu.file.context.export"));
			exportContextButton.addActionListener(new java.awt.event.ActionListener() { 
				@Override
				public void actionPerformed(java.awt.event.ActionEvent e) {
					Control.getSingleton().getMenuFileControl().exportContext();
				}
			});
		}
		return exportContextButton;
	}

	private void showFilterPlusDialog() {
		HistoryFilterPlusDialog dialog = getFilterPlusDialog();
		dialog.setModal(true);
    	try {
			dialog.setAllTags(Model.getSingleton().getDb().getTableTag().getAllTags());
		} catch (DatabaseException e) {
			log.error(e.getMessage(), e);
		}

		int exit = dialog.showDialog();
		SiteTreeFilter filter = new SiteTreeFilter(dialog.getFilter());
		filter.setInScope(this.getScopeButton().isSelected());
		if (exit != JOptionPane.CANCEL_OPTION) {
			setFilter();
		}
	}
	
	private void setFilter() {
		SiteTreeFilter filter = new SiteTreeFilter(getFilterPlusDialog().getFilter());
		filter.setInScope(scopeButton.isSelected());
		((SiteMap)treeSite.getModel()).setFilter(filter);
		((DefaultTreeModel)treeSite.getModel()).nodeStructureChanged((SiteNode)treeSite.getModel().getRoot());
    	getFilterStatus().setText(filter.toShortString());
    	getFilterStatus().setToolTipText(filter.toLongString());
		expandRoot();
		
		// Remove any out of scope contexts too
		this.reloadContextTree();
	}

	private JToggleButton getScopeButton() {
		if (scopeButton == null) {
			scopeButton = new ZapToggleButton();
			scopeButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(SiteMapPanel.class.getResource("/resource/icon/fugue/target-grey.png"))));
			scopeButton.setToolTipText(Constant.messages.getString("history.scope.button.unselected"));
			scopeButton.setSelectedIcon(DisplayUtils.getScaledIcon(new ImageIcon(SiteMapPanel.class.getResource("/resource/icon/fugue/target.png"))));
			scopeButton.setSelectedToolTipText(Constant.messages.getString("history.scope.button.selected"));

			scopeButton.addActionListener(new java.awt.event.ActionListener() { 
				@Override
				public void actionPerformed(java.awt.event.ActionEvent e) {
					setFilter();
				}
			});
		}
		return scopeButton;
	}

	/**
	 * This method initializes treeSite	
	 * 	
	 * @return javax.swing.JTree	
	 */    
	public JTree getTreeSite() {
		if (treeSite == null) {
			treeSite = new JTree(new DefaultTreeModel(new DefaultMutableTreeNode()));
			treeSite.setShowsRootHandles(true);
			treeSite.setName("treeSite");
			treeSite.setToggleClickCount(1);

			treeSite.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() { 

				@Override
				public void valueChanged(javax.swing.event.TreeSelectionEvent e) {    

				    SiteNode node = (SiteNode) treeSite.getLastSelectedPathComponent();
				    if (node == null) {
				        return;
				    }
				    if (!node.isRoot()) {
				    	HttpMessage msg = null;
                        try {
                            msg = node.getHistoryReference().getHttpMessage();
                        } catch (Exception e1) {
                        	// ZAP: Log exceptions
                        	log.warn(e1.getMessage(), e1);
                            return;
                            
                        }

                        getView().displayMessage(msg);

			        	// ZAP: Call SiteMapListenners
			            for (SiteMapListener listener : listeners) {
			            	listener.nodeSelected(node);
			            }
				    } else {
				    	// ZAP: clear the views when the root is selected
				        getView().displayMessage(null);
				    }
	
				}
			});
	        treeSite.setComponentPopupMenu(new SitesCustomPopupMenu());

			// ZAP: Add custom tree cell renderer.
	        DefaultTreeCellRenderer renderer = new SiteMapTreeCellRenderer(listeners);
			treeSite.setCellRenderer(renderer);
		}
		return treeSite;
	}
	
	
	public void reloadContextTree() {
		SiteNode root;
		if (this.contextTree == null) {
			root = new SiteNode(null, -1, Constant.messages.getString("context.list"));
			this.contextTree = new DefaultTreeModel(root);
		} else {
			root = (SiteNode)this.contextTree.getRoot();
			root.removeAllChildren();
		}
		for (Context ctx : Model.getSingleton().getSession().getContexts()) {
			if (ctx.isInScope() || ! this.getScopeButton().isSelected()) {
				// Add all in scope contexts, and out of scope ones if scope button not pressed
	            SiteNode node = new SiteNode(null, HistoryReference.TYPE_PROXIED, ctx.getName());
	            node.setUserObject(new Target(ctx));
				root.add(node);
			}
		}
		this.contextTree.nodeStructureChanged(root);
	}

	private JTree getTreeContext() {
		if (treeContext == null) {
			reloadContextTree();
			treeContext = new JTree(this.contextTree);
			treeContext.setShowsRootHandles(true);
			treeContext.setName(CONTEXT_TREE_COMPONENT_NAME);
			treeContext.setToggleClickCount(1);
			treeContext.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
			
			treeContext.addMouseListener(new java.awt.event.MouseAdapter() { 
				@Override
				public void mousePressed(java.awt.event.MouseEvent e) {
				}
					
				@Override
				public void mouseReleased(java.awt.event.MouseEvent e) {
					mouseClicked(e);
				}
				
				@Override
				public void mouseClicked(java.awt.event.MouseEvent e) {
				    if (treeSite.getLastSelectedPathComponent() != null) {
				    	// They selected a context node, deselect any context
				    	getTreeSite().clearSelection();
				    }
				    if (e.getClickCount() > 1) {
				    	// Its a double click - show the relevant context dialog
					    SiteNode node = (SiteNode) treeContext.getLastSelectedPathComponent();
					    if (node != null && node.getUserObject() != null) {
					    	Target target = (Target)node.getUserObject();
					    	getView().showSessionDialog(Model.getSingleton().getSession(), 
					    			ContextGeneralPanel.getPanelName(target.getContext()));
					    }
				    }
				}
			});
	        treeContext.setComponentPopupMenu(new ContextsCustomPopupMenu());

			treeContext.setCellRenderer(new ContextsTreeCellRenderer());
		}
		return treeContext;
	}

	public void expandRoot() {
        TreeNode root = (TreeNode) treeSite.getModel().getRoot();
        if (root == null) {
            return;
        }
        final TreePath rootTreePath = new TreePath(root);
	    
		if (EventQueue.isDispatchThread()) {
		    getTreeSite().expandPath(rootTreePath);
		    return;
		}
		try {
			EventQueue.invokeLater(new Runnable() {
				@Override
				public void run() {
				    getTreeSite().expandPath(rootTreePath);
				}
			});
		} catch (Exception e) {
        	// ZAP: Log exceptions
        	log.warn(e.getMessage(), e);
		}
	}
	
	// ZAP: Added addSiteMapListenners
	public void addSiteMapListener(SiteMapListener listenner) {
		this.listeners.add(listenner);
	}

	public void removeSiteMapListener(SiteMapListener listener) {
		this.listeners.remove(listener);
	}
	
	public void showInSites (SiteNode node) {
		TreeNode[] path = node.getPath();
		TreePath tp = new TreePath(path);
		treeSite.setExpandsSelectedPaths(true);
		treeSite.setSelectionPath(tp);
		treeSite.scrollPathToVisible(tp);
	}

	public void contextChanged(Context c) {
		getTreeContext();
		SiteNode root = (SiteNode)this.contextTree.getRoot();
		for (int i=0; i < root.getChildCount(); i++) {
			SiteNode node = (SiteNode)root.getChildAt(i);
	    	Target target = (Target)node.getUserObject();
	    	if (c.getIndex() == target.getContext().getIndex()) {
	    		target.setContext(c);
	    		if (node.getNodeName().equals(c.getName())) {
	    			this.contextTree.nodeChanged(node);
	    		} else {
	    			this.reloadContextTree();
	    		}
	    		break;
	    	}
		}
	}
	
    protected class SitesCustomPopupMenu extends JPopupMenu {
        private static final long serialVersionUID = 1L;

        @Override
        public void show(Component invoker, int x, int y) {
    		// ZAP: Select site list item on right click / menu key
        	TreePath tp = treeSite.getPathForLocation( x, y );
        	if ( tp != null ) {
        		boolean select = true;
        		// Only select a new item if the current item is not
        		// already selected - this is to allow multiple items
        		// to be selected
    	    	if (treeSite.getSelectionPaths() != null) {
    	    		for (TreePath t : treeSite.getSelectionPaths()) {
    	    			if (t.equals(tp)) {
    	    				select = false;
    	    				break;
    	    			}
    	    		}
    	    	}
    	    	if (select) {
    	    		treeSite.getSelectionModel().setSelectionPath(tp);
    	    	}
        	}

            final int countSelectedNodes = treeSite.getSelectionCount();
            final List historyReferences = new ArrayList<>(countSelectedNodes);
            if (countSelectedNodes > 0) {
                for (TreePath path : treeSite.getSelectionPaths()) {
                    final SiteNode node = (SiteNode) path.getLastPathComponent();
                    final HistoryReference historyReference = node.getHistoryReference();
                    if (historyReference != null) {
                        historyReferences.add(historyReference);
                    }
                }
            }
            SelectableHistoryReferencesContainer messageContainer = new DefaultSelectableHistoryReferencesContainer(
                    treeSite.getName(),
                    treeSite,
                    Collections. emptyList(),
                    historyReferences);
    		View.getSingleton().getPopupMenu().show(messageContainer, x, y);
        }

    }

    protected class ContextsCustomPopupMenu extends JPopupMenu {
        private static final long serialVersionUID = 1L;

        @Override
        public void show(Component invoker, int x, int y) {
    		// Select context list item on right click
        	TreePath tp = treeContext.getPathForLocation(x, y);
        	if ( tp != null ) {
        		boolean select = true;
        		// Only select a new item if the current item is not
        		// already selected - this is to allow multiple items
        		// to be selected
    	    	if (treeContext.getSelectionPaths() != null) {
    	    		for (TreePath t : treeContext.getSelectionPaths()) {
    	    			if (t.equals(tp)) {
    	    				select = false;
    	    				break;
    	    			}
    	    		}
    	    	}
    	    	if (select) {
    	    		treeContext.getSelectionModel().setSelectionPath(tp);
    	    	}
        	}
    		View.getSingleton().getPopupMenu().show(treeContext, x, y);
        }
    	
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy