/* * 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.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 PopupMenuHttpMessageContainer} that exposes the {@code HistoryReference}s of {@code HttpMessageContainer}s. * * @since 2.3.0 * @see PopupMenuHttpMessageContainer * @see HttpMessageContainer * @see #isEnableForMessageContainer(MessageContainer) */ public class PopupMenuHistoryReferenceContainer extends PopupMenuHttpMessageContainer { private static final long serialVersionUID = 1L; /** * Constructs a {@code PopupMenuHistoryReferenceContainer} with the given label and with no support for multiple selected * messages (the menu button will not be enabled when the invoker has multiple selected messages). * * @param label the label of the menu * @see #setButtonStateOverriddenByChildren(boolean) * @see #setProcessExtensionPopupChildren(boolean) * @see #isEnableForMessageContainer(MessageContainer) */ public PopupMenuHistoryReferenceContainer(String label) { this(label, false); } /** * Constructs a {@code PopupMenuHistoryReferenceContainer} with the given label and whether or not the menu supports * multiple selected messages (if {@code false} the menu 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 #setButtonStateOverriddenByChildren(boolean) * @see #setProcessExtensionPopupChildren(boolean) * @see #isEnableForMessageContainer(MessageContainer) */ public PopupMenuHistoryReferenceContainer(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 httpMessageContainer 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 httpMessageContainer) { return isButtonEnabledForSelectedHistoryReferences(getSelectedHistoryReferences(httpMessageContainer)); } /** * 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 httpMessageContainer 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 httpMessageContainer) { final Session session = Model.getSingleton().getSession(); for (HistoryReference historyReference : getSelectedHistoryReferences(httpMessageContainer)) { if (!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; } }