/* * 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/01/12 Changed the method valueChanged of the ListSelectionListener. // ZAP: 2012/03/15 Changed to allow clear the displayQueue. // ZAP: 2012/04/25 Added @Override annotation to all appropriate methods. // ZAP: 2012/04/28 Added logger and log of exception. // ZAP: 2012/05/02 Changed to use the class literal, instead of getting the // class at runtime, to get the resource. // ZAP: 2012/07/29 Issue 43: added Scope support // ZAP: 2013/02/26 Issue 538: Allow non sequential lines to be selected in the history log // ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments // ZAP: 2013/03/03 Issue 547: Deprecate unused classes and methods // ZAP: 2013/11/16 Issue 898: Replace all toggle buttons that set a tool tip text based on button's state with ZapToggleButton // ZAP: 2013/11/16 Issue 899: Remove "manual" update of toggle buttons' icon based on button's state // ZAP: 2013/11/16 Issue 886: Main pop up menu invoked twice on some components // ZAP: 2013/12/02 Issue 915: Dynamically filter history based on selection in the sites window // ZAP: 2014/01/28 Issue 207: Support keyboard shortcuts // ZAP: 2014/02/07 Issue 207: Give the most suitable component focus on tab switch // 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/03/23 Issue 503: Change the footer tabs to display the data // with tables instead of lists // ZAP: 2015/02/10 Issue 1528: Support user defined font size // ZAP: 2016/04/14 Use View to display the HTTP messages // ZAP: 2017/01/30 Use HistoryTable. // ZAP: 2017/03/03 Tweak filter label. package org.parosproxy.paros.extension.history; import java.awt.BorderLayout; import java.awt.Event; import java.awt.GridBagConstraints; import java.awt.Toolkit; import java.awt.event.KeyEvent; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JToggleButton; import javax.swing.JTree; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.TreePath; import org.apache.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.AbstractPanel; import org.parosproxy.paros.extension.ViewDelegate; import org.parosproxy.paros.model.HistoryReference; import org.parosproxy.paros.model.Model; import org.parosproxy.paros.model.SiteNode; import org.parosproxy.paros.view.View; import org.zaproxy.zap.extension.httppanel.HttpPanel; import org.zaproxy.zap.utils.DisplayUtils; import org.zaproxy.zap.view.DeselectableButtonGroup; import org.zaproxy.zap.view.ZapToggleButton; import org.zaproxy.zap.view.table.DefaultHistoryReferencesTableEntry; import org.zaproxy.zap.view.table.HistoryReferencesTable; import org.zaproxy.zap.view.table.HistoryReferencesTableModel; public class LogPanel extends AbstractPanel { private static final long serialVersionUID = 1L; // ZAP: Added logger. private static final Logger logger = Logger.getLogger(LogPanel.class); private javax.swing.JScrollPane scrollLog = null; private HistoryReferencesTable historyReferencesTable = null; // ZAP: Added history (filter) toolbar private javax.swing.JPanel historyPanel = null; private javax.swing.JToolBar panelToolbar = null; private JButton filterButton = null; private JLabel filterStatus = null; private ZapToggleButton scopeButton = null; private ExtensionHistory extension = null; private ZapToggleButton linkWithSitesTreeButton; private LinkWithSitesTreeSelectionListener linkWithSitesTreeSelectionListener; private DeselectableButtonGroup historyListFiltersButtonGroup; private final ViewDelegate view; /** * @deprecated (2.5.0) Use {@link #LogPanel(ViewDelegate)} instead. */ @Deprecated public LogPanel() { this(View.getSingleton()); } public LogPanel(ViewDelegate view) { super(); this.view = view; initialize(); } /** * This method initializes this */ private void initialize() { historyListFiltersButtonGroup = new DeselectableButtonGroup(); this.setLayout(new BorderLayout()); if (Model.getSingleton().getOptionsParam().getViewParam().getWmUiHandlingOption() == 0) { this.setSize(600, 200); } this.add(getHistoryPanel(), java.awt.BorderLayout.CENTER); this.setDefaultAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_H, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | Event.SHIFT_MASK, false)); this.setMnemonic(Constant.messages.getChar("history.panel.mnemonic")); } @Override public void tabSelected() { // Give the history list focus so that the user can immediatelly use the arrow keys to navigate getHistoryReferenceTable().requestFocusInWindow(); } void setExtension(ExtensionHistory extension) { this.extension = extension; } /** * This method initializes scrollLog * * @return javax.swing.JScrollPane */ private javax.swing.JScrollPane getScrollLog() { if (scrollLog == null) { scrollLog = new javax.swing.JScrollPane(); scrollLog.setViewportView(getHistoryReferenceTable()); scrollLog.setName("scrollLog"); } return scrollLog; } private javax.swing.JPanel getHistoryPanel() { if (historyPanel == null) { historyPanel = new javax.swing.JPanel(); historyPanel.setLayout(new java.awt.GridBagLayout()); historyPanel.setName("History Panel"); GridBagConstraints gridBagConstraints1 = new GridBagConstraints(); GridBagConstraints gridBagConstraints2 = new GridBagConstraints(); gridBagConstraints1.gridx = 0; gridBagConstraints1.gridy = 0; gridBagConstraints1.weightx = 1.0D; gridBagConstraints1.insets = new java.awt.Insets(2,2,2,2); gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; gridBagConstraints1.anchor = java.awt.GridBagConstraints.NORTHWEST; gridBagConstraints2.gridx = 0; gridBagConstraints2.gridy = 1; gridBagConstraints2.weightx = 1.0; gridBagConstraints2.weighty = 1.0; gridBagConstraints2.insets = new java.awt.Insets(0,0,0,0); gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints2.anchor = java.awt.GridBagConstraints.NORTHWEST; historyPanel.add(this.getPanelToolbar(), gridBagConstraints1); historyPanel.add(getScrollLog(), gridBagConstraints2); } return historyPanel; } private javax.swing.JToolBar getPanelToolbar() { if (panelToolbar == null) { panelToolbar = new javax.swing.JToolBar(); panelToolbar.setLayout(new java.awt.GridBagLayout()); panelToolbar.setEnabled(true); panelToolbar.setFloatable(false); panelToolbar.setRollover(true); panelToolbar.setPreferredSize(new java.awt.Dimension(800,30)); panelToolbar.setName("History Toolbar"); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.insets = new java.awt.Insets(0,0,0,0); gbc.anchor = java.awt.GridBagConstraints.WEST; panelToolbar.add(getScopeButton(), gbc); ++gbc.gridx; panelToolbar.add(getLinkWithSitesTreeButton(), gbc); ++gbc.gridx; panelToolbar.add(getFilterButton(), gbc); filterStatus = new JLabel(Constant.messages.getString("history.filter.label.filter") + " " + Constant.messages.getString("history.filter.label.off")); ++gbc.gridx; panelToolbar.add(filterStatus, gbc); ++gbc.gridx; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.anchor = java.awt.GridBagConstraints.EAST; gbc.fill = java.awt.GridBagConstraints.HORIZONTAL; panelToolbar.add(new JLabel(), gbc); } return panelToolbar; } private JButton getFilterButton() { if (filterButton == null) { filterButton = new JButton(); // ZAP: Changed to use the class literal. filterButton.setIcon(new ImageIcon(LogPanel.class.getResource("/resource/icon/16/054.png"))); // 'filter' icon filterButton.setToolTipText(Constant.messages.getString("history.filter.button.filter")); DisplayUtils.scaleIcon(filterButton); filterButton.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent e) { extension.showFilterPlusDialog(); } }); } return filterButton; } private JToggleButton getScopeButton() { if (scopeButton == null) { scopeButton = new ZapToggleButton(); scopeButton.setIcon(new ImageIcon(LogPanel.class.getResource("/resource/icon/fugue/target-grey.png"))); scopeButton.setToolTipText(Constant.messages.getString("history.scope.button.unselected")); scopeButton.setSelectedIcon(new ImageIcon(LogPanel.class.getResource("/resource/icon/fugue/target.png"))); scopeButton.setSelectedToolTipText(Constant.messages.getString("history.scope.button.selected")); DisplayUtils.scaleIcon(scopeButton); scopeButton.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent e) { extension.setShowJustInScope(scopeButton.isSelected()); } }); historyListFiltersButtonGroup.add(scopeButton); } return scopeButton; } private JToggleButton getLinkWithSitesTreeButton() { if (linkWithSitesTreeButton == null) { linkWithSitesTreeButton = new ZapToggleButton(); linkWithSitesTreeButton.setIcon(new ImageIcon(LogPanel.class.getResource("/resource/icon/16/earth-grey.png"))); linkWithSitesTreeButton.setToolTipText(Constant.messages.getString("history.linkWithSitesSelection.unselected.button.tooltip")); linkWithSitesTreeButton.setSelectedIcon(new ImageIcon(LogPanel.class.getResource("/resource/icon/16/094.png"))); linkWithSitesTreeButton.setSelectedToolTipText(Constant.messages.getString("history.linkWithSitesSelection.selected.button.tooltip")); DisplayUtils.scaleIcon(linkWithSitesTreeButton); linkWithSitesTreeButton.addActionListener(new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent e) { setLinkWithSitesTreeSelection(linkWithSitesTreeButton.isSelected()); } }); historyListFiltersButtonGroup.add(linkWithSitesTreeButton); } return linkWithSitesTreeButton; } public void setLinkWithSitesTreeSelection(boolean enabled) { linkWithSitesTreeButton.setSelected(enabled); final JTree sitesTree = view.getSiteTreePanel().getTreeSite(); String baseUri = null; if (enabled) { final TreePath selectionPath = sitesTree.getSelectionPath(); if (selectionPath != null) { baseUri = getLinkWithSitesTreeBaseUri((SiteNode) selectionPath.getLastPathComponent()); } sitesTree.addTreeSelectionListener(getLinkWithSitesTreeSelectionListener()); } else { sitesTree.removeTreeSelectionListener(getLinkWithSitesTreeSelectionListener()); } extension.setLinkWithSitesTree(enabled, baseUri); } private static String getLinkWithSitesTreeBaseUri(SiteNode siteNode) { if (!siteNode.isRoot()) { HistoryReference historyReference = siteNode.getHistoryReference(); if (historyReference != null) { return historyReference.getURI().toString(); } } return null; } private HistoryReferencesTable getHistoryReferenceTable() { if (historyReferencesTable == null) { historyReferencesTable = new HistoryTable(); historyReferencesTable.addMouseListener(new java.awt.event.MouseAdapter() { @Override public void mouseClicked(java.awt.event.MouseEvent e) { if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) { // double click view.getRequestPanel().setTabFocus(); return; } } }); } return historyReferencesTable; } protected void display(final HistoryReference historyRef) { getHistoryReferenceTable().selectHistoryReference(historyRef.getHistoryId()); } /** * @deprecated (2.6.0) No longer used/needed. */ @Deprecated public void clearDisplayQueue() { } /** * @deprecated (2.5.0) No longer used/needed. */ @Deprecated @SuppressWarnings("javadoc") public void setDisplayPanel(HttpPanel requestPanel, HttpPanel responsePanel) { } public void setFilterStatus (HistoryFilter filter) { filterStatus.setText(filter.toShortString()); filterStatus.setToolTipText(filter.toLongString()); } private LinkWithSitesTreeSelectionListener getLinkWithSitesTreeSelectionListener() { if (linkWithSitesTreeSelectionListener == null) { linkWithSitesTreeSelectionListener = new LinkWithSitesTreeSelectionListener(); } return linkWithSitesTreeSelectionListener; } private class LinkWithSitesTreeSelectionListener implements TreeSelectionListener { @Override public void valueChanged(TreeSelectionEvent e) { extension.updateLinkWithSitesTreeBaseUri(getLinkWithSitesTreeBaseUri((SiteNode) e.getPath().getLastPathComponent())); } } public HistoryReference getSelectedHistoryReference() { return getHistoryReferenceTable().getSelectedHistoryReference(); } public List<HistoryReference> getSelectedHistoryReferences() { return getHistoryReferenceTable().getSelectedHistoryReferences(); } public void setModel(HistoryReferencesTableModel<DefaultHistoryReferencesTableEntry> historyTableModel) { getHistoryReferenceTable().setModel(historyTableModel); } }