/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2010 psiinon@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.zaproxy.zap.extension.httpsessions;
import java.awt.CardLayout;
import java.awt.Event;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import org.jdesktop.swingx.JXTable;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.control.Control;
import org.parosproxy.paros.extension.AbstractPanel;
import org.parosproxy.paros.model.SiteNode;
import org.parosproxy.paros.view.View;
import org.zaproxy.zap.utils.DisplayUtils;
import org.zaproxy.zap.utils.SortedComboBoxModel;
import org.zaproxy.zap.view.ScanPanel;
/**
* The HttpSessionsPanel used as a display panel for the {@link ExtensionHttpSessions}, allowing the
* user to view and control the http sessions.
*/
public class HttpSessionsPanel extends AbstractPanel {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The Constant PANEL_NAME. */
public static final String PANEL_NAME = "httpsessions";
/** The extension. */
private ExtensionHttpSessions extension = null;
private JPanel panelCommand = null;
private JToolBar panelToolbar = null;
private JScrollPane jScrollPane = null;
private JComboBox<String> siteSelect = null;
private JButton newSessionButton = null;
private JXTable sessionsTable = null;
private JButton optionsButton = null;
/** The current site. */
private String currentSite = null;
/** The site model. */
private SortedComboBoxModel<String> siteModel = new SortedComboBoxModel<>();
/** The sessions model. */
private HttpSessionsTableModel sessionsModel = new HttpSessionsTableModel(null);
/**
* Instantiates a new http session panel.
*
* @param extensionHttpSession the extension http session
*/
public HttpSessionsPanel(ExtensionHttpSessions extensionHttpSession) {
super();
this.extension = extensionHttpSession;
initialize();
}
/**
* This method initializes this panel.
*/
private void initialize() {
this.setLayout(new CardLayout());
this.setSize(474, 251);
this.setName(Constant.messages.getString("httpsessions.panel.title"));
this.setIcon(new ImageIcon(HttpSessionsPanel.class.getResource("/resource/icon/16/session.png")));
this.setDefaultAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_H, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | Event.ALT_MASK | Event.SHIFT_MASK, false));
this.setMnemonic(Constant.messages.getChar("httpsessions.panel.mnemonic"));
this.add(getPanelCommand(), getPanelCommand().getName());
}
/**
* This method initializes the main panel.
*
* @return javax.swing.JPanel
*/
private javax.swing.JPanel getPanelCommand() {
if (panelCommand == null) {
panelCommand = new javax.swing.JPanel();
panelCommand.setLayout(new java.awt.GridBagLayout());
panelCommand.setName(Constant.messages.getString("httpsessions.panel.title"));
// Add the two components: toolbar and work pane
GridBagConstraints toolbarGridBag = new GridBagConstraints();
GridBagConstraints workPaneGridBag = new GridBagConstraints();
toolbarGridBag.gridx = 0;
toolbarGridBag.gridy = 0;
toolbarGridBag.weightx = 1.0d;
toolbarGridBag.insets = new java.awt.Insets(2, 2, 2, 2);
toolbarGridBag.anchor = java.awt.GridBagConstraints.NORTHWEST;
toolbarGridBag.fill = java.awt.GridBagConstraints.HORIZONTAL;
workPaneGridBag.gridx = 0;
workPaneGridBag.gridy = 1;
workPaneGridBag.weightx = 1.0;
workPaneGridBag.weighty = 1.0;
workPaneGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
workPaneGridBag.anchor = java.awt.GridBagConstraints.NORTHWEST;
workPaneGridBag.fill = java.awt.GridBagConstraints.BOTH;
panelCommand.add(this.getPanelToolbar(), toolbarGridBag);
panelCommand.add(getWorkPane(), workPaneGridBag);
}
return panelCommand;
}
/**
* Gets the options button.
*
* @return the options button
*/
private JButton getOptionsButton() {
if (optionsButton == null) {
optionsButton = new JButton();
optionsButton.setToolTipText(Constant.messages.getString("httpsessions.toolbar.options.button"));
optionsButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(ScanPanel.class.getResource("/resource/icon/16/041.png"))));
optionsButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Control.getSingleton().getMenuToolsControl()
.options(Constant.messages.getString("httpsessions.options.title"));
}
});
}
return optionsButton;
}
/**
* Gets the new session button.
*
* @return the new session button
*/
private JButton getNewSessionButton() {
if (newSessionButton == null) {
newSessionButton = new JButton();
newSessionButton.setText(Constant.messages.getString("httpsessions.toolbar.newsession.label"));
newSessionButton.setIcon(DisplayUtils.getScaledIcon(new ImageIcon(HttpSessionsPanel.class.getResource("/resource/icon/16/103.png"))));
newSessionButton.setToolTipText(Constant.messages.getString("httpsessions.toolbar.newsession.tooltip"));
newSessionButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HttpSessionsSite site = getCurrentHttpSessionSite();
if (site != null) {
site.createEmptySession();
}
}
});
}
return newSessionButton;
}
/**
* Gets the panel's toolbar.
*
* @return the panel toolbar
*/
private javax.swing.JToolBar getPanelToolbar() {
if (panelToolbar == null) {
// Initialize the toolbar
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("HttpSessionToolbar");
// Add elements
GridBagConstraints labelGridBag = new GridBagConstraints();
GridBagConstraints siteSelectGridBag = new GridBagConstraints();
GridBagConstraints newSessionGridBag = new GridBagConstraints();
GridBagConstraints emptyGridBag = new GridBagConstraints();
GridBagConstraints optionsGridBag = new GridBagConstraints();
labelGridBag.gridx = 0;
labelGridBag.gridy = 0;
labelGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
labelGridBag.anchor = java.awt.GridBagConstraints.WEST;
siteSelectGridBag.gridx = 1;
siteSelectGridBag.gridy = 0;
siteSelectGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
siteSelectGridBag.anchor = java.awt.GridBagConstraints.WEST;
newSessionGridBag.gridx = 2;
newSessionGridBag.gridy = 0;
newSessionGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
newSessionGridBag.anchor = java.awt.GridBagConstraints.WEST;
emptyGridBag.gridx = 3;
emptyGridBag.gridy = 0;
emptyGridBag.weightx = 1.0;
emptyGridBag.weighty = 1.0;
emptyGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
emptyGridBag.anchor = java.awt.GridBagConstraints.WEST;
emptyGridBag.fill = java.awt.GridBagConstraints.HORIZONTAL;
optionsGridBag.gridx = 4;
optionsGridBag.gridy = 0;
optionsGridBag.insets = new java.awt.Insets(0, 0, 0, 0);
optionsGridBag.anchor = java.awt.GridBagConstraints.EAST;
JLabel label = new JLabel(Constant.messages.getString("httpsessions.toolbar.site.label"));
panelToolbar.add(label, labelGridBag);
panelToolbar.add(getSiteSelect(), siteSelectGridBag);
panelToolbar.add(getNewSessionButton(), newSessionGridBag);
panelToolbar.add(getOptionsButton(), optionsGridBag);
// Add an empty JLabel to fill the space
panelToolbar.add(new JLabel(), emptyGridBag);
}
return panelToolbar;
}
/**
* Gets the work pane where data is shown.
*
* @return the work pane
*/
private JScrollPane getWorkPane() {
if (jScrollPane == null) {
jScrollPane = new JScrollPane();
jScrollPane.setViewportView(getHttpSessionsTable());
}
return jScrollPane;
}
/**
* Sets the sessions table column sizes.
*/
private void setSessionsTableColumnSizes() {
sessionsTable.getColumnModel().getColumn(0).setMinWidth(60);
sessionsTable.getColumnModel().getColumn(0).setPreferredWidth(60); // active
sessionsTable.getColumnModel().getColumn(1).setMinWidth(120);
sessionsTable.getColumnModel().getColumn(1).setPreferredWidth(200); // name
sessionsTable.getColumnModel().getColumn(3).setMinWidth(100);
sessionsTable.getColumnModel().getColumn(3).setPreferredWidth(150); // matched
}
/**
* Gets the http sessions table.
*
* @return the http sessions table
*/
private JXTable getHttpSessionsTable() {
if (sessionsTable == null) {
sessionsTable = new JXTable(sessionsModel);
sessionsTable.setColumnSelectionAllowed(false);
sessionsTable.setCellSelectionEnabled(false);
sessionsTable.setRowSelectionAllowed(true);
sessionsTable.setAutoCreateRowSorter(true);
sessionsTable.setColumnControlVisible(true);
this.setSessionsTableColumnSizes();
sessionsTable.setName(PANEL_NAME);
sessionsTable.setDoubleBuffered(true);
sessionsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
sessionsTable.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(java.awt.event.MouseEvent e) {
showPopupMenuIfTriggered(e);
}
@Override
public void mouseReleased(java.awt.event.MouseEvent e) {
showPopupMenuIfTriggered(e);
}
private void showPopupMenuIfTriggered(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) {
// Select table item
int row = sessionsTable.rowAtPoint(e.getPoint());
if (row < 0 || !sessionsTable.getSelectionModel().isSelectedIndex(row)) {
sessionsTable.getSelectionModel().clearSelection();
if (row >= 0) {
sessionsTable.getSelectionModel().setSelectionInterval(row, row);
}
}
View.getSingleton().getPopupMenu().show(e.getComponent(), e.getX(), e.getY());
}
}
});
}
return sessionsTable;
}
/**
* Gets the site select ComboBox.
*
* @return the site select
*/
private JComboBox<String> getSiteSelect() {
if (siteSelect == null) {
siteSelect = new JComboBox<>(siteModel);
siteSelect.addItem(Constant.messages.getString("httpsessions.toolbar.site.select"));
siteSelect.setSelectedIndex(0);
// Add the item listener for when the site is selected
siteSelect.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (ItemEvent.SELECTED == e.getStateChange()) {
if (siteSelect.getSelectedIndex() > 0) {
siteSelected((String) e.getItem());
} // If the user selects the first option (empty one), force the selection to
// the first valid site
else if (siteModel.getSize() > 1) {
siteModel.setSelectedItem(siteModel.getElementAt(1));
}
}
}
});
}
return siteSelect;
}
/**
* Adds a new site to the "Http Sessions" tab.
* <p>
* The method must be called in the EDT, failing to do so might result in thread interference or memory consistency errors.
* </p>
*
* @param site the site
* @see #addSiteAsynchronously(String)
* @see EventQueue
*/
public void addSite(String site) {
if (siteModel.getIndexOf(site) < 0) {
siteModel.addElement(site);
if (currentSite == null) {
// First site added, automatically select it
siteModel.setSelectedItem(site);
}
}
}
/**
* Adds a new site, asynchronously, to the "Http Sessions" tab.
* <p>
* The call to this method will return immediately and the site will be added in the EDT (by calling the method
* {@code EventQueue#invokeLater(Runnable)}) after all pending events have been processed.
* </p>
*
* @param site the site
* @see #addSite(String)
* @see EventQueue#invokeLater(Runnable)
*/
public void addSiteAsynchronously(final String site) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
addSite(site);
}
});
}
/**
* A new Site was selected.
*
* @param site the site
*/
private void siteSelected(String site) {
if (!site.equals(currentSite)) {
this.sessionsModel = extension.getHttpSessionsSite(site).getModel();
this.getHttpSessionsTable().setModel(this.sessionsModel);
this.setSessionsTableColumnSizes();
currentSite = site;
}
}
/**
* Node selected.
*
* @param node the node
*/
public void nodeSelected(SiteNode node) {
if (node != null) {
siteModel.setSelectedItem(ScanPanel.cleanSiteName(node, true));
}
}
/**
* Reset the panel.
*/
public void reset() {
currentSite = null;
siteModel.removeAllElements();
siteModel.addElement(Constant.messages.getString("httpsessions.toolbar.site.select"));
sessionsModel = new HttpSessionsTableModel(null);
getHttpSessionsTable().setModel(sessionsModel);
}
/**
* Gets the current http session site.
*
* @return the current http session site, or null if no HttpSessionSite is selected
*/
public HttpSessionsSite getCurrentHttpSessionSite() {
if (currentSite == null) {
return null;
}
return extension.getHttpSessionsSite(currentSite);
}
/**
* Gets the currently selected site.
*
* @return the current site
*/
public String getCurrentSite(){
return currentSite;
}
/**
* Gets the selected http session.
*
* @return the selected session, or null if nothing is selected
*/
public HttpSession getSelectedSession() {
final int selectedRow = this.sessionsTable.getSelectedRow();
if (selectedRow == -1) {
// No row selected
return null;
}
final int rowIndex = sessionsTable.convertRowIndexToModel(selectedRow);
return this.sessionsModel.getHttpSessionAt(rowIndex);
}
}