/* * 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.brk; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Event; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.event.KeyEvent; import javax.swing.BorderFactory; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.KeyStroke; import org.apache.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.control.Control.Mode; import org.parosproxy.paros.extension.AbstractPanel; import org.parosproxy.paros.extension.option.OptionsParamView; import org.parosproxy.paros.model.Model; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; import org.zaproxy.zap.extension.httppanel.HttpPanel; import org.zaproxy.zap.extension.httppanel.HttpPanelRequest; import org.zaproxy.zap.extension.httppanel.HttpPanelResponse; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.tab.Tab; public class BreakPanel extends AbstractPanel implements Tab, BreakpointManagementInterface { private static final long serialVersionUID = 1L; private static final Logger LOGGER = Logger.getLogger(BreakPanel.class); private static final String REQUEST_PANEL = "request"; private static final String RESPONSE_PANEL = "response"; private HttpPanelRequest requestPanel; private HttpPanelResponse responsePanel; private ExtensionBreak extension; private JPanel panelContent; private BreakPanelToolbarFactory breakToolbarFactory; private BreakpointsParam breakpointsParams; private final JToggleButton toolBarReqButton; private final JToggleButton toolBarResButton; private final JToggleButton toolBarAllButton; private final JButton toolBarBtnStep; private final JButton toolBarBtnContinue; private final JButton toolBarBtnDrop; private final JButton toolBarBtnBreakPoint; private Message msg; private boolean isAlwaysOnTop = false; private boolean request; /** * The break buttons shown in the main panel of the Break tab. */ private final BreakButtonsUI mainBreakButtons; /** * The break buttons shown in the request panel of the Break tab. */ private final BreakButtonsUI requestBreakButtons; /** * The break buttons shown in the response panel of the Break tab. */ private final BreakButtonsUI responseBreakButtons; /** * The current location of the break buttons. * * @see #setButtonsLocation(int) */ private int currentButtonsLocation; /** * The current button mode. * * @see #setButtonMode(int) */ private int currentButtonMode; public BreakPanel(ExtensionBreak extension, BreakpointsParam breakpointsParams) { super(); this.extension = extension; this.breakpointsParams = breakpointsParams; this.setIcon(new ImageIcon(BreakPanel.class.getResource("/resource/icon/16/101grey.png"))); // 'grey X' icon this.setDefaultAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | Event.SHIFT_MASK, false)); this.setMnemonic(Constant.messages.getChar("brk.panel.mnemonic")); this.setLayout(new BorderLayout()); breakToolbarFactory = new BreakPanelToolbarFactory(breakpointsParams, this); panelContent = new JPanel(new CardLayout()); this.add(panelContent, BorderLayout.CENTER); requestPanel = new HttpPanelRequest(false, OptionsParamView.BASE_VIEW_KEY + ".break."); requestPanel.loadConfig(Model.getSingleton().getOptionsParam().getConfig()); responsePanel = new HttpPanelResponse(false, OptionsParamView.BASE_VIEW_KEY + ".break."); responsePanel.loadConfig(Model.getSingleton().getOptionsParam().getConfig()); panelContent.add(requestPanel, REQUEST_PANEL); panelContent.add(responsePanel, RESPONSE_PANEL); toolBarReqButton = breakToolbarFactory.getBtnBreakRequest(); View.getSingleton().addMainToolbarButton(toolBarReqButton); toolBarResButton = breakToolbarFactory.getBtnBreakResponse(); View.getSingleton().addMainToolbarButton(toolBarResButton); toolBarAllButton = breakToolbarFactory.getBtnBreakAll(); View.getSingleton().addMainToolbarButton(toolBarAllButton); toolBarBtnStep = breakToolbarFactory.getBtnStep(); View.getSingleton().addMainToolbarButton(toolBarBtnStep); toolBarBtnContinue = breakToolbarFactory.getBtnContinue(); View.getSingleton().addMainToolbarButton(toolBarBtnContinue); toolBarBtnDrop = breakToolbarFactory.getBtnDrop(); View.getSingleton().addMainToolbarButton(toolBarBtnDrop); toolBarBtnBreakPoint = breakToolbarFactory.getBtnBreakPoint(); View.getSingleton().addMainToolbarButton(toolBarBtnBreakPoint); mainBreakButtons = new BreakButtonsUI("mainBreakButtons", breakToolbarFactory); this.add(mainBreakButtons.getComponent(), BorderLayout.NORTH); requestBreakButtons = new BreakButtonsUI("requestBreakButtons", breakToolbarFactory); requestPanel.addOptions(requestBreakButtons.getComponent(), HttpPanel.OptionsLocation.AFTER_COMPONENTS); responseBreakButtons = new BreakButtonsUI("responseBreakButtons", breakToolbarFactory); responsePanel.addOptions(responseBreakButtons.getComponent(), HttpPanel.OptionsLocation.AFTER_COMPONENTS); currentButtonsLocation = -1; } /** * Sets the location of the break buttons. * <p> * If the location is already set and the main tool bar visibility is the same, no change is done. * * @param location the location to set */ void setButtonsLocation(int location) { if (currentButtonsLocation == location) { mainBreakButtons.setVisible(location == 0 && isMainToolBarHidden()); return; } currentButtonsLocation = location; switch (location) { case 0: requestBreakButtons.setVisible(false); responseBreakButtons.setVisible(false); setToolbarButtonsVisible(true); // If the user decided to disable the main toolbar, the break // buttons have to be force to be displayed in the break panel mainBreakButtons.setVisible(isMainToolBarHidden()); break; case 1: case 2: requestBreakButtons.setVisible(true); responseBreakButtons.setVisible(true); setToolbarButtonsVisible(location == 2); mainBreakButtons.setVisible(false); break; default: setToolbarButtonsVisible(true); } } /** * Tells whether or not the main tool bar is hidden. * * @return {@code true} if the main tool bar is hidden, {@code false} otherwise */ private boolean isMainToolBarHidden() { return !extension.getModel().getOptionsParam().getViewParam().isShowMainToolbar(); } @Override public boolean isBreakRequest() { return breakToolbarFactory.isBreakRequest(); } @Override public boolean isBreakResponse() { return breakToolbarFactory.isBreakResponse(); } @Override public boolean isBreakAll() { return breakToolbarFactory.isBreakAll(); } @Override public void breakpointHit () { breakToolbarFactory.breakpointHit(); } @Override public boolean isHoldMessage(Message aMessage) { return breakToolbarFactory.isHoldMessage(); } public boolean isHoldMessage() { return breakToolbarFactory.isHoldMessage(); } @Override public boolean isStepping() { return breakToolbarFactory.isStepping(); } @Override public boolean isToBeDropped() { return breakToolbarFactory.isToBeDropped(); } @Override public void breakpointDisplayed () { final Boolean alwaysOnTopOption = breakpointsParams.getAlwaysOnTop(); if (alwaysOnTopOption == null || alwaysOnTopOption.booleanValue()) { java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { View.getSingleton().getMainFrame().setAlwaysOnTop(true); View.getSingleton().getMainFrame().toFront(); setTabFocus(); isAlwaysOnTop = true; if (alwaysOnTopOption == null) { // Prompt the user the first time boolean keepOn = View.getSingleton().showConfirmDialog( Constant.messages.getString("brk.alwaysOnTop.message")) == JOptionPane.OK_OPTION; breakpointsParams.setAlwaysOnTop(Boolean.valueOf(keepOn)); if (! keepOn) { // Turn it off View.getSingleton().getMainFrame().setAlwaysOnTop(false); isAlwaysOnTop = false; } } } }); } try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { View.getSingleton().getMainFrame().toFront(); } }); } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } } private void setToolbarButtonsVisible(boolean visible) { boolean simple = currentButtonMode == BreakpointsParam.BUTTON_MODE_SIMPLE; toolBarReqButton.setVisible(visible && !simple); toolBarResButton.setVisible(visible && !simple); toolBarAllButton.setVisible(visible && simple); toolBarBtnStep.setVisible(visible); toolBarBtnContinue.setVisible(visible); toolBarBtnDrop.setVisible(visible); toolBarBtnBreakPoint.setVisible(visible); } @Override public void setMessage(final Message aMessage, final boolean isRequest) { try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { msg = aMessage; CardLayout cl = (CardLayout)(panelContent.getLayout()); request = isRequest; if (isRequest) { requestPanel.setMessage(aMessage, true); requestPanel.setEditable(true); cl.show(panelContent, REQUEST_PANEL); } else { responsePanel.setMessage(aMessage, true); responsePanel.setEditable(true); cl.show(panelContent, RESPONSE_PANEL); } } }); } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } } @Override public boolean isRequest() { return this.request; } @Override public Message getMessage() { return msg; } @Override public void saveMessage(final boolean isRequest) { try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { CardLayout cl = (CardLayout)(panelContent.getLayout()); if (isRequest) { requestPanel.saveData(); cl.show(panelContent, REQUEST_PANEL); } else { responsePanel.saveData(); cl.show(panelContent, RESPONSE_PANEL); } } }); } catch (Exception ie) { LOGGER.warn(ie.getMessage(), ie); } } public void savePanels() { requestPanel.saveConfig(Model.getSingleton().getOptionsParam().getConfig()); responsePanel.saveConfig(Model.getSingleton().getOptionsParam().getConfig()); } @Override public void clearAndDisableRequest() { if (EventQueue.isDispatchThread()) { clearAndDisableRequestEventHandler(); } else { try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { clearAndDisableRequestEventHandler(); } }); } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } } } private void clearAndDisableRequestEventHandler() { this.msg = null; requestPanel.clearView(false); requestPanel.setEditable(false); breakpointLeft(); } @Override public void clearAndDisableResponse() { if (EventQueue.isDispatchThread()) { clearAndDisableResponseEventHandler(); } else { try { EventQueue.invokeAndWait(new Runnable() { @Override public void run() { clearAndDisableResponseEventHandler(); } }); } catch (Exception e) { LOGGER.warn(e.getMessage(), e); } } } private void clearAndDisableResponseEventHandler() { this.msg = null; responsePanel.clearView(false); responsePanel.setEditable(false); breakpointLeft(); } private void breakpointLeft() { if (this.isAlwaysOnTop) { View.getSingleton().getMainFrame().setAlwaysOnTop(false); this.isAlwaysOnTop = false; } } @Override public void init() { breakToolbarFactory.init(); } @Override public void reset() { this.msg = null; breakToolbarFactory.reset(); } @Override public void sessionModeChanged(Mode mode) { if (mode.equals(Mode.safe)) { this.breakToolbarFactory.setBreakEnabled(false); } else { this.breakToolbarFactory.setBreakEnabled(true); } } @Override public void setBreakAllRequests(boolean brk) { breakToolbarFactory.setBreakRequest(brk); } @Override public void setBreakAllResponses(boolean brk) { breakToolbarFactory.setBreakResponse(brk); } @Override public void setBreakAll(boolean brk) { breakToolbarFactory.setBreakAll(brk); } @Override public void step() { breakToolbarFactory.setStep(true); } @Override public void cont() { breakToolbarFactory.setContinue(true); breakToolbarFactory.setBreakAll(false); breakToolbarFactory.setBreakRequest(false); breakToolbarFactory.setBreakResponse(false); } @Override public void drop() { breakToolbarFactory.setDrop(true); } public void showNewBreakPointDialog() { extension.addUiBreakpoint(new HttpMessage()); } public void setButtonMode (int mode) { if (currentButtonMode == mode) { return; } currentButtonMode = mode; this.breakToolbarFactory.setButtonMode(mode); if (currentButtonsLocation == 0 || currentButtonsLocation == 2) { boolean simple = mode == BreakpointsParam.BUTTON_MODE_SIMPLE; toolBarReqButton.setVisible(!simple); toolBarResButton.setVisible(!simple); toolBarAllButton.setVisible(simple); } mainBreakButtons.setButtonMode(mode); requestBreakButtons.setButtonMode(mode); responseBreakButtons.setButtonMode(mode); } /** * A wrapper of a view component with break related buttons/functionality. * * @see #getComponent() */ private static class BreakButtonsUI { private final JToolBar toolBar; private final JToggleButton requestButton; private final JToggleButton responseButton; private final JToggleButton allButton; public BreakButtonsUI(String name, BreakPanelToolbarFactory breakToolbarFactory) { requestButton = breakToolbarFactory.getBtnBreakRequest(); responseButton = breakToolbarFactory.getBtnBreakResponse(); allButton = breakToolbarFactory.getBtnBreakAll(); toolBar = new JToolBar(); toolBar.setFloatable(false); toolBar.setBorder(BorderFactory.createEmptyBorder()); toolBar.setRollover(true); toolBar.setName(name); toolBar.add(requestButton); toolBar.add(responseButton); toolBar.add(allButton); toolBar.add(breakToolbarFactory.getBtnStep()); toolBar.add(breakToolbarFactory.getBtnContinue()); toolBar.add(breakToolbarFactory.getBtnDrop()); toolBar.add(breakToolbarFactory.getBtnBreakPoint()); } /** * Sets whether or not the underlying view component is visible. * * @param visible {@code true} if the view component should be visible, {@code false} otherwise */ public void setVisible(boolean visible) { toolBar.setVisible(visible); } /** * Sets the current button mode. * * @param mode the mode to be set * @see BreakpointsParam#BUTTON_MODE_SIMPLE * @see BreakpointsParam#BUTTON_MODE_DUAL */ public void setButtonMode(int mode) { boolean simple = mode == BreakpointsParam.BUTTON_MODE_SIMPLE; requestButton.setVisible(!simple); responseButton.setVisible(!simple); allButton.setVisible(simple); } /** * Gets the underlying view component, with the break buttons. * * @return the view component */ public JComponent getComponent() { return toolBar; } } }