/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2014 The ZAP Development Team * * 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.view.popup; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.parosproxy.paros.model.HistoryReference; import org.parosproxy.paros.model.Model; import org.parosproxy.paros.model.Session; import org.parosproxy.paros.network.HttpMessage; import org.zaproxy.zap.view.messagecontainer.MessageContainer; import org.zaproxy.zap.view.messagecontainer.http.HttpMessageContainer; import org.zaproxy.zap.view.messagecontainer.http.SelectableHistoryReferencesContainer; import org.zaproxy.zap.view.messagecontainer.http.SingleHistoryReferenceContainer; /** * A {@code PopupMenuItemHttpMessageContainer} that exposes the {@code HistoryReference}s of {@code HttpMessageContainer}s. * * @since 2.3.0 * @see PopupMenuItemHttpMessageContainer * @see HttpMessageContainer * @see #isEnableForMessageContainer(MessageContainer) */ public abstract class PopupMenuItemHistoryReferenceContainer extends PopupMenuItemHttpMessageContainer { private static final long serialVersionUID = -7860130362424758504L; /** * Constructs a {@code PopupMenuItemHistoryReferenceContainer} with the given label and with no support for multiple * selected messages (the menu item button will not be enabled when the invoker has multiple selected messages). * * @param label the label of the menu * @see #isEnableForMessageContainer(MessageContainer) */ public PopupMenuItemHistoryReferenceContainer(String label) { this(label, false); } /** * Constructs a {@code PopupMenuItemHistoryReferenceContainer} with the given label and whether or not the menu item * supports multiple selected messages (if {@code false} the menu item button will not be enabled when the invoker has * multiple selected messages). * * @param label the label of the menu * @param multiSelect {@code true} if the menu supports multiple selected messages, {@code false} otherwise. * @see #isEnableForMessageContainer(MessageContainer) */ public PopupMenuItemHistoryReferenceContainer(String label, boolean multiSelect) { super(label, multiSelect); } /** * Tells whether or not the menu is enable for the given HTTP message container. * <p> * By default is enable for {@code SingleHistoryReferenceContainer}s and {@code SelectableHistoryReferencesContainer}s. * </p> * <p> * Normally overridden if other implementations of {@code HttpMessageContainer} are supported. The methods * {@code getSelectedMessages(HttpMessageContainer)}, {@code getSelectedHistoryReferences(HttpMessageContainer)} and * {@code getNumberOfSelectedMessages(HttpMessageContainer)} might need to be overridden accordingly to the supported * implementations. * </p> * * @param httpMessageContainer the message container that will be evaluated * @return {@code true} if the given message container is a {@code SingleHistoryReferenceContainer} or * {@code SelectableHistoryReferencesContainer}. * @see #getSelectedMessages(HttpMessageContainer) * @see #getSelectedHistoryReferences(HttpMessageContainer) * @see #getNumberOfSelectedMessages(HttpMessageContainer) * @see SingleHistoryReferenceContainer * @see SelectableHistoryReferencesContainer */ @Override protected boolean isEnable(HttpMessageContainer httpMessageContainer) { if (httpMessageContainer instanceof SelectableHistoryReferencesContainer || httpMessageContainer instanceof SingleHistoryReferenceContainer) { return true; } return false; } /** * Tells whether or not the button should be enabled for the selected messages of the given message container. * <p> * Defaults to call the method {@code isButtonEnabledForSelectedHistoryReferences(List)} with the selected messages obtained * by calling the method {@code getSelectedHistoryReferences(HttpMessageContainer)}, with the given message container as * parameter. * </p> * <p> * Normally overridden if other implementations of {@code HttpMessageContainer} are supported. * </p> * * @param messageContainer the container that will be evaluated * @return {@code true} if the button should be enabled for the selected messages, {@code false} otherwise. * @see #isButtonEnabledForSelectedHistoryReferences(List) * @see #getSelectedHistoryReferences(HttpMessageContainer) */ @Override protected boolean isButtonEnabledForSelectedMessages(HttpMessageContainer messageContainer) { return isButtonEnabledForSelectedHistoryReferences(getSelectedHistoryReferences(messageContainer)); } /** * Tells whether or not the selected messages of the given message container are in scope. * <p> * By default, the selected messages are obtained by calling the method getSelectedHistoryReferences(httpMessageContainer) * with the given message container as parameter and for each selected message is called the method * {@code Session#isInScope(HistoryReference)} with the message as parameter. * </p> * <p> * Normally overridden if other implementations of {@code HttpMessageContainer} are supported. Default are * {@code SingleHistoryReferenceContainer} and {@code SelectableHistoryReferencesContainer}. * </p> * * @param messageContainer the container that will be evaluated * @return {@code true} if all the selected messages are in scope, {@code false} otherwise. * @see #isEnableForMessageContainer(MessageContainer) * @see Session#isInScope(HistoryReference) */ @Override protected boolean isSelectedMessagesInSessionScope(HttpMessageContainer messageContainer) { final Session session = Model.getSingleton().getSession(); for (HistoryReference historyReference : getSelectedHistoryReferences(messageContainer)) { if (historyReference != null && !session.isInScope(historyReference)) { return false; } } return true; } /** * Returns the selected messages of the given message container. * <p> * By default it returns the selected messages from {@code SelectableHistoryReferencesContainer}s and for * {@code SingleHistoryReferenceContainer}s returns the contained message or empty {@code List} if none. * </p> * <p> * Normally overridden if other implementations of {@code HttpMessageContainer} are supported. Default are * {@code SingleHistoryReferenceContainer} and {@code SelectableHistoryReferencesContainer}. * </p> * * @param httpMessageContainer the container that will be evaluated * @return a {@code List} containing the selected messages * @see #isButtonEnabledForSelectedMessages(List) * @see #isSelectedMessagesInSessionScope(HttpMessageContainer) * @see SingleHistoryReferenceContainer * @see SelectableHistoryReferencesContainer */ protected List<HistoryReference> getSelectedHistoryReferences(HttpMessageContainer httpMessageContainer) { if (httpMessageContainer instanceof SelectableHistoryReferencesContainer) { return ((SelectableHistoryReferencesContainer) httpMessageContainer).getSelectedHistoryReferences(); } else if (httpMessageContainer instanceof SingleHistoryReferenceContainer) { SingleHistoryReferenceContainer singleContainer = (SingleHistoryReferenceContainer) httpMessageContainer; if (!singleContainer.isEmpty()) { List<HistoryReference> selectedHistoryReferences = new ArrayList<>(1); selectedHistoryReferences.add(singleContainer.getHistoryReference()); return selectedHistoryReferences; } } return Collections.emptyList(); } /** * Tells whether or not the button should be enabled for the given selected messages. * <p> * By default, it returns {@code true} unless the method {@code isButtonEnabledForHistoryReference(HistoryReference)} * returns false for one of the selected messages. * </p> * * @param historyReferences the selected messages in the message container * @return {@code true} if the button should be enabled for the given selected messages, {@code false} otherwise. * @see #isButtonEnabledForHistoryReference(HistoryReference) */ protected boolean isButtonEnabledForSelectedHistoryReferences(List<HistoryReference> historyReferences) { for (HistoryReference historyReference : historyReferences) { if (historyReference != null && !isButtonEnabledForHistoryReference(historyReference)) { return false; } } return true; } /** * Tells whether or not the button should be enabled for the given selected message. * <p> * By default, it returns {@code true} if it is not a temporary message. * * @param historyReference the selected message, never {@code null} * @return {@code true} if the button should be enabled for the given selected message, {@code false} otherwise. * @see HistoryReference#TYPE_TEMPORARY */ protected boolean isButtonEnabledForHistoryReference(HistoryReference historyReference) { return historyReference.getHistoryType() != HistoryReference.TYPE_TEMPORARY; } /** * Performs the actions on the the given message container. * <p> * Calls the method {@code performHistoryReferenceActions(List)} with the selected messages obtained by calling the method * {@code getSelectedHistoryReferences(HttpMessageContainer)}, with the given message container as parameter. * </p> * * @param httpMessageContainer the container with the selected messages * @see #performHistoryReferenceActions(List) * @see #getSelectedHistoryReferences(HttpMessageContainer) */ @Override protected final void performActions(HttpMessageContainer httpMessageContainer) { performHistoryReferenceActions(getSelectedHistoryReferences(httpMessageContainer)); } /** * Does nothing. Never called. * * @see #performHistoryReferenceActions(List) */ @Override protected final void performActions(List<HttpMessage> httpMessages) { } /** * Does nothing. Never called. * * @see #performAction(HistoryReference) */ @Override protected final void performAction(HttpMessage httpMessage) { } /** * Performs the actions on all the the given messages. * <p> * Defaults to call the method {@code performAction(HistoryReference)} for each message (with the history references as * parameter). * </p> * <p> * Normally overridden if other implementations of {@code HttpMessageContainer} are supported (or not the desired * behaviour). * </p> * * @param historyReferences the history references that will be used to perform the actions * @see #performAction(HistoryReference) */ protected void performHistoryReferenceActions(List<HistoryReference> historyReferences) { for (HistoryReference historyReference : historyReferences) { if (historyReference != null) { this.performAction(historyReference); } } } /** * Performs an action on the given history reference. * * @param historyReference the history reference, never {@code null} */ protected abstract void performAction(HistoryReference historyReference); }