From 5bd41a1adb10b95d63745ee80b71c36594df6fab Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sat, 13 Jan 2024 16:28:07 +0530 Subject: [PATCH 01/24] initiated migration Signed-off-by: aryangupta701 --- addOns/brk/CHANGELOG.md | 6 + addOns/brk/brk.gradle.kts | 40 + addOns/brk/gradle.properties | 2 + .../addon/brk/AbstractBreakPointMessage.java | 35 + .../java/org/zaproxy/addon/brk/BreakAPI.java | 353 +++++++ .../addon/brk/BreakEventPublisher.java | 87 ++ .../org/zaproxy/addon/brk/BreakPanel.java | 763 +++++++++++++++ .../addon/brk/BreakPanelToolbarFactory.java | 871 ++++++++++++++++++ .../brk/BreakpointManagementInterface.java | 72 ++ .../addon/brk/BreakpointMessageHandler2.java | 239 +++++ .../addon/brk/BreakpointMessageInterface.java | 35 + .../addon/brk/BreakpointsOptionsPanel.java | 245 +++++ .../zaproxy/addon/brk/BreakpointsPanel.java | 355 +++++++ .../zaproxy/addon/brk/BreakpointsParam.java | 182 ++++ .../addon/brk/BreakpointsTableModel.java | 203 ++++ .../brk/BreakpointsUiManagerInterface.java | 39 + .../org/zaproxy/addon/brk/ExtensionBreak.java | 678 ++++++++++++++ .../zaproxy/addon/brk/PopupMenuEditBreak.java | 56 ++ .../zaproxy/addon/brk/PopupMenuRemove.java | 57 ++ .../brk/impl/http/BreakAddEditDialog.java | 166 ++++ .../HttpBreakpointManagementDaemonImpl.java | 219 +++++ .../brk/impl/http/HttpBreakpointMessage.java | 252 +++++ .../HttpBreakpointsUiManagerInterface.java | 162 ++++ .../impl/http/PopupMenuAddBreakHistory.java | 63 ++ .../brk/impl/http/PopupMenuAddBreakSites.java | 55 ++ .../brk/impl/http/ProxyListenerBreak.java | 99 ++ .../BreakpointMessageHandler2UnitTest.java | 259 ++++++ ...reakpointManagementDaemonImplUnitTest.java | 149 +++ .../addon/network/ExtensionNetwork.java | 2 +- .../plugnhack/ExtensionPlugNHack.java | 2 +- .../brk/ClientBreakpointMessage.java | 2 +- .../brk/ClientBreakpointMessageHandler.java | 4 +- .../ClientBreakpointsUiManagerInterface.java | 6 +- .../brk/PopupMenuAddBreakClient.java | 2 +- .../plugnhack/brk/PopupMenuEditBreak.java | 4 +- .../websocket/ExtensionWebSocket.java | 4 +- .../zap/extension/websocket/WebSocketAPI.java | 2 +- .../brk/PopupMenuAddBreakWebSocket.java | 2 +- .../websocket/brk/PopupMenuEditBreak.java | 4 +- .../brk/WebSocketBreakpointMessage.java | 2 +- .../WebSocketBreakpointMessageHandler.java | 4 +- ...ebSocketBreakpointsUiManagerInterface.java | 6 +- .../brk/WebSocketProxyListenerBreak.java | 2 +- 43 files changed, 5766 insertions(+), 24 deletions(-) create mode 100644 addOns/brk/CHANGELOG.md create mode 100644 addOns/brk/brk.gradle.kts create mode 100644 addOns/brk/gradle.properties create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/AbstractBreakPointMessage.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakAPI.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakEventPublisher.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanel.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanelToolbarFactory.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointManagementInterface.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageHandler2.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageInterface.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsOptionsPanel.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsPanel.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsParam.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsTableModel.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsUiManagerInterface.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuEditBreak.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuRemove.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/BreakAddEditDialog.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImpl.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointMessage.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointsUiManagerInterface.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakHistory.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakSites.java create mode 100644 addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/ProxyListenerBreak.java create mode 100644 addOns/brk/src/test/java/org/zaproxy/addon/brk/BreakpointMessageHandler2UnitTest.java create mode 100644 addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java diff --git a/addOns/brk/CHANGELOG.md b/addOns/brk/CHANGELOG.md new file mode 100644 index 00000000000..a1d458d43a6 --- /dev/null +++ b/addOns/brk/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog +All notable changes to this add-on will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## Unreleased \ No newline at end of file diff --git a/addOns/brk/brk.gradle.kts b/addOns/brk/brk.gradle.kts new file mode 100644 index 00000000000..e9fa30e268d --- /dev/null +++ b/addOns/brk/brk.gradle.kts @@ -0,0 +1,40 @@ +description = "Exposes client (browser) side information in ZAP using Firefox and Chrome extensions." + +zapAddOn { + addOnName.set("Break") + + manifest { + author.set("ZAP Dev Team") + url.set("https://www.zaproxy.org/docs/desktop/addons/brk/") + extensions { + + } + dependencies { + addOns { + register("selenium") { + version.set(">=15.14.0") + } + register("network") { + version.set(">=0.8.0") + } + register("commonlib") + } + } + } +} + +crowdin { + configuration { + val resourcesPath = "org/zaproxy/addon/${zapAddOn.addOnId.get()}/resources/" + tokens.put("%messagesPath%", resourcesPath) + tokens.put("%helpPath%", resourcesPath) + } +} + +dependencies { + zapAddOn("commonlib") + zapAddOn("selenium") + zapAddOn("network") + + testImplementation(project(":testutils")) +} diff --git a/addOns/brk/gradle.properties b/addOns/brk/gradle.properties new file mode 100644 index 00000000000..2a0ce7fc7a6 --- /dev/null +++ b/addOns/brk/gradle.properties @@ -0,0 +1,2 @@ +version=0.8.0 +release=false diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/AbstractBreakPointMessage.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/AbstractBreakPointMessage.java new file mode 100644 index 00000000000..2ba8da5d7a9 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/AbstractBreakPointMessage.java @@ -0,0 +1,35 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk; + +public abstract class AbstractBreakPointMessage implements BreakpointMessageInterface { + + private boolean isEnabled = true; + + @Override + public void setEnabled(boolean enabled) { + this.isEnabled = enabled; + } + + @Override + public boolean isEnabled() { + return isEnabled; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakAPI.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakAPI.java new file mode 100644 index 00000000000..2e0b73fd600 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakAPI.java @@ -0,0 +1,353 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2013 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.addon.brk; + +import java.io.IOException; +import net.sf.json.JSONObject; +import org.parosproxy.paros.network.HttpHeader; +import org.parosproxy.paros.network.HttpInputStream; +import org.parosproxy.paros.network.HttpMalformedHeaderException; +import org.parosproxy.paros.network.HttpMessage; +import org.parosproxy.paros.network.HttpOutputStream; +import org.zaproxy.zap.extension.api.API; +import org.zaproxy.zap.extension.api.ApiAction; +import org.zaproxy.zap.extension.api.ApiException; +import org.zaproxy.zap.extension.api.ApiImplementor; +import org.zaproxy.zap.extension.api.ApiPersistentConnection; +import org.zaproxy.zap.extension.api.ApiResponse; +import org.zaproxy.zap.extension.api.ApiResponseElement; +import org.zaproxy.zap.extension.api.ApiView; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.utils.ApiUtils; + +public class BreakAPI extends ApiImplementor { + + private static final String PREFIX = "break"; + + private static final String ACTION_BREAK = "break"; + private static final String ACTION_BREAK_ON_ID = "breakOnId"; + private static final String ACTION_ADD_HTTP_BREAK_POINT = "addHttpBreakpoint"; + private static final String ACTION_REM_HTTP_BREAK_POINT = "removeHttpBreakpoint"; + private static final String ACTION_CONTINUE = "continue"; + private static final String ACTION_STEP = "step"; + private static final String ACTION_DROP = "drop"; + private static final String ACTION_SET_HTTP_MESSAGE = "setHttpMessage"; + + private static final String VIEW_IS_BREAK_ALL = "isBreakAll"; + private static final String VIEW_IS_BREAK_REQUEST = "isBreakRequest"; + private static final String VIEW_IS_BREAK_RESPONSE = "isBreakResponse"; + private static final String VIEW_HTTP_MESSAGE = "httpMessage"; + + private static final String PCONN_WAIT_FOR_HTTP_BREAK = "waitForHttpBreak"; + + private static final String PARAM_STRING = "string"; + private static final String PARAM_LOCATION = "location"; + private static final String PARAM_MATCH = "match"; + private static final String PARAM_INVERSE = "inverse"; + private static final String PARAM_IGNORECASE = "ignorecase"; + private static final String PARAM_KEY = "key"; + private static final String PARAM_SCOPE = "scope"; + private static final String PARAM_STATE = "state"; + private static final String PARAM_TYPE = "type"; + private static final String PARAM_HTTP_HEADER = "httpHeader"; + private static final String PARAM_HTTP_BODY = "httpBody"; + private static final String PARAM_POLL = "poll"; + private static final String PARAM_KEEP_ALIVE = "keepalive"; + + private static final String VALUE_TYPE_HTTP_ALL = "http-all"; + private static final String VALUE_TYPE_HTTP_REQUESTS = "http-requests"; + private static final String VALUE_TYPE_HTTP_RESPONSES = "http-responses"; + + private ExtensionBreak extension = null; + + public BreakAPI(ExtensionBreak ext) { + extension = ext; + + this.addApiView(new ApiView(VIEW_IS_BREAK_ALL)); + this.addApiView(new ApiView(VIEW_IS_BREAK_REQUEST)); + this.addApiView(new ApiView(VIEW_IS_BREAK_RESPONSE)); + this.addApiView(new ApiView(VIEW_HTTP_MESSAGE)); + + this.addApiAction( + new ApiAction( + ACTION_BREAK, + new String[] {PARAM_TYPE, PARAM_STATE}, + new String[] { + PARAM_SCOPE + })); // Not currently used but kept for compatibility purposes + this.addApiAction( + new ApiAction( + ACTION_SET_HTTP_MESSAGE, + new String[] {PARAM_HTTP_HEADER}, + new String[] {PARAM_HTTP_BODY})); + this.addApiAction(new ApiAction(ACTION_CONTINUE)); + this.addApiAction(new ApiAction(ACTION_STEP)); + this.addApiAction(new ApiAction(ACTION_DROP)); + this.addApiAction( + new ApiAction( + ACTION_ADD_HTTP_BREAK_POINT, + new String[] { + PARAM_STRING, + PARAM_LOCATION, + PARAM_MATCH, + PARAM_INVERSE, + PARAM_IGNORECASE + })); + this.addApiAction( + new ApiAction( + ACTION_REM_HTTP_BREAK_POINT, + new String[] { + PARAM_STRING, + PARAM_LOCATION, + PARAM_MATCH, + PARAM_INVERSE, + PARAM_IGNORECASE + })); + + this.addApiPersistentConnection( + new ApiPersistentConnection( + PCONN_WAIT_FOR_HTTP_BREAK, + new String[] {}, + new String[] {PARAM_POLL, PARAM_KEEP_ALIVE})); + } + + @Override + public String getPrefix() { + return PREFIX; + } + + @Override + public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { + if (ACTION_BREAK.equals(name)) { + String type = params.getString(PARAM_TYPE).toLowerCase(); + boolean state = ApiUtils.getBooleanParam(params, PARAM_STATE); + if (type.equals(VALUE_TYPE_HTTP_ALL)) { + extension.setBreakAllRequests(state); + extension.setBreakAllResponses(state); + } else if (type.equals(VALUE_TYPE_HTTP_REQUESTS)) { + extension.setBreakAllRequests(state); + } else if (type.equals(VALUE_TYPE_HTTP_RESPONSES)) { + extension.setBreakAllResponses(state); + } else { + throw new ApiException( + ApiException.Type.ILLEGAL_PARAMETER, + PARAM_TYPE + + " not in [" + + VALUE_TYPE_HTTP_ALL + + "," + + VALUE_TYPE_HTTP_REQUESTS + + "," + + VALUE_TYPE_HTTP_RESPONSES + + "]"); + } + + } else if (ACTION_BREAK_ON_ID.equals(name)) { + extension.setBreakOnId( + params.getString(PARAM_KEY), + params.getString(PARAM_STATE).equalsIgnoreCase("on")); + + } else if (ACTION_CONTINUE.equals(name)) { + extension.getBreakpointManagementInterface().cont(); + + } else if (ACTION_STEP.equals(name)) { + extension.getBreakpointManagementInterface().step(); + + } else if (ACTION_DROP.equals(name)) { + extension.getBreakpointManagementInterface().drop(); + + } else if (ACTION_SET_HTTP_MESSAGE.equals(name)) { + if (extension.getBreakpointManagementInterface().getMessage() == null) { + // We've not got an intercepted message + throw new ApiException(ApiException.Type.DOES_NOT_EXIST); + } + + String header = params.getString(PARAM_HTTP_HEADER); + String body = this.getParam(params, PARAM_HTTP_BODY, ""); + + if (header.indexOf(HttpHeader.CRLF) < 0) { + if (header.indexOf("\\n") >= 0) { + // Makes it easier to use via API UI + header = header.replace("\\r", "\r").replace("\\n", "\n"); + } + } + + Message msg = extension.getBreakpointManagementInterface().getMessage(); + + if (msg instanceof HttpMessage) { + HttpMessage httpMsg = (HttpMessage) msg; + if (extension.getBreakpointManagementInterface().isRequest()) { + + try { + httpMsg.setRequestHeader(header); + httpMsg.setRequestBody(body); + extension.getBreakpointManagementInterface().setMessage(httpMsg, true); + + } catch (HttpMalformedHeaderException e) { + throw new ApiException(ApiException.Type.ILLEGAL_PARAMETER, e.getMessage()); + } + } else { + try { + httpMsg.setResponseHeader(header); + httpMsg.setResponseBody(body); + extension.getBreakpointManagementInterface().setMessage(httpMsg, false); + + } catch (HttpMalformedHeaderException e) { + throw new ApiException(ApiException.Type.ILLEGAL_PARAMETER, e.getMessage()); + } + } + } + + } else if (ACTION_ADD_HTTP_BREAK_POINT.equals(name)) { + try { + extension.addHttpBreakpoint( + params.getString(PARAM_STRING), + params.getString(PARAM_LOCATION), + params.getString(PARAM_MATCH), + ApiUtils.getBooleanParam(params, PARAM_INVERSE), + ApiUtils.getBooleanParam(params, PARAM_IGNORECASE)); + } catch (IllegalArgumentException e) { + throw new ApiException(ApiException.Type.ILLEGAL_PARAMETER, e.getMessage()); + } + + } else if (ACTION_REM_HTTP_BREAK_POINT.equals(name)) { + try { + extension.removeHttpBreakpoint( + params.getString(PARAM_STRING), + params.getString(PARAM_LOCATION), + params.getString(PARAM_MATCH), + ApiUtils.getBooleanParam(params, PARAM_INVERSE), + ApiUtils.getBooleanParam(params, PARAM_IGNORECASE)); + } catch (IllegalArgumentException e) { + throw new ApiException(ApiException.Type.ILLEGAL_PARAMETER, e.getMessage()); + } + + } else { + throw new ApiException(ApiException.Type.BAD_ACTION); + } + return ApiResponseElement.OK; + } + + @Override + public ApiResponse handleApiView(String name, JSONObject params) throws ApiException { + if (VIEW_IS_BREAK_ALL.equals(name)) { + return new ApiResponseElement( + name, + Boolean.toString(extension.getBreakpointManagementInterface().isBreakAll())); + } else if (VIEW_IS_BREAK_REQUEST.equals(name)) { + return new ApiResponseElement( + name, + Boolean.toString( + extension.getBreakpointManagementInterface().isBreakRequest())); + } else if (VIEW_IS_BREAK_RESPONSE.equals(name)) { + return new ApiResponseElement( + name, + Boolean.toString( + extension.getBreakpointManagementInterface().isBreakResponse())); + } else if (VIEW_HTTP_MESSAGE.equals(name)) { + Message msg = extension.getBreakpointManagementInterface().getMessage(); + if (msg == null) { + return new ApiResponseElement(name, ""); + } else if (msg instanceof HttpMessage) { + HttpMessage httpMsg = (HttpMessage) msg; + StringBuilder sb = new StringBuilder(); + if (extension.getBreakpointManagementInterface().isRequest()) { + sb.append(httpMsg.getRequestHeader().toString()); + sb.append(httpMsg.getRequestBody().toString()); + } else { + sb.append(httpMsg.getResponseHeader().toString()); + sb.append(httpMsg.getResponseBody().toString()); + } + return new ApiResponseElement(name, sb.toString()); + } + throw new ApiException(ApiException.Type.BAD_TYPE); + } else { + throw new ApiException(ApiException.Type.BAD_VIEW); + } + } + + @Override + public void handleApiPersistentConnection( + HttpMessage msg, + HttpInputStream httpIn, + HttpOutputStream httpOut, + String name, + JSONObject params) + throws ApiException { + if (PCONN_WAIT_FOR_HTTP_BREAK.equals(name)) { + int poll = params.optInt(PARAM_POLL, 500); + int keepAlive = params.optInt(PARAM_KEEP_ALIVE, -1); + + try { + String contentType; + int nextKeepAlive = keepAlive * 1000; + int alive = 0; + if (keepAlive > 0) { + contentType = "text/plain"; + } else { + contentType = "text/event-stream"; + } + msg.setResponseHeader(API.getDefaultResponseHeader(contentType, -1)); + msg.getResponseHeader().setHeader(HttpHeader.CONNECTION, HttpHeader._KEEP_ALIVE); + + httpOut.write(msg.getResponseHeader()); + while (true) { + Message brkMsg = extension.getBreakpointManagementInterface().getMessage(); + if (brkMsg != null && brkMsg instanceof HttpMessage) { + String event; + HttpMessage httpMsg = (HttpMessage) brkMsg; + JSONObject jo = new JSONObject(); + if (extension.getBreakpointManagementInterface().isRequest()) { + event = "httpRequest"; + jo.put("header", httpMsg.getRequestHeader().toString()); + jo.put("body", httpMsg.getRequestBody().toString()); + } else { + event = "httpResponse"; + jo.put("header", httpMsg.getResponseHeader().toString()); + jo.put("body", httpMsg.getResponseBody().toString()); + } + httpOut.write("event: " + event + "\n"); + httpOut.write("data: " + jo.toString() + "\n\n"); + httpOut.flush(); + break; + } + try { + Thread.sleep(poll); + alive += poll; + } catch (InterruptedException e) { + // Ignore + } + if (keepAlive > 0 && alive > nextKeepAlive) { + httpOut.write("event: keepalive\n"); + httpOut.write("data: {}\n\n"); + httpOut.flush(); + nextKeepAlive = alive + (keepAlive * 1000); + } + } + } catch (IOException e) { + // Ignore - likely to just mean the client has closed the connection + } finally { + httpOut.close(); + httpIn.close(); + } + return; + } + throw new ApiException(ApiException.Type.BAD_PCONN); + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakEventPublisher.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakEventPublisher.java new file mode 100644 index 00000000000..de8803dfeb1 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakEventPublisher.java @@ -0,0 +1,87 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2018 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.addon.brk; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.zaproxy.zap.ZAP; +import org.zaproxy.zap.eventBus.Event; +import org.zaproxy.zap.eventBus.EventPublisher; +import org.zaproxy.zap.extension.httppanel.Message; + +/** + * @since 2.8.0 + */ +public class BreakEventPublisher implements EventPublisher { + + private static BreakEventPublisher publisher = null; + + /** Indicates that a message hit a breakpoint. */ + public static final String BREAK_POINT_HIT = "break.hit"; + + /** + * Indicates the message currently being changed (active). + * + *

Only one message can be active at the same time. + */ + public static final String BREAK_POINT_ACTIVE = "break.active"; + + /** Indicates that the active message no longer is, it might have been dropped or forwarded. */ + public static final String BREAK_POINT_INACTIVE = "break.inactive"; + + public static final String MESSAGE_TYPE = "messageType"; + + @Override + public String getPublisherName() { + return BreakEventPublisher.class.getCanonicalName(); + } + + public static synchronized BreakEventPublisher getPublisher() { + if (publisher == null) { + publisher = new BreakEventPublisher(); + ZAP.getEventBus() + .registerPublisher( + publisher, BREAK_POINT_HIT, BREAK_POINT_ACTIVE, BREAK_POINT_INACTIVE); + } + return publisher; + } + + public void publishHitEvent(Message msg) { + this.publishEvent(BREAK_POINT_HIT, msg, msg.toEventData()); + } + + public void publishActiveEvent(Message msg) { + this.publishEvent(BREAK_POINT_ACTIVE, msg, msg.toEventData()); + } + + public void publishInactiveEvent(Message msg) { + this.publishEvent(BREAK_POINT_INACTIVE, msg, Collections.emptyMap()); + } + + private void publishEvent(String event, Message msg, Map parameters) { + Map map = new HashMap<>(); + map.putAll(parameters); // Could be an empty map + map.put(MESSAGE_TYPE, msg.getType()); + + ZAP.getEventBus() + .publishSyncEvent(getPublisher(), new Event(getPublisher(), event, null, map)); + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanel.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanel.java new file mode 100644 index 00000000000..df1d0a42cc2 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanel.java @@ -0,0 +1,763 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk; + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.EventQueue; +import java.awt.event.KeyEvent; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +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.JToolBar.Separator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.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.InvalidMessageDataException; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.extension.httppanel.view.impl.models.http.HttpPanelViewModelUtils; +import org.zaproxy.zap.utils.DisplayUtils; +import org.zaproxy.zap.view.ZapToggleButton; + +@SuppressWarnings("serial") +public class BreakPanel extends AbstractPanel implements BreakpointManagementInterface { + + private static final long serialVersionUID = 1L; + private static final Logger LOGGER = LogManager.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 ZapToggleButton fixRequestContentLength; + private ZapToggleButton fixResponseContentLength; + private ZapToggleButton fixRequestHostHeader; + + 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( + extension + .getView() + .getMenuShortcutKeyStroke(KeyEvent.VK_B, KeyEvent.SHIFT_DOWN_MASK, false)); + this.setMnemonic(Constant.messages.getChar("brk.panel.mnemonic")); + + this.setLayout(new BorderLayout()); + + breakToolbarFactory = new BreakPanelToolbarFactory(extension, 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); + + // The options toolbars are always added just to the Break request and response panels + JToolBar requestOptionsToolBar = new JToolBar(); + requestOptionsToolBar.setFloatable(false); + requestOptionsToolBar.setBorder(BorderFactory.createEmptyBorder()); + requestOptionsToolBar.setRollover(true); + + requestOptionsToolBar.add(this.getRequestButtonFixContentLength()); + requestOptionsToolBar.add(this.getRequestButtonFixHostHeader()); + requestPanel.addOptions(requestOptionsToolBar, HttpPanel.OptionsLocation.AFTER_COMPONENTS); + + JToolBar responseOptionsToolBar = new JToolBar(); + responseOptionsToolBar.setFloatable(false); + responseOptionsToolBar.setBorder(BorderFactory.createEmptyBorder()); + responseOptionsToolBar.setRollover(true); + + responseOptionsToolBar.add(this.getResponseButtonFixContentLength()); + responsePanel.addOptions( + responseOptionsToolBar, HttpPanel.OptionsLocation.AFTER_COMPONENTS); + + currentButtonsLocation = -1; + } + + /** + * Sets the location of the break buttons. + * + *

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() { + if (!View.getSingleton().isCanGetFocus()) { + return; + } + final Boolean alwaysOnTopOption = breakpointsParams.getAlwaysOnTop(); + if (alwaysOnTopOption == null || alwaysOnTopOption) { + + 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(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); + getRequestButtonFixContentLength() + .setVisible(msg instanceof HttpMessage); + getRequestButtonFixHostHeader() + .setVisible(msg instanceof HttpMessage); + cl.show(panelContent, REQUEST_PANEL); + } else { + responsePanel.setMessage(aMessage, true); + responsePanel.setEditable(true); + getResponseButtonFixContentLength() + .setVisible(msg instanceof HttpMessage); + 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) { + Message msg = getMessage(); + if (msg instanceof HttpMessage) { + updateHttpRequestMessage((HttpMessage) msg); + } + cl.show(panelContent, REQUEST_PANEL); + } else { + Message msg = getMessage(); + if (msg instanceof HttpMessage + && getResponseButtonFixContentLength().isSelected()) { + HttpPanelViewModelUtils.updateResponseContentLength( + (HttpMessage) msg); + } + cl.show(panelContent, RESPONSE_PANEL); + } + } + }); + } catch (Exception ie) { + LOGGER.warn(ie.getMessage(), ie); + } + } + + @SuppressWarnings("unchecked") + private void updateHttpRequestMessage(HttpMessage msg) { + if (getRequestButtonFixContentLength().isSelected()) { + HttpPanelViewModelUtils.updateRequestContentLength(msg); + } + if (!getRequestButtonFixHostHeader().isSelected()) { + Map properties; + if (msg.getUserObject() instanceof Map) { + properties = (Map) msg.getUserObject(); + } else { + properties = new HashMap<>(); + msg.setUserObject(properties); + } + + properties.put("host.normalization", Boolean.FALSE); + } + } + + boolean isValidState() { + HttpPanel panel = isRequest() ? requestPanel : responsePanel; + try { + panel.saveData(); + return true; + } catch (InvalidMessageDataException e) { + StringBuilder warnMessage = new StringBuilder(150); + warnMessage.append(Constant.messages.getString("brk.panel.warn.datainvalid")); + + String exceptionMessage = e.getLocalizedMessage(); + if (exceptionMessage != null && !exceptionMessage.isEmpty()) { + warnMessage.append('\n').append(exceptionMessage); + } + View.getSingleton().showWarningDialog(warnMessage.toString()); + } + return false; + } + + 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); + getRequestButtonFixContentLength().setVisible(false); + getRequestButtonFixHostHeader().setVisible(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); + getResponseButtonFixContentLength().setVisible(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() { + if (!isValidState()) { + return; + } + + breakToolbarFactory.step(); + } + + @Override + public void cont() { + if (!isValidState()) { + return; + } + + breakToolbarFactory.setContinue(true); + breakToolbarFactory.setBreakAll(false); + breakToolbarFactory.setBreakRequest(false); + breakToolbarFactory.setBreakResponse(false); + } + + @Override + public void drop() { + breakToolbarFactory.drop(); + } + + 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); + } + + protected void setShowIgnoreFilesButtons(boolean showButtons) { + this.breakToolbarFactory.setShowIgnoreFilesButtons(showButtons); + + mainBreakButtons.setShowIgnoreFilesButtons(showButtons); + requestBreakButtons.setShowIgnoreFilesButtons(showButtons); + responseBreakButtons.setShowIgnoreFilesButtons(showButtons); + } + + public List getIgnoreRulesEnableList() { + return breakToolbarFactory.getIgnoreRulesEnableList(); + } + + public void updateIgnoreFileTypesRegexs() { + breakToolbarFactory.updateIgnoreFileTypesRegexs(); + } + + private ZapToggleButton getRequestButtonFixContentLength() { + if (fixRequestContentLength == null) { + fixRequestContentLength = + new ZapToggleButton( + DisplayUtils.getScaledIcon( + new ImageIcon( + BreakPanel.class.getResource( + "/resource/icon/fugue/application-resize.png"))), + true); + fixRequestContentLength.setToolTipText( + Constant.messages.getString("brk.checkBox.fixLength")); + fixRequestContentLength.setVisible(false); + } + return fixRequestContentLength; + } + + private ZapToggleButton getResponseButtonFixContentLength() { + if (fixResponseContentLength == null) { + fixResponseContentLength = + new ZapToggleButton( + DisplayUtils.getScaledIcon( + new ImageIcon( + BreakPanel.class.getResource( + "/resource/icon/fugue/application-resize.png"))), + true); + fixResponseContentLength.setToolTipText( + Constant.messages.getString("brk.checkBox.fixLength")); + fixResponseContentLength.setVisible(false); + } + return fixResponseContentLength; + } + + private ZapToggleButton getRequestButtonFixHostHeader() { + if (fixRequestHostHeader == null) { + fixRequestHostHeader = + new ZapToggleButton( + DisplayUtils.getScaledIcon( + new ImageIcon( + BreakPanel.class.getResource( + "/resource/icon/fugue/server.png"))), + true); + fixRequestHostHeader.setToolTipText( + Constant.messages.getString("brk.checkBox.fixHostHeader")); + fixRequestHostHeader.setVisible(false); + } + return fixRequestHostHeader; + } + + /** + * 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; + private final Separator separatorForBreakOnButtons; + private final JToggleButton brkOnJavaScriptButton; + private final JToggleButton brkOnCssAndFontsButton; + private final JToggleButton brkOnMultimediaButton; + private final Separator separatorForBreakOnlyScopeButton; + private final JToggleButton brkOnlyOnScopeButton; + + public BreakButtonsUI(String name, BreakPanelToolbarFactory breakToolbarFactory) { + requestButton = breakToolbarFactory.getBtnBreakRequest(); + responseButton = breakToolbarFactory.getBtnBreakResponse(); + allButton = breakToolbarFactory.getBtnBreakAll(); + separatorForBreakOnButtons = new JToolBar.Separator(); + brkOnJavaScriptButton = breakToolbarFactory.getBtnBreakOnJavaScript(); + brkOnCssAndFontsButton = breakToolbarFactory.getBtnBreakOnCssAndFonts(); + brkOnMultimediaButton = breakToolbarFactory.getBtnBreakOnMultimedia(); + separatorForBreakOnlyScopeButton = new JToolBar.Separator(); + brkOnlyOnScopeButton = breakToolbarFactory.getBtnOnlyBreakOnScope(); + + 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()); + toolBar.add(separatorForBreakOnButtons); + toolBar.add(brkOnJavaScriptButton); + toolBar.add(brkOnCssAndFontsButton); + toolBar.add(brkOnMultimediaButton); + toolBar.add(separatorForBreakOnlyScopeButton); + toolBar.add(brkOnlyOnScopeButton); + } + + /** + * 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); + } + + public void setShowIgnoreFilesButtons(boolean showButtons) { + separatorForBreakOnButtons.setVisible(showButtons); + brkOnJavaScriptButton.setVisible(showButtons); + brkOnCssAndFontsButton.setVisible(showButtons); + brkOnMultimediaButton.setVisible(showButtons); + separatorForBreakOnlyScopeButton.setVisible(showButtons); + brkOnlyOnScopeButton.setVisible(showButtons); + } + + /** + * Gets the underlying view component, with the break buttons. + * + * @return the view component + */ + public JComponent getComponent() { + return toolBar; + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanelToolbarFactory.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanelToolbarFactory.java new file mode 100644 index 00000000000..e147c6e79d4 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakPanelToolbarFactory.java @@ -0,0 +1,871 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2011 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.addon.brk; + +import java.awt.event.ActionEvent; +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JOptionPane; +import javax.swing.JToggleButton; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.view.TabbedPanel; +import org.parosproxy.paros.view.View; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage; +import org.zaproxy.zap.utils.DisplayUtils; +import org.zaproxy.zap.utils.Stats; +import org.zaproxy.zap.view.TabbedPanel2; +import org.zaproxy.zap.view.ZapToggleButton; + +// Button notes +// BreakRequest button, if set all requests trapped +// BreakResponse button, ditto for responses +// If breakpoint hit, Break tab gets focus and icon goes red +// Step button, only if breakpoint hit, submits just this req/resp, breaks on next +// Continue button, only if breakpoint hit, submits this req/resp and continues until next break +// point hit +// If BreakReq & Resp both selected Step and Continue buttons have same effect +// + +public class BreakPanelToolbarFactory { + + private static final String ICON_RESOURCE_PATH = "/resource/icon/"; + + private ContinueButtonAction continueButtonAction; + private StepButtonAction stepButtonAction; + private DropButtonAction dropButtonAction; + private AddBreakpointButtonAction addBreakpointButtonAction; + + private BreakRequestsButtonAction breakRequestsButtonAction; + private BreakResponsesButtonAction breakResponsesButtonAction; + private BreakAllButtonAction breakAllButtonAction; + + private SetBreakOnJavaScriptAction setBreakOnJavaScriptAction; + private SetBreakOnCssAndFontsAction setBreakOnCssAndFontsAction; + private SetBreakOnMultimediaAction setBreakOnMultimediaAction; + private SetBreakOnlyOnScopeAction setOnlyBreakOnScopeAction; + + private boolean cont = false; + private boolean step = false; + private boolean stepping = false; + private boolean drop = false; + private boolean isBreakRequest = false; + private boolean isBreakResponse = false; + private boolean isBreakAll = false; + private boolean isBreakOnJavaScript = true; + private boolean isBreakOnCssAndFonts = true; + private boolean isBreakOnMultimedia = true; + + private BreakPanel breakPanel = null; + + private BreakpointsParam breakpointsParams; + private int mode = 0; + + private List ignoreRulesEnable; + private HttpBreakpointMessage ignoreJavascriptBreakpointMessage; + private HttpBreakpointMessage ignoreCssAndFontsBreakpointMessage; + private HttpBreakpointMessage ignoreMultimediaBreakpointMessage; + + /** + * A counter to keep track of how many messages are currently caught, to disable the break + * buttons when no message is left. + * + *

The counter is increased when a {@link #breakpointHit() breakpoint is hit} and decreased + * when a message is no longer {@link #isHoldMessage() being held}. + * + * @see #countLock + */ + private int countCaughtMessages; + + /** The object to synchronise changes to {@link #countCaughtMessages}. */ + private final Object countLock = new Object(); + + private final ExtensionBreak extensionBreak; + + public BreakPanelToolbarFactory(BreakpointsParam breakpointsParams, BreakPanel breakPanel) { + this(null, breakpointsParams, breakPanel); + } + + public BreakPanelToolbarFactory( + ExtensionBreak extensionBreak, + BreakpointsParam breakpointsParams, + BreakPanel breakPanel) { + super(); + + this.extensionBreak = extensionBreak; + + continueButtonAction = new ContinueButtonAction(); + stepButtonAction = new StepButtonAction(); + dropButtonAction = new DropButtonAction(); + addBreakpointButtonAction = new AddBreakpointButtonAction(); + + breakRequestsButtonAction = new BreakRequestsButtonAction(); + breakResponsesButtonAction = new BreakResponsesButtonAction(); + breakAllButtonAction = new BreakAllButtonAction(); + + setBreakOnJavaScriptAction = new SetBreakOnJavaScriptAction(); + setBreakOnCssAndFontsAction = new SetBreakOnCssAndFontsAction(); + setBreakOnMultimediaAction = new SetBreakOnMultimediaAction(); + setOnlyBreakOnScopeAction = new SetBreakOnlyOnScopeAction(); + + this.breakpointsParams = breakpointsParams; + this.breakPanel = breakPanel; + + this.ignoreRulesEnable = new ArrayList<>(3); + + ignoreJavascriptBreakpointMessage = + new HttpBreakpointMessage( + breakpointsParams.getJavascriptUrlRegex(), + HttpBreakpointMessage.Location.url, + HttpBreakpointMessage.Match.regex, + false, + true); + ignoreRulesEnable.add(ignoreJavascriptBreakpointMessage); + + ignoreCssAndFontsBreakpointMessage = + new HttpBreakpointMessage( + breakpointsParams.getCssAndFontsUrlRegex(), + HttpBreakpointMessage.Location.url, + HttpBreakpointMessage.Match.regex, + false, + true); + ignoreRulesEnable.add(ignoreCssAndFontsBreakpointMessage); + + ignoreMultimediaBreakpointMessage = + new HttpBreakpointMessage( + breakpointsParams.getMultimediaUrlRegex(), + HttpBreakpointMessage.Location.url, + HttpBreakpointMessage.Match.regex, + false, + true); + ignoreRulesEnable.add(ignoreMultimediaBreakpointMessage); + } + + public List getIgnoreRulesEnableList() { + return ignoreRulesEnable; + } + + private static ImageIcon getScaledIcon(String path) { + return DisplayUtils.getScaledIcon( + new ImageIcon( + BreakPanelToolbarFactory.class.getResource(ICON_RESOURCE_PATH + path))); + } + + private void setActiveIcon(boolean active) { + if (active) { + // Have to do this before the getParent() call + breakPanel.setTabFocus(); + } + if (breakPanel.getParent() instanceof TabbedPanel) { + TabbedPanel parent = (TabbedPanel) breakPanel.getParent(); + if (active) { + parent.setIconAt( + parent.indexOfComponent(breakPanel), getScaledIcon("16/101.png")); // Red X + } else { + parent.setIconAt( + parent.indexOfComponent(breakPanel), + getScaledIcon("16/101grey.png")); // Grey X + } + if (parent instanceof TabbedPanel2) { + // If possible lock the tab while it is active so it cant be closed + ((TabbedPanel2) parent).setTabLocked(breakPanel, !active); + } + } + } + + public void breakpointHit() { + synchronized (countLock) { + countCaughtMessages++; + } + + // This could have been via a breakpoint, so force the serialisation + resetRequestSerialization(true); + + // Set the active icon and reset the continue button + this.setActiveIcon(true); + setContinue(false); + } + + public boolean isBreakRequest() { + return isBreakRequest || isBreakAll; + } + + public boolean isBreakResponse() { + return isBreakResponse || isBreakAll; + } + + public boolean isBreakAll() { + return isBreakAll; + } + + public JButton getBtnStep() { + return new JButton(stepButtonAction); + } + + public JButton getBtnContinue() { + return new JButton(continueButtonAction); + } + + public JButton getBtnDrop() { + return new JButton(dropButtonAction); + } + + private int askForDropConfirmation() { + String title = Constant.messages.getString("brk.dialogue.confirmDropMessage.title"); + String message = Constant.messages.getString("brk.dialogue.confirmDropMessage.message"); + JCheckBox checkBox = + new JCheckBox( + Constant.messages.getString( + "brk.dialogue.confirmDropMessage.option.dontAskAgain")); + String confirmButtonLabel = + Constant.messages.getString("brk.dialogue.confirmDropMessage.button.confirm.label"); + String cancelButtonLabel = + Constant.messages.getString("brk.dialogue.confirmDropMessage.button.cancel.label"); + + int option = + JOptionPane.showOptionDialog( + View.getSingleton().getMainFrame(), + new Object[] {message, " ", checkBox}, + title, + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + new String[] {confirmButtonLabel, cancelButtonLabel}, + null); + + if (checkBox.isSelected()) { + breakpointsParams.setConfirmDropMessage(false); + } + + return option; + } + + public JToggleButton getBtnBreakRequest() { + ZapToggleButton btnBreakRequest; + + btnBreakRequest = new ZapToggleButton(breakRequestsButtonAction); + btnBreakRequest.setSelectedIcon(getScaledIcon("16/105r.png")); + + btnBreakRequest.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.request.unset")); + + return btnBreakRequest; + } + + public JToggleButton getBtnBreakResponse() { + ZapToggleButton btnBreakResponse; + + btnBreakResponse = new ZapToggleButton(breakResponsesButtonAction); + btnBreakResponse.setSelectedIcon(getScaledIcon("16/106r.png")); + + btnBreakResponse.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.response.unset")); + + return btnBreakResponse; + } + + public JToggleButton getBtnBreakAll() { + ZapToggleButton btnBreakAll; + + btnBreakAll = new ZapToggleButton(breakAllButtonAction); + btnBreakAll.setSelectedIcon(getScaledIcon("16/151.png")); + + btnBreakAll.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.all.unset")); + + return btnBreakAll; + } + + public JToggleButton getBtnBreakOnJavaScript() { + ZapToggleButton btnBreakOnJavaScript; + + btnBreakOnJavaScript = new ZapToggleButton(setBreakOnJavaScriptAction); + btnBreakOnJavaScript.setSelectedIcon(getScaledIcon("breakTypes/javascriptNotBreaking.png")); + btnBreakOnJavaScript.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.brkjavascript.set")); + + return btnBreakOnJavaScript; + } + + public JToggleButton getBtnBreakOnCssAndFonts() { + ZapToggleButton btnBreakOnCssAndFonts; + + btnBreakOnCssAndFonts = new ZapToggleButton(setBreakOnCssAndFontsAction); + btnBreakOnCssAndFonts.setSelectedIcon( + getScaledIcon("breakTypes/cssAndFontsNotBreaking.png")); + btnBreakOnCssAndFonts.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.brkcssfonts.set")); + + return btnBreakOnCssAndFonts; + } + + public JToggleButton getBtnBreakOnMultimedia() { + ZapToggleButton btnBreakOnMultimedia; + + btnBreakOnMultimedia = new ZapToggleButton(setBreakOnMultimediaAction); + btnBreakOnMultimedia.setSelectedIcon(getScaledIcon("breakTypes/multimediaNotBreaking.png")); + btnBreakOnMultimedia.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.brkmultimedia.set")); + + return btnBreakOnMultimedia; + } + + public JToggleButton getBtnOnlyBreakOnScope() { + ZapToggleButton btnOnlyBreakOnScope; + + btnOnlyBreakOnScope = new ZapToggleButton(setOnlyBreakOnScopeAction); + btnOnlyBreakOnScope.setSelectedIcon(getScaledIcon("fugue/target.png")); + + btnOnlyBreakOnScope.setSelectedToolTipText( + Constant.messages.getString("brk.toolbar.button.brkOnlyOnScope.unset")); + + return btnOnlyBreakOnScope; + } + + public JButton getBtnBreakPoint() { + return new JButton(addBreakpointButtonAction); + } + + public boolean isStepping() { + return stepping; + } + + private void resetRequestSerialization(boolean forceSerialize) { + if (Control.getSingleton() == null) { + // Still in setup + return; + } + // If forces or either break buttons are pressed force the proxy to submit requests and + // responses serially + boolean serialise = forceSerialize || isBreakRequest() || isBreakResponse() || isBreakAll; + if (extensionBreak != null) { + extensionBreak.getSerialisationRequiredListeners().forEach(e -> e.accept(serialise)); + } + } + + public void setBreakRequest(boolean brk) { + isBreakRequest = brk; + resetRequestSerialization(false); + + breakRequestsButtonAction.setSelected(isBreakRequest); + } + + public void setBreakResponse(boolean brk) { + isBreakResponse = brk; + resetRequestSerialization(false); + + breakResponsesButtonAction.setSelected(isBreakResponse); + } + + public void setBreakAll(boolean brk) { + isBreakAll = brk; + if (!brk) { + stepping = false; + } + + resetRequestSerialization(false); + + breakAllButtonAction.setSelected(isBreakAll); + } + + public void setBreakOnJavaScript(boolean brk) { + isBreakOnJavaScript = brk; + setBreakOnJavaScriptAction.setSelected(!isBreakOnJavaScript); + ignoreJavascriptBreakpointMessage.setEnabled(!isBreakOnJavaScript); + } + + public void setBreakOnCssAndFonts(boolean brk) { + isBreakOnCssAndFonts = brk; + setBreakOnCssAndFontsAction.setSelected(!isBreakOnCssAndFonts); + ignoreCssAndFontsBreakpointMessage.setEnabled(!isBreakOnCssAndFonts); + } + + public void setBreakOnMultimedia(boolean brk) { + isBreakOnMultimedia = brk; + setBreakOnMultimediaAction.setSelected(!isBreakOnMultimedia); + ignoreMultimediaBreakpointMessage.setEnabled(!isBreakOnMultimedia); + } + + public void setOnlyBreakOnScope(boolean brk) { + breakpointsParams.setInScopeOnly(brk); + setOnlyBreakOnScopeAction.setSelected(brk); + } + + private void toggleBreakRequest() { + setBreakRequest(!isBreakRequest); + } + + private void toggleBreakResponse() { + setBreakResponse(!isBreakResponse); + } + + private void toggleBreakAll() { + setBreakAll(!isBreakAll); + } + + private void toggleBreakOnJavascript() { + setBreakOnJavaScript(!isBreakOnJavaScript); + } + + private void toggleBreakOnCssAndFonts() { + setBreakOnCssAndFonts(!isBreakOnCssAndFonts); + } + + private void toggleBreakOnMultimedia() { + setBreakOnMultimedia(!isBreakOnMultimedia); + } + + private void toggleBreakOnScopeOnly() { + setOnlyBreakOnScope(!breakpointsParams.isInScopeOnly()); + } + + public boolean isHoldMessage() { + if (isHoldMessageImpl()) { + return true; + } + + synchronized (countLock) { + countCaughtMessages--; + if (countCaughtMessages == 0) { + setButtonsAndIconState(false); + } + } + return false; + } + + private boolean isHoldMessageImpl() { + if (step) { + // Only works one time, until its pressed again + stepping = true; + step = false; + return false; + } + if (cont) { + // They've pressed the continue button, stop stepping + stepping = false; + resetRequestSerialization(false); + return false; + } + if (drop) { + return false; + } + return true; + } + + public boolean isContinue() { + return cont; + } + + public void setBreakEnabled(boolean enabled) { + if (!enabled) { + this.isBreakRequest = false; + this.isBreakResponse = false; + this.isBreakAll = false; + this.setContinue(true); + } + breakRequestsButtonAction.setSelected(false); + breakRequestsButtonAction.setEnabled(enabled); + + breakResponsesButtonAction.setSelected(false); + breakResponsesButtonAction.setEnabled(enabled); + + breakAllButtonAction.setSelected(false); + breakAllButtonAction.setEnabled(enabled); + } + + private void setButtonsAndIconState(boolean enabled) { + stepButtonAction.setEnabled(enabled); + continueButtonAction.setEnabled(enabled); + dropButtonAction.setEnabled(enabled); + if (!enabled) { + this.setActiveIcon(false); + } + } + + protected void setContinue(boolean isContinue) { + this.cont = isContinue; + setButtonsAndIconState(!isContinue); + } + + protected void step() { + step = true; + Stats.incCounter(ExtensionBreak.BREAK_POINT_STEP_STATS); + } + + protected void drop() { + if (breakpointsParams.isConfirmDropMessage() + && askForDropConfirmation() != JOptionPane.OK_OPTION) { + return; + } + drop = true; + Stats.incCounter(ExtensionBreak.BREAK_POINT_DROP_STATS); + } + + public boolean isToBeDropped() { + if (drop) { + drop = false; + return true; + } + return false; + } + + public void init() { + cont = false; + step = false; + stepping = false; + drop = false; + isBreakRequest = false; + isBreakResponse = false; + isBreakAll = false; + setShowIgnoreFilesButtons(false); + countCaughtMessages = 0; + } + + public void reset() { + if (isBreakRequest()) { + toggleBreakRequest(); + } + + if (isBreakResponse()) { + toggleBreakResponse(); + } + + if (isBreakAll()) { + toggleBreakAll(); + } + + setContinue(true); + } + + /** + * Sets the current button mode. + * + *

If the mode is already set no change is done, otherwise it does the following: + * + *

+ * + * The enabled state of previous mode is disabled to prevent interferences between the modes. + * + * @param mode the mode to be set + * @see #isBreakAll() + * @see #isBreakRequest() + * @see #isBreakResponse() + */ + public void setButtonMode(int mode) { + if (this.mode == mode) { + return; + } + if (this.mode == BreakpointsParam.BUTTON_MODE_SIMPLE) { + if (isBreakAll) { + setBreakAll(false); + setBreakRequest(true); + setBreakResponse(true); + } + } else if (isBreakRequest || isBreakResponse) { + setBreakRequest(false); + setBreakResponse(false); + setBreakAll(true); + } + this.mode = mode; + } + + public void setShowIgnoreFilesButtons(boolean showButtons) { + if (!showButtons) { + setBreakOnJavaScript(true); + setBreakOnCssAndFonts(true); + setBreakOnMultimedia(true); + setOnlyBreakOnScope(breakpointsParams.isInScopeOnly()); + } + } + + public void updateIgnoreFileTypesRegexs() { + ignoreJavascriptBreakpointMessage.setString(this.breakpointsParams.getJavascriptUrlRegex()); + ignoreCssAndFontsBreakpointMessage.setString( + this.breakpointsParams.getCssAndFontsUrlRegex()); + ignoreMultimediaBreakpointMessage.setString(this.breakpointsParams.getMultimediaUrlRegex()); + } + + private class ContinueButtonAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + public ContinueButtonAction() { + super(null, getScaledIcon("16/131.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.cont")); + + setEnabled(false); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (!breakPanel.isValidState()) { + return; + } + + setContinue(true); + setBreakAll(false); + setBreakRequest(false); + setBreakResponse(false); + } + } + + private class StepButtonAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + public StepButtonAction() { + super(null, getScaledIcon("16/143.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.step")); + + setEnabled(false); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (!breakPanel.isValidState()) { + return; + } + + if (mode == BreakpointsParam.BUTTON_MODE_SIMPLE && !isBreakAll) { + // In simple mode 'step' if the breakAll button is disabled then it acts like + // 'continue' + // so that its hopefully obvious to users when break is on or not + setContinue(true); + } else { + step(); + } + } + } + + private class DropButtonAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + public DropButtonAction() { + super(null, getScaledIcon("16/150.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.bin")); + + setEnabled(false); + } + + @Override + public void actionPerformed(ActionEvent e) { + drop(); + } + } + + private class AddBreakpointButtonAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + public AddBreakpointButtonAction() { + super(null, getScaledIcon("16/break_add.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.brkpoint")); + } + + @Override + public void actionPerformed(ActionEvent e) { + breakPanel.showNewBreakPointDialog(); + } + } + + private class BreakRequestsButtonAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public BreakRequestsButtonAction() { + super(null, getScaledIcon("16/105.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.request.set")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakRequest(); + } + } + + private class BreakResponsesButtonAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public BreakResponsesButtonAction() { + super(null, getScaledIcon("16/106.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.response.set")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakResponse(); + } + } + + private class BreakAllButtonAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public BreakAllButtonAction() { + super(null, getScaledIcon("16/152.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.all.set")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakAll(); + } + } + + private class SetBreakOnJavaScriptAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public SetBreakOnJavaScriptAction() { + super(null, getScaledIcon("breakTypes/javascript.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.brkjavascript.unset")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakOnJavascript(); + } + } + + private class SetBreakOnCssAndFontsAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public SetBreakOnCssAndFontsAction() { + super(null, getScaledIcon("breakTypes/cssAndFonts.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.brkcssfonts.unset")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakOnCssAndFonts(); + } + } + + private class SetBreakOnMultimediaAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public SetBreakOnMultimediaAction() { + super(null, getScaledIcon("breakTypes/multimedia.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.brkmultimedia.unset")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakOnMultimedia(); + } + } + + private class SetBreakOnlyOnScopeAction extends SelectableAbstractAction { + + private static final long serialVersionUID = 1L; + + public SetBreakOnlyOnScopeAction() { + super(null, getScaledIcon("fugue/target-grey.png")); + + putValue( + Action.SHORT_DESCRIPTION, + Constant.messages.getString("brk.toolbar.button.brkOnlyOnScope.set")); + } + + @Override + public void actionPerformed(ActionEvent e) { + toggleBreakOnScopeOnly(); + } + } + + /** + * An {@code AbstractAction} which allows to be selected. + * + * @see AbstractAction + * @see #setSelected(boolean) + */ + private abstract static class SelectableAbstractAction extends AbstractAction { + + private static final long serialVersionUID = 1L; + + /** + * Creates a {@code SelectableAbstractAction} with the specified {@code name} and {@code + * icon}. + * + * @param name the name for the action or {@code null} for no name + * @param icon the icon for the action or {@code null} for no icon + */ + public SelectableAbstractAction(String name, Icon icon) { + super(name, icon); + } + + /** + * Sets whether the action is selected or not. + * + * @param selected {@code true} if the action should be selected, {@code false} otherwise + */ + public void setSelected(boolean selected) { + putValue(Action.SELECTED_KEY, selected); + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointManagementInterface.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointManagementInterface.java new file mode 100644 index 00000000000..434291ea446 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointManagementInterface.java @@ -0,0 +1,72 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2016 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.addon.brk; + +import org.parosproxy.paros.control.Control.Mode; +import org.zaproxy.zap.extension.httppanel.Message; + +public interface BreakpointManagementInterface { + + boolean isBreakRequest(); + + boolean isBreakResponse(); + + boolean isBreakAll(); + + void breakpointHit(); + + boolean isHoldMessage(Message aMessage); + + boolean isStepping(); + + boolean isToBeDropped(); + + Message getMessage(); + + void setMessage(Message aMessage, boolean isRequest); + + boolean isRequest(); + + void saveMessage(boolean isRequest); + + void clearAndDisableRequest(); + + void clearAndDisableResponse(); + + void init(); + + void reset(); + + void sessionModeChanged(Mode mode); + + void setBreakAllRequests(boolean brk); + + void setBreakAllResponses(boolean brk); + + void setBreakAll(boolean brk); + + void step(); + + void cont(); + + void drop(); + + void breakpointDisplayed(); +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageHandler2.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageHandler2.java new file mode 100644 index 00000000000..04f2dd74395 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageHandler2.java @@ -0,0 +1,239 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2016 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.addon.brk; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.control.Control.Mode; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.utils.Stats; + +public class BreakpointMessageHandler2 { + + private static final Logger LOGGER = LogManager.getLogger(BreakpointMessageHandler2.class); + + protected static final Object SEMAPHORE = new Object(); + + protected final BreakpointManagementInterface breakMgmt; + + protected List enabledBreakpoints; + + protected List enabledIgnoreRules; + + private List enabledKeyBreakpoints = new ArrayList<>(); + + public List getEnabledKeyBreakpoints() { + return enabledKeyBreakpoints; + } + + public void setEnabledKeyBreakpoints(List enabledKeyBreakpoints) { + this.enabledKeyBreakpoints = enabledKeyBreakpoints; + } + + public BreakpointMessageHandler2(BreakpointManagementInterface aBreakPanel) { + this.breakMgmt = aBreakPanel; + } + + public void setEnabledBreakpoints(List breakpoints) { + this.enabledBreakpoints = breakpoints; + } + + public void setEnabledIgnoreRules(List IgnoreRules) { + this.enabledIgnoreRules = IgnoreRules; + } + + /** + * Do not call if in {@link Mode#safe}. + * + * @param aMessage + * @param onlyIfInScope + * @return False if message should be dropped. + */ + public boolean handleMessageReceivedFromClient(Message aMessage, boolean onlyIfInScope) { + if (!isBreakpoint(aMessage, true, onlyIfInScope)) { + return true; + } + + // Do this outside of the semaphore loop so that the 'continue' button can apply to all + // queued breakpoints + // but be reset when the next breakpoint is hit + breakMgmt.breakpointHit(); + Stats.incCounter(ExtensionBreak.BREAK_POINT_HIT_STATS); + BreakEventPublisher.getPublisher().publishHitEvent(aMessage); + + synchronized (SEMAPHORE) { + if (breakMgmt.isHoldMessage(aMessage)) { + BreakEventPublisher.getPublisher().publishActiveEvent(aMessage); + setBreakDisplay(aMessage, true); + waitUntilContinue(aMessage, true); + BreakEventPublisher.getPublisher().publishInactiveEvent(aMessage); + } + } + breakMgmt.clearAndDisableRequest(); + return !breakMgmt.isToBeDropped(); + } + + /** + * Do not call if in {@link Mode#safe}. + * + * @param aMessage + * @param onlyIfInScope + * @return False if message should be dropped. + */ + public boolean handleMessageReceivedFromServer(Message aMessage, boolean onlyIfInScope) { + if (!isBreakpoint(aMessage, false, onlyIfInScope)) { + return true; + } + + // Do this outside of the semaphore loop so that the 'continue' button can apply to all + // queued breakpoints + // but be reset when the next breakpoint is hit + breakMgmt.breakpointHit(); + Stats.incCounter(ExtensionBreak.BREAK_POINT_HIT_STATS); + BreakEventPublisher.getPublisher().publishHitEvent(aMessage); + + synchronized (SEMAPHORE) { + if (breakMgmt.isHoldMessage(aMessage)) { + BreakEventPublisher.getPublisher().publishActiveEvent(aMessage); + setBreakDisplay(aMessage, false); + waitUntilContinue(aMessage, false); + BreakEventPublisher.getPublisher().publishInactiveEvent(aMessage); + } + } + breakMgmt.clearAndDisableResponse(); + return !breakMgmt.isToBeDropped(); + } + + private void setBreakDisplay(final Message msg, boolean isRequest) { + breakMgmt.setMessage(msg, isRequest); + breakMgmt.breakpointDisplayed(); + } + + private void waitUntilContinue(Message aMessage, final boolean isRequest) { + // Note that multiple requests and responses can get built up, so pressing continue only + // releases the current break, not all of them. + while (breakMgmt.isHoldMessage(aMessage)) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + LOGGER.warn(e.getMessage(), e); + } + } + breakMgmt.saveMessage(isRequest); + } + + /** + * You have to handle {@link Mode#safe} outside. + * + * @param aMessage + * @param isRequest + * @param onlyIfInScope + * @return True if a breakpoint for given message exists. + */ + public boolean isBreakpoint(Message aMessage, boolean isRequest, boolean onlyIfInScope) { + if (aMessage.isForceIntercept()) { + // The browser told us to do it Your Honour + return true; + } + + if (isSkipOnIgnoreRules(aMessage, isRequest, onlyIfInScope)) { + return false; + } + + if (onlyIfInScope && !aMessage.isInScope()) { + return false; + } + + if (isBreakOnAllRequests(aMessage, isRequest)) { + // Break on all requests + return true; + } else if (isBreakOnAllResponses(aMessage, isRequest)) { + // Break on all responses + return true; + } else if (isBreakOnStepping(aMessage, isRequest)) { + // Stopping through all requests and responses + return true; + } + + return isBreakOnEnabledBreakpoint(aMessage, isRequest, onlyIfInScope); + } + + protected boolean isBreakOnAllRequests(Message aMessage, boolean isRequest) { + return isRequest && breakMgmt.isBreakRequest(); + } + + protected boolean isBreakOnAllResponses(Message aMessage, boolean isRequest) { + return !isRequest && breakMgmt.isBreakResponse(); + } + + protected boolean isBreakOnStepping(Message aMessage, boolean isRequest) { + return breakMgmt.isStepping(); + } + + protected boolean isBreakOnEnabledBreakpoint( + Message aMessage, boolean isRequest, boolean onlyIfInScope) { + if (enabledBreakpoints.isEmpty()) { + // No breakpoints + return false; + } + + // match against the breakpoints + synchronized (enabledBreakpoints) { + Iterator it = enabledBreakpoints.iterator(); + + while (it.hasNext()) { + BreakpointMessageInterface breakpoint = it.next(); + + if (breakpoint.match(aMessage, isRequest, onlyIfInScope)) { + return true; + } + } + } + + return false; + } + + protected boolean isSkipOnIgnoreRules( + Message aMessage, boolean isRequest, boolean onlyIfInScope) { + if (enabledIgnoreRules == null || enabledIgnoreRules.isEmpty()) { + // No Ignoring rules + return false; + } + + // match against the ignoring rule + synchronized (enabledIgnoreRules) { + Iterator it = enabledIgnoreRules.iterator(); + + while (it.hasNext()) { + BreakpointMessageInterface ignoreRule = it.next(); + + if (ignoreRule.isEnabled() + && ignoreRule.match(aMessage, isRequest, onlyIfInScope)) { + return true; + } + } + } + + return false; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageInterface.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageInterface.java new file mode 100644 index 00000000000..b72b80a1d2b --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointMessageInterface.java @@ -0,0 +1,35 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk; + +import org.zaproxy.zap.extension.httppanel.Message; + +public interface BreakpointMessageInterface { + + String getType(); + + boolean match(Message aMessage, boolean isRequest, boolean onlyIfInScope); + + void setEnabled(boolean enabled); + + boolean isEnabled(); + + String getDisplayMessage(); +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsOptionsPanel.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsOptionsPanel.java new file mode 100644 index 00000000000..b2f15fd9670 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsOptionsPanel.java @@ -0,0 +1,245 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2013 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.addon.brk; + +import java.awt.CardLayout; +import java.awt.GridBagLayout; +import java.awt.Insets; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.option.OptionsViewPanel; +import org.parosproxy.paros.model.OptionsParam; +import org.parosproxy.paros.view.AbstractParamPanel; +import org.zaproxy.zap.utils.ZapTextField; +import org.zaproxy.zap.view.LayoutHelper; + +/** + * The GUI breakpoints options panel. + * + *

It allows to change the following breakpoints options: + * + *

    + *
  • Confirm drop message - asks for confirmation when a trapped message is dropped. + *
+ * + * @see org.zaproxy.addon.brk.BreakPanelToolbarFactory#getBtnDrop() + */ +public class BreakpointsOptionsPanel extends AbstractParamPanel { + + private static final long serialVersionUID = 7483614036849207715L; + + private JCheckBox checkBoxConfirmDropMessage = null; + private JCheckBox checkBoxAlwaysOnTop = null; + private JCheckBox checkBoxInScopeOnly = null; + private JCheckBox checkBoxShowIgnoreFilesButtons = null; + private ZapTextField javascriptUrlRegexField = null; + private ZapTextField cssAndFontsUrlRegexField = null; + private ZapTextField multimediaUrlRegexField = null; + private JComboBox buttonMode = null; + + public BreakpointsOptionsPanel() { + super(); + setName(Constant.messages.getString("brk.optionspanel.name")); + + this.setLayout(new CardLayout()); + + JPanel panel = new JPanel(new GridBagLayout()); + panel.setBorder(new EmptyBorder(2, 2, 2, 2)); + + int row = 0; + panel.add( + getCheckBoxConfirmDropMessage(), + LayoutHelper.getGBC(0, row++, 2, 1.0, new Insets(2, 2, 2, 2))); + panel.add( + getCheckBoxInScopeOnly(), + LayoutHelper.getGBC(0, row++, 2, 1.0, new Insets(2, 2, 2, 2))); + panel.add( + getCheckBoxAlwaysOnTop(), + LayoutHelper.getGBC(0, row++, 2, 1.0, new Insets(2, 2, 2, 2))); + panel.add( + getCheckBoxShowIgnoreFilesButtons(), + LayoutHelper.getGBC(0, row++, 2, 1.0, new Insets(2, 2, 2, 2))); + + JLabel javascriptUrlRegexLabel = + new JLabel( + Constant.messages.getString( + "brk.optionspanel.option.javaScriptUrlRegex.label")); + javascriptUrlRegexLabel.setLabelFor(getJavascriptUrlRegexField()); + + panel.add(javascriptUrlRegexLabel, LayoutHelper.getGBC(0, 4, 1, 2.0)); + panel.add(getJavascriptUrlRegexField(), LayoutHelper.getGBC(1, 4, 1, 8.0)); + + JLabel cssAndFontsUrlRegexLabel = + new JLabel( + Constant.messages.getString( + "brk.optionspanel.option.cssAndFontsUrlRegex.label")); + cssAndFontsUrlRegexLabel.setLabelFor(getCssAndFontsUrlRegexField()); + + panel.add(cssAndFontsUrlRegexLabel, LayoutHelper.getGBC(0, 5, 1, 2.0)); + panel.add(getCssAndFontsUrlRegexField(), LayoutHelper.getGBC(1, 5, 1, 8.0)); + + JLabel multimediaUrlRegexLabel = + new JLabel( + Constant.messages.getString( + "brk.optionspanel.option.multimediaUrlRegex.label")); + multimediaUrlRegexLabel.setLabelFor(getMultimediaUrlRegexField()); + + panel.add(multimediaUrlRegexLabel, LayoutHelper.getGBC(0, 6, 1, 2.0)); + panel.add(getMultimediaUrlRegexField(), LayoutHelper.getGBC(1, 6, 1, 8.0)); + + JLabel modeLabel = + new JLabel(Constant.messages.getString("brk.optionspanel.option.breakmode.label")); + modeLabel.setLabelFor(getButtonMode()); + panel.add(modeLabel, LayoutHelper.getGBC(0, 7, 1, 0.5)); + panel.add(getButtonMode(), LayoutHelper.getGBC(1, 7, 1, 0.5)); + panel.add(new JLabel(), LayoutHelper.getGBC(0, 10, 1, 0.5D, 1.0D)); // Spacer + + add(panel); + } + + private JCheckBox getCheckBoxConfirmDropMessage() { + if (checkBoxConfirmDropMessage == null) { + checkBoxConfirmDropMessage = + new JCheckBox( + Constant.messages.getString( + "brk.optionspanel.option.confirmDropMessage.label")); + } + return checkBoxConfirmDropMessage; + } + + private JCheckBox getCheckBoxAlwaysOnTop() { + if (checkBoxAlwaysOnTop == null) { + checkBoxAlwaysOnTop = + new JCheckBox( + Constant.messages.getString( + "brk.optionspanel.option.alwaysOnTop.label")); + } + return checkBoxAlwaysOnTop; + } + + private JCheckBox getCheckBoxInScopeOnly() { + if (checkBoxInScopeOnly == null) { + checkBoxInScopeOnly = + new JCheckBox( + Constant.messages.getString( + "brk.optionspanel.option.inScopeOnly.label")); + } + return checkBoxInScopeOnly; + } + + private JCheckBox getCheckBoxShowIgnoreFilesButtons() { + if (checkBoxShowIgnoreFilesButtons == null) { + checkBoxShowIgnoreFilesButtons = + new JCheckBox( + Constant.messages.getString( + "brk.optionspanel.option.showBreakFilteringButtons.label")); + } + return checkBoxShowIgnoreFilesButtons; + } + + private ZapTextField getJavascriptUrlRegexField() { + if (javascriptUrlRegexField == null) { + javascriptUrlRegexField = new ZapTextField(); + } + return javascriptUrlRegexField; + } + + private ZapTextField getCssAndFontsUrlRegexField() { + if (cssAndFontsUrlRegexField == null) { + cssAndFontsUrlRegexField = new ZapTextField(); + } + return cssAndFontsUrlRegexField; + } + + private ZapTextField getMultimediaUrlRegexField() { + if (multimediaUrlRegexField == null) { + multimediaUrlRegexField = new ZapTextField(); + } + return multimediaUrlRegexField; + } + + private JComboBox getButtonMode() { + if (buttonMode == null) { + buttonMode = new JComboBox<>(); + buttonMode.addItem( + Constant.messages.getString("brk.optionspanel.option.breakmode.simple.label")); + buttonMode.addItem( + Constant.messages.getString("brk.optionspanel.option.breakmode.dual.label")); + } + return buttonMode; + } + + @Override + public void initParam(Object obj) { + final OptionsParam options = (OptionsParam) obj; + final BreakpointsParam param = options.getParamSet(BreakpointsParam.class); + + getCheckBoxConfirmDropMessage().setSelected(param.isConfirmDropMessage()); + // Note param.alwaysOnTop will be null if the user hasn't specified a preference yet + getCheckBoxAlwaysOnTop().setSelected(!Boolean.FALSE.equals(param.getAlwaysOnTop())); + getCheckBoxInScopeOnly().setSelected(param.isInScopeOnly()); + getCheckBoxShowIgnoreFilesButtons().setSelected(param.isShowIgnoreFilesButtons()); + if (options.getViewParam().getBrkPanelViewOption() + == OptionsViewPanel.BreakLocation.TOOL_BAR_ONLY.getValue()) { + checkBoxShowIgnoreFilesButtons.setEnabled(false); + checkBoxShowIgnoreFilesButtons.setToolTipText( + Constant.messages.getString("brk.optionspanel.option.notpossibletoshowtip")); + } else { + checkBoxShowIgnoreFilesButtons.setEnabled(true); + checkBoxShowIgnoreFilesButtons.setToolTipText(""); + } + getButtonMode().setSelectedIndex(param.getButtonMode() - 1); + getJavascriptUrlRegexField().setText(param.getJavascriptUrlRegex()); + getJavascriptUrlRegexField().discardAllEdits(); + getCssAndFontsUrlRegexField().setText(param.getCssAndFontsUrlRegex()); + getCssAndFontsUrlRegexField().discardAllEdits(); + getMultimediaUrlRegexField().setText(param.getMultimediaUrlRegex()); + getMultimediaUrlRegexField().discardAllEdits(); + } + + @Override + public void saveParam(Object obj) throws Exception { + final OptionsParam options = (OptionsParam) obj; + final BreakpointsParam param = options.getParamSet(BreakpointsParam.class); + + param.setConfirmDropMessage(getCheckBoxConfirmDropMessage().isSelected()); + if (param.getAlwaysOnTop() != null || !getCheckBoxAlwaysOnTop().isSelected()) { + // Dont set the option if its not already set, unless the user has changed it + // This is so that the warning message will still be shown the first time a breakpoint + // is hit + param.setAlwaysOnTop(getCheckBoxAlwaysOnTop().isSelected()); + } + param.setInScopeOnly(getCheckBoxInScopeOnly().isSelected()); + param.setShowIgnoreFilesButtons(getCheckBoxShowIgnoreFilesButtons().isSelected()); + param.setButtonMode(this.getButtonMode().getSelectedIndex() + 1); + param.setJavascriptUrlRegex(getJavascriptUrlRegexField().getText()); + param.setCssAndFontsUrlRegex(getCssAndFontsUrlRegexField().getText()); + param.setMultimediaUrlRegex(getMultimediaUrlRegexField().getText()); + } + + @Override + public String getHelpIndex() { + return "ui.dialogs.options.breakpoints"; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsPanel.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsPanel.java new file mode 100644 index 00000000000..54d38327b86 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsPanel.java @@ -0,0 +1,355 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk; + +import java.awt.CardLayout; +import java.awt.EventQueue; +import java.awt.GridBagConstraints; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; +import javax.swing.ImageIcon; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import javax.swing.table.TableColumn; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jdesktop.swingx.JXTable; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.AbstractPanel; +import org.parosproxy.paros.view.View; + +@SuppressWarnings("serial") +public class BreakpointsPanel extends AbstractPanel { + + private static final long serialVersionUID = 1L; + + public static final String PANEL_NAME = "breakpoints"; + + private ExtensionBreak extension; + private javax.swing.JPanel panelCommand = null; + private javax.swing.JLabel jLabel = null; + private JScrollPane jScrollPane = null; + private JXTable breakpointsTable = null; + private BreakpointsTableModel model = new BreakpointsTableModel(); + + private static final String BRK_TABLE = "brk.table"; + private static final String PREF_COLUMN_WIDTH = "column.width"; + private final Preferences preferences; + private final String prefnzPrefix = this.getClass().getSimpleName() + "."; + + private static final Logger LOGGER = LogManager.getLogger(BreakpointsPanel.class); + + public BreakpointsPanel(ExtensionBreak extension) { + super(); + this.extension = extension; + this.preferences = Preferences.userNodeForPackage(getClass()); + + initialize(); + } + + private void initialize() { + this.setLayout(new CardLayout()); + this.setSize(474, 251); + this.setName(Constant.messages.getString("brk.panel.title")); + this.setIcon( + new ImageIcon( + BreakpointsPanel.class.getResource( + "/resource/icon/16/101.png"))); // 'red X' icon + this.setDefaultAccelerator( + extension + .getView() + .getMenuShortcutKeyStroke( + KeyEvent.VK_B, + KeyEvent.ALT_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK, + false)); + this.setMnemonic(Constant.messages.getChar("brk.panel.mnemonic")); + this.add(getPanelCommand(), getPanelCommand().getName()); + } + + private javax.swing.JPanel getPanelCommand() { + if (panelCommand == null) { + + panelCommand = new javax.swing.JPanel(); + panelCommand.setLayout(new java.awt.GridBagLayout()); + panelCommand.setName(Constant.messages.getString("brk.panel.title")); + + jLabel = getJLabel(); + GridBagConstraints gridBagConstraints1 = new GridBagConstraints(); + GridBagConstraints gridBagConstraints2 = new GridBagConstraints(); + + // Better without this? + // jLabel.setText("Breakpoints:"); + gridBagConstraints1.gridx = 0; + gridBagConstraints1.gridy = 0; + gridBagConstraints1.insets = new java.awt.Insets(2, 2, 2, 2); + gridBagConstraints1.anchor = java.awt.GridBagConstraints.NORTHWEST; + gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; + gridBagConstraints1.weightx = 1.0D; + gridBagConstraints2.gridx = 0; + gridBagConstraints2.gridy = 1; + gridBagConstraints2.weightx = 1.0; + gridBagConstraints2.weighty = 1.0; + gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH; + gridBagConstraints2.insets = new java.awt.Insets(0, 0, 0, 0); + gridBagConstraints2.anchor = java.awt.GridBagConstraints.NORTHWEST; + + // panelCommand.add(jLabel, gridBagConstraints1); + panelCommand.add(getJScrollPane(), gridBagConstraints2); + } + return panelCommand; + } + + private javax.swing.JLabel getJLabel() { + if (jLabel == null) { + jLabel = new javax.swing.JLabel(); + jLabel.setText(" "); + } + return jLabel; + } + + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setViewportView(getBreakpoints()); + } + return jScrollPane; + } + + protected JXTable getBreakpoints() { + if (breakpointsTable == null) { + breakpointsTable = new JXTable(model); + + breakpointsTable.setColumnSelectionAllowed(false); + breakpointsTable.setCellSelectionEnabled(false); + breakpointsTable.setRowSelectionAllowed(true); + breakpointsTable.setColumnControlVisible(true); + + breakpointsTable + .getColumnModel() + .getColumn(0) + .setPreferredWidth(restoreColumnWidth(BRK_TABLE, 100)); + breakpointsTable + .getColumnModel() + .getColumn(0) + .addPropertyChangeListener(new ColumnResizedListener(BRK_TABLE)); + breakpointsTable.getColumnModel().getColumn(0).setMaxWidth(250); + + breakpointsTable.getTableHeader().setReorderingAllowed(false); + + breakpointsTable.setName(PANEL_NAME); + breakpointsTable.setDoubleBuffered(true); + breakpointsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + breakpointsTable.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 = breakpointsTable.rowAtPoint(e.getPoint()); + if (row < 0 + || !breakpointsTable + .getSelectionModel() + .isSelectedIndex(row)) { + breakpointsTable.getSelectionModel().clearSelection(); + if (row >= 0) { + breakpointsTable + .getSelectionModel() + .setSelectionInterval(row, row); + } + } + + View.getSingleton() + .getPopupMenu() + .show(e.getComponent(), e.getX(), e.getY()); + } + } + + @Override + public void mouseClicked(java.awt.event.MouseEvent e) { + if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) { + // Its a double click + extension.editUiSelectedBreakpoint(); + } + } + }); + } + return breakpointsTable; + } + + public BreakpointMessageInterface getSelectedBreakpoint() { + int selectedRow = breakpointsTable.getSelectedRow(); + if (selectedRow != -1) { + return model.getBreakpointAtRow(breakpointsTable.convertRowIndexToModel(selectedRow)); + } + return null; + } + + private void selectRowAndEnsureVisible(int row) { + if (row != -1) { + breakpointsTable.getSelectionModel().setSelectionInterval(row, row); + breakpointsTable.scrollRectToVisible(breakpointsTable.getCellRect(row, 0, true)); + } + } + + private void addBreakpointModel(BreakpointMessageInterface breakpoint) { + model.addBreakpoint(breakpoint); + selectRowAndEnsureVisible(model.getLastAffectedRow()); + } + + void addBreakpoint(final BreakpointMessageInterface breakpoint) { + if (EventQueue.isDispatchThread()) { + addBreakpointModel(breakpoint); + return; + } + try { + EventQueue.invokeAndWait( + new Runnable() { + @Override + public void run() { + addBreakpointModel(breakpoint); + } + }); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + private void editBreakpointModel( + BreakpointMessageInterface oldBreakpoint, BreakpointMessageInterface newBreakpoint) { + model.editBreakpoint(oldBreakpoint, newBreakpoint); + selectRowAndEnsureVisible(model.getLastAffectedRow()); + } + + void editBreakpoint( + final BreakpointMessageInterface oldBreakpoint, + final BreakpointMessageInterface newBreakpoint) { + if (EventQueue.isDispatchThread()) { + editBreakpointModel(oldBreakpoint, newBreakpoint); + return; + } + try { + EventQueue.invokeAndWait( + new Runnable() { + @Override + public void run() { + editBreakpointModel(oldBreakpoint, newBreakpoint); + } + }); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + private void removeBreakpointModel(BreakpointMessageInterface breakpoint) { + model.removeBreakpoint(breakpoint); + } + + public void removeBreakpoint(final BreakpointMessageInterface breakpoint) { + if (EventQueue.isDispatchThread()) { + removeBreakpointModel(breakpoint); + return; + } + try { + EventQueue.invokeAndWait( + new Runnable() { + @Override + public void run() { + removeBreakpointModel(breakpoint); + } + }); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + private void saveColumnWidth(String prefix, int width) { + if (width > 0) { + LOGGER.debug( + "Saving preference {}{}.{}={}", prefnzPrefix, prefix, PREF_COLUMN_WIDTH, width); + this.preferences.put( + prefnzPrefix + prefix + "." + PREF_COLUMN_WIDTH, Integer.toString(width)); + // immediate flushing + try { + this.preferences.flush(); + } catch (final BackingStoreException e) { + LOGGER.error("Error while saving the preferences", e); + } + } + } + + private int restoreColumnWidth(String prefix, int fallback) { + int result = fallback; + final String sizestr = + preferences.get(prefnzPrefix + prefix + "." + PREF_COLUMN_WIDTH, null); + if (sizestr != null) { + int width = 0; + try { + width = Integer.parseInt(sizestr.trim()); + } catch (final Exception e) { + // ignoring, cause is prevented by default values; + } + if (width > 0) { + result = width; + LOGGER.debug( + "Restoring preference {}{}.{}={}", + prefnzPrefix, + prefix, + PREF_COLUMN_WIDTH, + width); + } + } + return result; + } + + private final class ColumnResizedListener implements PropertyChangeListener { + + private final String prefix; + + public ColumnResizedListener(String prefix) { + super(); + assert prefix != null; + this.prefix = prefix; + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + TableColumn column = (TableColumn) evt.getSource(); + if (column != null) { + LOGGER.debug( + "{}{}.{}={}", prefnzPrefix, prefix, PREF_COLUMN_WIDTH, column.getWidth()); + saveColumnWidth(prefix, column.getWidth()); + } + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsParam.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsParam.java new file mode 100644 index 00000000000..e90d1a3d803 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsParam.java @@ -0,0 +1,182 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2013 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.addon.brk; + +import org.parosproxy.paros.common.AbstractParam; + +/** + * Manages the breakpoints configurations saved in the configuration file. + * + *

It allows to change, programmatically, the following breakpoints options: + * + *

    + *
  • Confirm drop message - asks for confirmation when a trapped message is dropped. + *
+ * + * @see org.zaproxy.addon.brk.BreakPanelToolbarFactory#getBtnDrop() + */ +public class BreakpointsParam extends AbstractParam { + + public static final int BUTTON_MODE_SIMPLE = 1; + public static final int BUTTON_MODE_DUAL = 2; + + private static final String PARAM_BASE_KEY = "breakpoints"; + + private static final String PARAM_CONFIRM_DROP_MESSAGE_KEY = + PARAM_BASE_KEY + ".confirmDropMessage"; + private static final String PARAM_UI_BUTTON_MODE = PARAM_BASE_KEY + ".buttonMode"; + private static final String PARAM_BRK_ALWAYS_ON_TOP = PARAM_BASE_KEY + ".alwaysOnTop"; + private static final String PARAM_BRK_IN_SCOPE_ONLY = PARAM_BASE_KEY + ".inScopeOnly"; + private static final String SHOW_IGNORE_REQUESTS_BUTTONS = + PARAM_BASE_KEY + ".showIgnoreRequestsButtons"; + private static final String JAVASCRIPT_URL_REGEX = PARAM_BASE_KEY + ".javaScriptUrlRegex"; + private static final String CSS_AND_FONTS_URL_REGEX = PARAM_BASE_KEY + ".cssAndFontsUrlRegex"; + private static final String MULTIMEDIA_URL_REGEX = PARAM_BASE_KEY + ".multimediaUrlRegex"; + + private static final String JAVASCRIPT_URL_REGEX_DEFAULT = ".*\\.js.*"; + private static final String CSS_AND_FONTS_URL_REGEX_DEFAULT = ".*\\.(?:css|woff|woff2|ttf).*"; + private static final String MULTIMEDIA_URL_REGEX_DEFAULT = + ".*\\.(?:png|gif|jpg|jpeg|svg|mp4|mp3|webm|webp|ico).*"; + + /** Default is {@code false}. */ + private boolean confirmDropMessage; + + private int buttonMode = BUTTON_MODE_SIMPLE; + private Boolean alwaysOnTop = null; + private boolean inScopeOnly = false; + private boolean showIgnoreFilesButtons = false; + private String javascriptUrlRegex = JAVASCRIPT_URL_REGEX_DEFAULT; + private String cssAndFontsUrlRegex = CSS_AND_FONTS_URL_REGEX_DEFAULT; + private String multimediaUrlRegex = MULTIMEDIA_URL_REGEX_DEFAULT; + + public BreakpointsParam() { + super(); + + confirmDropMessage = false; + } + + /** + * Parses the breakpoints options. + * + *

The following options are parsed: + * + *

    + *
  • Confirm drop message. + *
+ */ + @Override + protected void parse() { + confirmDropMessage = getBoolean(PARAM_CONFIRM_DROP_MESSAGE_KEY, false); + buttonMode = getInt(PARAM_UI_BUTTON_MODE, BUTTON_MODE_SIMPLE); + alwaysOnTop = getConfig().getBoolean(PARAM_BRK_ALWAYS_ON_TOP, null); + inScopeOnly = getBoolean(PARAM_BRK_IN_SCOPE_ONLY, false); + showIgnoreFilesButtons = getBoolean(SHOW_IGNORE_REQUESTS_BUTTONS, false); + javascriptUrlRegex = getString(JAVASCRIPT_URL_REGEX, JAVASCRIPT_URL_REGEX_DEFAULT); + cssAndFontsUrlRegex = getString(CSS_AND_FONTS_URL_REGEX, CSS_AND_FONTS_URL_REGEX_DEFAULT); + multimediaUrlRegex = getString(MULTIMEDIA_URL_REGEX_DEFAULT, MULTIMEDIA_URL_REGEX_DEFAULT); + } + + /** + * Tells whether the user should confirm the drop of the trapped message. + * + * @return {@code true} if the user should confirm the drop, {@code false} otherwise + * @see #setConfirmDropMessage(boolean) + */ + public boolean isConfirmDropMessage() { + return confirmDropMessage; + } + + /** + * Sets whether the user should confirm the drop of the trapped message. + * + * @param confirmDrop {@code true} if the user should confirm the drop, {@code false} otherwise + * @see #isConfirmDropMessage() + * @see org.zaproxy.addon.brk.BreakPanelToolbarFactory#getBtnDrop() + */ + public void setConfirmDropMessage(boolean confirmDrop) { + if (confirmDropMessage != confirmDrop) { + this.confirmDropMessage = confirmDrop; + getConfig().setProperty(PARAM_CONFIRM_DROP_MESSAGE_KEY, confirmDrop); + } + } + + public int getButtonMode() { + return buttonMode; + } + + public void setButtonMode(int buttonMode) { + this.buttonMode = buttonMode; + getConfig().setProperty(PARAM_UI_BUTTON_MODE, buttonMode); + } + + public Boolean getAlwaysOnTop() { + return alwaysOnTop; + } + + public void setAlwaysOnTop(Boolean alwaysOnTop) { + this.alwaysOnTop = alwaysOnTop; + getConfig().setProperty(PARAM_BRK_ALWAYS_ON_TOP, alwaysOnTop); + } + + public boolean isInScopeOnly() { + return inScopeOnly; + } + + public void setInScopeOnly(boolean inScopeOnly) { + this.inScopeOnly = inScopeOnly; + getConfig().setProperty(PARAM_BRK_IN_SCOPE_ONLY, inScopeOnly); + } + + public boolean isShowIgnoreFilesButtons() { + return showIgnoreFilesButtons; + } + + public void setShowIgnoreFilesButtons(boolean showIgnoreFilesButtons) { + this.showIgnoreFilesButtons = showIgnoreFilesButtons; + getConfig().setProperty(SHOW_IGNORE_REQUESTS_BUTTONS, showIgnoreFilesButtons); + } + + public String getJavascriptUrlRegex() { + return javascriptUrlRegex; + } + + public void setJavascriptUrlRegex(String javascriptUrlRegex) { + this.javascriptUrlRegex = javascriptUrlRegex; + getConfig().setProperty(JAVASCRIPT_URL_REGEX, javascriptUrlRegex); + } + + public String getCssAndFontsUrlRegex() { + return cssAndFontsUrlRegex; + } + + public void setCssAndFontsUrlRegex(String cssAndFontsUrlRegex) { + this.cssAndFontsUrlRegex = cssAndFontsUrlRegex; + getConfig().setProperty(CSS_AND_FONTS_URL_REGEX, cssAndFontsUrlRegex); + } + + public String getMultimediaUrlRegex() { + return multimediaUrlRegex; + } + + public void setMultimediaUrlRegex(String multimediaUrlRegex) { + this.multimediaUrlRegex = multimediaUrlRegex; + getConfig().setProperty(MULTIMEDIA_URL_REGEX, multimediaUrlRegex); + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsTableModel.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsTableModel.java new file mode 100644 index 00000000000..467a865543c --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsTableModel.java @@ -0,0 +1,203 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.swing.table.AbstractTableModel; +import org.parosproxy.paros.Constant; + +@SuppressWarnings("serial") +public class BreakpointsTableModel extends AbstractTableModel { + + private static final long serialVersionUID = -8160051343126299124L; + + private static final int COLUMN_COUNT = 3; + + private static final String[] columnNames = { + Constant.messages.getString("brk.table.header.enabled"), + Constant.messages.getString("brk.table.header.type"), + Constant.messages.getString("brk.table.header.condition") + }; + + private List breakpoints; + private List breakpointsEnabled; + + private Map mapBreakpointRow; + + private int lastAffectedRow; + + public BreakpointsTableModel() { + super(); + + breakpoints = new ArrayList<>(0); + breakpointsEnabled = new ArrayList<>(0); + + mapBreakpointRow = new HashMap<>(); + + lastAffectedRow = -1; + } + + public List getBreakpointsList() { + return breakpoints; + } + + public List getBreakpointsEnabledList() { + return breakpointsEnabled; + } + + @Override + public int getColumnCount() { + return COLUMN_COUNT; + } + + @Override + public int getRowCount() { + return breakpoints.size(); + } + + @Override + public String getColumnName(int col) { + return columnNames[col]; + } + + @Override + public Object getValueAt(int row, int column) { + Object obj = null; + BreakpointMessageInterface breakpoint = breakpoints.get(row); + if (column == 0) { + obj = breakpoint.isEnabled(); + } else if (column == 1) { + obj = breakpoint.getType(); + } else { + obj = breakpoint.getDisplayMessage(); + } + return obj; + } + + public BreakpointMessageInterface getBreakpointAtRow(int row) { + return breakpoints.get(row); + } + + public void addBreakpoint(BreakpointMessageInterface breakpoint) { + breakpoints.add(breakpoint); + this.fireTableRowsInserted(breakpoints.size() - 1, breakpoints.size() - 1); + + rebuildMapBreakpointRow(); + lastAffectedRow = mapBreakpointRow.get(breakpoint); + + if (breakpoint.isEnabled()) { + synchronized (breakpointsEnabled) { + breakpointsEnabled.add(breakpoint); + } + } + } + + public void editBreakpoint( + BreakpointMessageInterface oldBreakpoint, BreakpointMessageInterface newBreakpoint) { + int row = mapBreakpointRow.remove(oldBreakpoint); + breakpoints.remove(row); + this.fireTableRowsDeleted(row, row); + + mapBreakpointRow.put(newBreakpoint, 0); + breakpoints.add(newBreakpoint); + this.fireTableRowsInserted(breakpoints.size() - 1, breakpoints.size() - 1); + + rebuildMapBreakpointRow(); + lastAffectedRow = mapBreakpointRow.get(newBreakpoint); + + synchronized (breakpointsEnabled) { + if (oldBreakpoint.isEnabled()) { + breakpointsEnabled.remove(oldBreakpoint); + } + if (newBreakpoint.isEnabled()) { + breakpointsEnabled.add(newBreakpoint); + } + } + } + + public void removeBreakpoint(BreakpointMessageInterface breakpoint) { + Integer row = mapBreakpointRow.remove(breakpoint); + + if (row != null) { + breakpoints.remove(breakpoint); + this.fireTableRowsDeleted(row, row); + + rebuildMapBreakpointRow(); + + synchronized (breakpointsEnabled) { + if (breakpoint.isEnabled()) { + breakpointsEnabled.remove(breakpoint); + } + } + } + } + + public int getLastAffectedRow() { + return lastAffectedRow; + } + + @Override + public boolean isCellEditable(int row, int column) { + return (column == 0); + } + + @Override + public void setValueAt(Object value, int row, int column) { + if (column == 0) { + if (value instanceof Boolean) { + boolean isEnabled = breakpoints.get(row).isEnabled(); + breakpoints.get(row).setEnabled((Boolean) value); + this.fireTableCellUpdated(row, column); + + if (isEnabled) { + synchronized (breakpointsEnabled) { + breakpointsEnabled.remove(breakpoints.get(row)); + } + } else { + synchronized (breakpointsEnabled) { + breakpointsEnabled.add(breakpoints.get(row)); + } + } + } + } + } + + @Override + public Class getColumnClass(int column) { + if (column == 0) { + return Boolean.class; + } + return String.class; + } + + private void rebuildMapBreakpointRow() { + mapBreakpointRow.clear(); + int i = 0; + for (Iterator iterator = breakpoints.iterator(); + iterator.hasNext(); + ++i) { + mapBreakpointRow.put(iterator.next(), i); + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsUiManagerInterface.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsUiManagerInterface.java new file mode 100644 index 00000000000..4c1e86a18ad --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/BreakpointsUiManagerInterface.java @@ -0,0 +1,39 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk; + +import org.zaproxy.zap.extension.httppanel.Message; + +public interface BreakpointsUiManagerInterface { + + Class getMessageClass(); + + Class getBreakpointClass(); + + String getType(); + + void handleAddBreakpoint(Message aMessage); + + void handleEditBreakpoint(BreakpointMessageInterface breakpoint); + + void handleRemoveBreakpoint(BreakpointMessageInterface breakpoint); + + void reset(); +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java new file mode 100644 index 00000000000..07a98a58374 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java @@ -0,0 +1,678 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk; + +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Consumer; +import javax.swing.JList; +import javax.swing.JTree; +import javax.swing.tree.TreePath; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.control.Control.Mode; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.parosproxy.paros.extension.ExtensionHookView; +import org.parosproxy.paros.extension.OptionsChangedListener; +import org.parosproxy.paros.extension.SessionChangedListener; +import org.parosproxy.paros.model.HistoryReference; +import org.parosproxy.paros.model.OptionsParam; +import org.parosproxy.paros.model.Session; +import org.parosproxy.paros.model.SiteNode; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointManagementDaemonImpl; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage.Location; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage.Match; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointsUiManagerInterface; +import org.zaproxy.addon.brk.impl.http.ProxyListenerBreak; +import org.zaproxy.zap.extension.help.ExtensionHelp; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.view.ZapMenuItem; + +public class ExtensionBreak extends ExtensionAdaptor + implements SessionChangedListener, OptionsChangedListener { + + public static final String NAME = "ExtensionBreak"; + + private static final Logger LOGGER = LogManager.getLogger(ExtensionBreak.class); + + public static final String BREAK_POINT_HIT_STATS = "stats.break.hit"; + public static final String BREAK_POINT_STEP_STATS = "stats.break.step"; + public static final String BREAK_POINT_DROP_STATS = "stats.break.drop"; + + private BreakPanel breakPanel = null; + private ProxyListenerBreak proxyListener = null; + + private BreakpointsPanel breakpointsPanel = null; + + private PopupMenuEditBreak popupMenuEditBreak = null; + private PopupMenuRemove popupMenuRemove = null; + + private BreakpointMessageHandler2 breakpointMessageHandler; + + private Map, BreakpointsUiManagerInterface> + mapBreakpointUiManager; + + private Map, BreakpointsUiManagerInterface> mapMessageUiManager; + + private Mode mode = Control.getSingleton().getMode(); + + private BreakpointsParam breakpointsParams; + + private BreakpointsOptionsPanel breakpointsOptionsPanel; + + private BreakpointManagementInterface breakpointManagementInterface; + private HttpBreakpointsUiManagerInterface httpBreakpoints; + + private ZapMenuItem menuBreakOnRequests = null; + private ZapMenuItem menuBreakOnResponses = null; + private ZapMenuItem menuStep = null; + private ZapMenuItem menuContinue = null; + private ZapMenuItem menuDrop = null; + private ZapMenuItem menuHttpBreakpoint = null; + + private BreakAPI api = new BreakAPI(this); + private List> serialisationRequiredListeners; + + public ExtensionBreak() { + super(NAME); + this.setOrder(24); + } + + @Override + public String getUIName() { + return Constant.messages.getString("brk.name"); + } + + @Override + public void init() { + serialisationRequiredListeners = Collections.synchronizedList(new ArrayList<>(1)); + } + + public BreakpointManagementInterface getBreakpointManagementInterface() { + return this.breakpointManagementInterface; + } + + public void addSerialisationRequiredListener(Consumer listener) { + Objects.requireNonNull(listener); + serialisationRequiredListeners.add(listener); + } + + public void removeSerialisationRequiredListener(Consumer listener) { + Objects.requireNonNull(listener); + serialisationRequiredListeners.remove(listener); + } + + List> getSerialisationRequiredListeners() { + return serialisationRequiredListeners; + } + + @Override + public void hook(ExtensionHook extensionHook) { + super.hook(extensionHook); + + extensionHook.addOptionsParamSet(getOptionsParam()); + extensionHook.addProxyListener(getProxyListenerBreak()); + extensionHook.addSessionListener(this); + extensionHook.addOptionsChangedListener(this); + + extensionHook.addApiImplementor(api); + + if (getView() != null) { + breakPanel = new BreakPanel(this, getOptionsParam()); + breakPanel.setName(Constant.messages.getString("tab.break")); + breakpointMessageHandler = new BreakpointMessageHandler2(breakPanel); + breakpointMessageHandler.setEnabledBreakpoints( + getBreakpointsModel().getBreakpointsEnabledList()); + breakpointMessageHandler.setEnabledIgnoreRules(breakPanel.getIgnoreRulesEnableList()); + breakpointManagementInterface = breakPanel; + + ExtensionHookView pv = extensionHook.getHookView(); + pv.addWorkPanel(breakPanel); + pv.addOptionPanel(getOptionsPanel()); + + extensionHook.getHookView().addStatusPanel(getBreakpointsPanel()); + + extensionHook.getHookMenu().addPopupMenuItem(getPopupMenuEdit()); + extensionHook.getHookMenu().addPopupMenuItem(getPopupMenuDelete()); + + mapBreakpointUiManager = new HashMap<>(); + mapMessageUiManager = new HashMap<>(); + + httpBreakpoints = + new HttpBreakpointsUiManagerInterface(extensionHook.getHookMenu(), this); + + addBreakpointsUiManager(httpBreakpoints); + + extensionHook.getHookMenu().addToolsMenuItem(getMenuToggleBreakOnRequests()); + extensionHook.getHookMenu().addToolsMenuItem(getMenuToggleBreakOnResponses()); + extensionHook.getHookMenu().addToolsMenuItem(getMenuStep()); + extensionHook.getHookMenu().addToolsMenuItem(getMenuContinue()); + extensionHook.getHookMenu().addToolsMenuItem(getMenuDrop()); + extensionHook.getHookMenu().addToolsMenuItem(getMenuAddHttpBreakpoint()); + + ExtensionHelp.enableHelpKey(breakPanel, "ui.tabs.break"); + ExtensionHelp.enableHelpKey(getBreakpointsPanel(), "ui.tabs.breakpoints"); + } else { + this.breakpointManagementInterface = new HttpBreakpointManagementDaemonImpl(); + + breakpointMessageHandler = new BreakpointMessageHandler2(breakpointManagementInterface); + breakpointMessageHandler.setEnabledBreakpoints(new ArrayList<>()); + breakpointMessageHandler.setEnabledIgnoreRules(new ArrayList<>()); + } + } + + private BreakpointsParam getOptionsParam() { + if (breakpointsParams == null) { + breakpointsParams = new BreakpointsParam(); + } + return breakpointsParams; + } + + private BreakpointsOptionsPanel getOptionsPanel() { + if (breakpointsOptionsPanel == null) { + breakpointsOptionsPanel = new BreakpointsOptionsPanel(); + } + return breakpointsOptionsPanel; + } + + private BreakpointsPanel getBreakpointsPanel() { + if (breakpointsPanel == null) { + breakpointsPanel = new BreakpointsPanel(this); + } + return breakpointsPanel; + } + + public void addBreakpoint(BreakpointMessageInterface breakpoint) { + this.getBreakpointsPanel().addBreakpoint(breakpoint); + // Switch to the panel for some visual feedback + this.getBreakpointsPanel().setTabFocus(); + } + + public void editBreakpoint( + BreakpointMessageInterface oldBreakpoint, BreakpointMessageInterface newBreakpoint) { + this.getBreakpointsPanel().editBreakpoint(oldBreakpoint, newBreakpoint); + } + + public void removeBreakpoint(BreakpointMessageInterface breakpoint) { + this.getBreakpointsPanel().removeBreakpoint(breakpoint); + } + + public List getBreakpointsList() { + return getBreakpointsModel().getBreakpointsList(); + } + + public BreakpointMessageInterface getUiSelectedBreakpoint() { + return getBreakpointsPanel().getSelectedBreakpoint(); + } + + public void addBreakpointsUiManager(BreakpointsUiManagerInterface uiManager) { + if (getView() == null) { + return; + } + mapBreakpointUiManager.put(uiManager.getBreakpointClass(), uiManager); + mapMessageUiManager.put(uiManager.getMessageClass(), uiManager); + } + + public void removeBreakpointsUiManager(BreakpointsUiManagerInterface uiManager) { + if (getView() == null) { + return; + } + mapBreakpointUiManager.remove(uiManager.getBreakpointClass()); + mapMessageUiManager.remove(uiManager.getMessageClass()); + } + + public void setBreakAllRequests(boolean brk) { + this.breakpointManagementInterface.setBreakAllRequests(brk); + } + + public void setBreakAllResponses(boolean brk) { + this.breakpointManagementInterface.setBreakAllResponses(brk); + } + + public void addHttpBreakpoint( + String string, String location, String match, boolean inverse, boolean ignoreCase) { + this.addBreakpoint( + new HttpBreakpointMessage( + string, + getLocationEnum(location), + getMatchEnum(match), + inverse, + ignoreCase)); + } + + private static Location getLocationEnum(String location) { + try { + return Location.valueOf(location); + } catch (Exception e) { + throw new IllegalArgumentException( + "location must be one of " + Arrays.toString(Location.values())); + } + } + + private static Match getMatchEnum(String match) { + try { + return Match.valueOf(match); + } catch (Exception e) { + throw new IllegalArgumentException( + "match must be one of " + Arrays.toString(Match.values())); + } + } + + public void removeHttpBreakpoint( + String string, String location, String match, boolean inverse, boolean ignoreCase) { + this.removeBreakpoint( + new HttpBreakpointMessage( + string, + getLocationEnum(location), + getMatchEnum(match), + inverse, + ignoreCase)); + } + + public void addUiBreakpoint(Message aMessage) { + BreakpointsUiManagerInterface uiManager = getBreakpointUiManager(aMessage.getClass()); + if (uiManager != null) { + uiManager.handleAddBreakpoint(aMessage); + } + } + + private BreakpointsUiManagerInterface getBreakpointUiManager(Class clazz) { + if (!Message.class.isAssignableFrom(clazz)) { + return null; + } + + BreakpointsUiManagerInterface uiManager = mapMessageUiManager.get(clazz); + if (uiManager == null) { + uiManager = getBreakpointUiManager(clazz.getSuperclass()); + } + + return uiManager; + } + + public void editUiSelectedBreakpoint() { + BreakpointMessageInterface breakpoint = getBreakpointsPanel().getSelectedBreakpoint(); + if (breakpoint != null) { + BreakpointsUiManagerInterface uiManager = + mapBreakpointUiManager.get(breakpoint.getClass()); + if (uiManager != null) { + uiManager.handleEditBreakpoint(breakpoint); + } + } + } + + public void removeUiSelectedBreakpoint() { + BreakpointMessageInterface breakpoint = getBreakpointsPanel().getSelectedBreakpoint(); + if (breakpoint != null) { + BreakpointsUiManagerInterface uiManager = + mapBreakpointUiManager.get(breakpoint.getClass()); + if (uiManager != null) { + uiManager.handleRemoveBreakpoint(breakpoint); + } + } + } + + private BreakpointsTableModel getBreakpointsModel() { + return (BreakpointsTableModel) this.getBreakpointsPanel().getBreakpoints().getModel(); + } + + private ProxyListenerBreak getProxyListenerBreak() { + if (proxyListener == null) { + proxyListener = new ProxyListenerBreak(getModel(), this); + } + return proxyListener; + } + + private PopupMenuEditBreak getPopupMenuEdit() { + if (popupMenuEditBreak == null) { + popupMenuEditBreak = new PopupMenuEditBreak(); + popupMenuEditBreak.setExtension(this); + } + return popupMenuEditBreak; + } + + private PopupMenuRemove getPopupMenuDelete() { + if (popupMenuRemove == null) { + popupMenuRemove = new PopupMenuRemove(); + popupMenuRemove.setExtension(this); + } + return popupMenuRemove; + } + + private ZapMenuItem getMenuToggleBreakOnRequests() { + if (menuBreakOnRequests == null) { + menuBreakOnRequests = + new ZapMenuItem( + "menu.tools.brk.req", + getView().getMenuShortcutKeyStroke(KeyEvent.VK_B, 0, false)); + menuBreakOnRequests.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (getOptionsParam().getButtonMode() + == BreakpointsParam.BUTTON_MODE_SIMPLE) { + // Single button mode - toggle break on all + breakpointManagementInterface.setBreakAll( + !breakpointManagementInterface.isBreakAll()); + } else { + // Toggle break on requests + breakpointManagementInterface.setBreakAllRequests( + !breakpointManagementInterface.isBreakRequest()); + } + } + }); + } + return menuBreakOnRequests; + } + + private ZapMenuItem getMenuToggleBreakOnResponses() { + if (menuBreakOnResponses == null) { + menuBreakOnResponses = + new ZapMenuItem( + "menu.tools.brk.resp", + getView() + .getMenuShortcutKeyStroke( + KeyEvent.VK_B, KeyEvent.ALT_DOWN_MASK, false)); + menuBreakOnResponses.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (getOptionsParam().getButtonMode() + == BreakpointsParam.BUTTON_MODE_SIMPLE) { + // Single button mode - toggle break on all + breakpointManagementInterface.setBreakAll( + !breakpointManagementInterface.isBreakAll()); + } else { + // Toggle break on Responses + breakpointManagementInterface.setBreakAllResponses( + !breakpointManagementInterface.isBreakResponse()); + } + } + }); + } + return menuBreakOnResponses; + } + + private ZapMenuItem getMenuStep() { + if (menuStep == null) { + menuStep = + new ZapMenuItem( + "menu.tools.brk.step", + getView().getMenuShortcutKeyStroke(KeyEvent.VK_S, 0, false)); + menuStep.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (breakpointManagementInterface.isHoldMessage(null)) { + // Menu currently always enabled, but dont do anything unless a + // message is being held + breakpointManagementInterface.step(); + } + } + }); + } + return menuStep; + } + + private ZapMenuItem getMenuContinue() { + if (menuContinue == null) { + menuContinue = + new ZapMenuItem( + "menu.tools.brk.cont", + getView().getMenuShortcutKeyStroke(KeyEvent.VK_C, 0, false)); + menuContinue.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (breakpointManagementInterface.isHoldMessage(null)) { + // Menu currently always enabled, but dont do anything unless a + // message is being held + breakpointManagementInterface.cont(); + } + } + }); + } + return menuContinue; + } + + private ZapMenuItem getMenuDrop() { + if (menuDrop == null) { + menuDrop = + new ZapMenuItem( + "menu.tools.brk.drop", + getView().getMenuShortcutKeyStroke(KeyEvent.VK_X, 0, false)); + menuDrop.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + if (breakpointManagementInterface.isHoldMessage(null)) { + // Menu currently always enabled, but dont do anything unless a + // message is being held + breakpointManagementInterface.drop(); + } + } + }); + } + return menuDrop; + } + + private ZapMenuItem getMenuAddHttpBreakpoint() { + if (menuHttpBreakpoint == null) { + menuHttpBreakpoint = + new ZapMenuItem( + "menu.tools.brk.custom", + getView().getMenuShortcutKeyStroke(KeyEvent.VK_A, 0, false)); + menuHttpBreakpoint.addActionListener( + new java.awt.event.ActionListener() { + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + // Check to see if anything is selected in the main tabs + String url = ""; + Component c = getView().getMainFrame().getFocusOwner(); + if (c != null) { + if (c instanceof JList) { + // Handles the history list and similar + @SuppressWarnings("rawtypes") + Object sel = ((JList) c).getSelectedValue(); + try { + if (sel != null + && sel instanceof HistoryReference + && ((HistoryReference) sel).getURI() != null) { + url = ((HistoryReference) sel).getURI().toString(); + } + } catch (Exception e1) { + // Ignore + } + } else if (c instanceof JTree) { + // Handles the Sites tree + TreePath path = ((JTree) c).getSelectionPath(); + try { + if (path != null + && path.getLastPathComponent() + instanceof SiteNode) { + url = + ((SiteNode) path.getLastPathComponent()) + .getHistoryReference() + .getURI() + .toString(); + } + } catch (Exception e1) { + // Ignore + } + } + } + httpBreakpoints.handleAddBreakpoint(url); + } + }); + } + return menuHttpBreakpoint; + } + + @Override + public String getAuthor() { + return Constant.ZAP_TEAM; + } + + @Override + public String getDescription() { + return Constant.messages.getString("brk.desc"); + } + + @Override + public void sessionAboutToChange(final Session session) { + if (EventQueue.isDispatchThread()) { + sessionAboutToChange(); + } else { + try { + EventQueue.invokeAndWait( + new Runnable() { + @Override + public void run() { + sessionAboutToChange(); + } + }); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + } + + @Override + public void sessionChanged(Session session) { + if (getView() == null) { + return; + } + breakpointManagementInterface.init(); + } + + private void sessionAboutToChange() { + if (getView() == null) { + return; + } + breakpointManagementInterface.reset(); + } + + @Override + public void sessionScopeChanged(Session session) {} + + @Override + public void destroy() { + if (breakPanel != null) { + breakPanel.savePanels(); + } + } + + public boolean messageReceivedFromClient(Message aMessage) { + if (mode.equals(Mode.safe)) { + return true; + } + return breakpointMessageHandler.handleMessageReceivedFromClient( + aMessage, mode.equals(Mode.protect)); + } + + public boolean messageReceivedFromServer(Message aMessage) { + if (mode.equals(Mode.safe)) { + return true; + } + return breakpointMessageHandler.handleMessageReceivedFromServer( + aMessage, mode.equals(Mode.protect)); + } + + /** + * Exposes list of enabled breakpoints. + * + * @return list of enabled breakpoints + */ + public List getBreakpointsEnabledList() { + if (mode.equals(Mode.safe)) { + return new ArrayList<>(); + } + return getBreakpointsModel().getBreakpointsEnabledList(); + } + + @Override + public void sessionModeChanged(Mode mode) { + this.mode = mode; + if (getView() == null) { + return; + } + this.breakpointManagementInterface.sessionModeChanged(mode); + } + + public void setBreakOnId(String id, boolean enable) { + LOGGER.debug("setBreakOnId {} {}", id, enable); + if (enable) { + breakpointMessageHandler.getEnabledKeyBreakpoints().add(id); + } else { + breakpointMessageHandler.getEnabledKeyBreakpoints().remove(id); + } + } + + @Override + public void optionsChanged(OptionsParam optionsParam) { + applyViewOptions(optionsParam); + } + + /** + * Applies the given (view) options to the break components, by setting the location of the + * break buttons and the break buttons mode. + * + *

The call to this method has no effect if there's no view. + * + * @param options the current options + */ + private void applyViewOptions(OptionsParam options) { + if (getView() == null) { + return; + } + + breakPanel.setButtonsLocation(options.getViewParam().getBrkPanelViewOption()); + breakPanel.setButtonMode(options.getParamSet(BreakpointsParam.class).getButtonMode()); + breakPanel.setShowIgnoreFilesButtons( + options.getParamSet(BreakpointsParam.class).isShowIgnoreFilesButtons()); + breakPanel.updateIgnoreFileTypesRegexs(); + } + + @Override + public void optionsLoaded() { + applyViewOptions(getModel().getOptionsParam()); + } + + public boolean isInScopeOnly() { + return this.getOptionsParam().isInScopeOnly(); + } + + @Override + /** No database tables used, so all supported */ + public boolean supportsDb(String type) { + return true; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuEditBreak.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuEditBreak.java new file mode 100644 index 00000000000..f8e9e543027 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuEditBreak.java @@ -0,0 +1,56 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk; + +import java.awt.Component; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.ExtensionPopupMenuItem; + +@SuppressWarnings("serial") +public class PopupMenuEditBreak extends ExtensionPopupMenuItem { + + private static final long serialVersionUID = 1L; + + private ExtensionBreak extension; + + public PopupMenuEditBreak() { + super(Constant.messages.getString("brk.edit.popup")); + this.addActionListener( + new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + extension.editUiSelectedBreakpoint(); + } + }); + } + + public void setExtension(ExtensionBreak extension) { + this.extension = extension; + } + + @Override + public boolean isEnableForComponent(Component invoker) { + if (invoker.getName() != null && invoker.getName().equals(BreakpointsPanel.PANEL_NAME)) { + return true; + } + return false; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuRemove.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuRemove.java new file mode 100644 index 00000000000..598757da6e8 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/PopupMenuRemove.java @@ -0,0 +1,57 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk; + +import java.awt.Component; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.extension.ExtensionPopupMenuItem; + +@SuppressWarnings("serial") +public class PopupMenuRemove extends ExtensionPopupMenuItem { + + private static final long serialVersionUID = 1L; + private ExtensionBreak extension = null; + + public PopupMenuRemove() { + super(Constant.messages.getString("brk.remove.popup")); + + this.addActionListener( + new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent e) { + extension.removeUiSelectedBreakpoint(); + } + }); + } + + @Override + public boolean isEnableForComponent(Component invoker) { + if (invoker.getName() != null && invoker.getName().equals(BreakpointsPanel.PANEL_NAME)) { + this.setEnabled(true); + return true; + } + return false; + } + + void setExtension(ExtensionBreak extension) { + this.extension = extension; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/BreakAddEditDialog.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/BreakAddEditDialog.java new file mode 100644 index 00000000000..c760695971b --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/BreakAddEditDialog.java @@ -0,0 +1,166 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2013 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.addon.brk.impl.http; + +import java.awt.Dimension; +import java.awt.Frame; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import org.parosproxy.paros.Constant; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage.Location; +import org.zaproxy.addon.brk.impl.http.HttpBreakpointMessage.Match; +import org.zaproxy.zap.view.StandardFieldsDialog; + +@SuppressWarnings("serial") +public class BreakAddEditDialog extends StandardFieldsDialog { + + private static final String FIELD_LOCATION = "brk.brkpoint.location.label"; + private static final String FIELD_MATCH = "brk.brkpoint.match.label"; + private static final String FIELD_STRING = "brk.brkpoint.string.label"; + private static final String FIELD_INVERSE = "brk.brkpoint.inverse.label"; + private static final String FIELD_IGNORECASE = "brk.brkpoint.ignorecase.label"; + + private static final long serialVersionUID = 1L; + + private HttpBreakpointsUiManagerInterface breakPointsManager; + private boolean add = false; + private HttpBreakpointMessage breakpoint; + + public BreakAddEditDialog( + HttpBreakpointsUiManagerInterface breakPointsManager, Frame owner, Dimension dim) { + super(owner, "brk.brkpoint.add.title", dim, true); + this.breakPointsManager = breakPointsManager; + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + public void init(HttpBreakpointMessage breakpoint, boolean add) { + this.add = add; + this.breakpoint = breakpoint; + + this.removeAllFields(); + + if (add) { + this.setTitle(Constant.messages.getString("brk.brkpoint.add.title")); + } else { + this.setTitle(Constant.messages.getString("brk.brkpoint.edit.title")); + } + + this.addComboField(FIELD_LOCATION, getLocations(), this.locToStr(breakpoint.getLocation())); + this.addComboField(FIELD_MATCH, getMatches(), this.matchToStr(breakpoint.getMatch())); + this.addTextField(FIELD_STRING, breakpoint.getString()); + this.addCheckBoxField(FIELD_INVERSE, breakpoint.isInverse()); + this.addCheckBoxField(FIELD_IGNORECASE, breakpoint.isIgnoreCase()); + + this.addPadding(); + } + + private List getLocations() { + ArrayList list = new ArrayList<>(); + for (Location loc : HttpBreakpointMessage.Location.values()) { + list.add(this.locToStr(loc)); + } + return list; + } + + private String locToStr(Location loc) { + return Constant.messages.getString("brk.brkpoint.location." + loc.name()); + } + + private Location strToLoc(String str) { + for (Location loc : HttpBreakpointMessage.Location.values()) { + if (this.locToStr(loc).equals(str)) { + return loc; + } + } + return null; + } + + private List getMatches() { + ArrayList list = new ArrayList<>(); + for (Match match : HttpBreakpointMessage.Match.values()) { + list.add(this.matchToStr(match)); + } + return list; + } + + private String matchToStr(Match match) { + return Constant.messages.getString("brk.brkpoint.match." + match.name()); + } + + private Match strToMatch(String str) { + for (Match match : HttpBreakpointMessage.Match.values()) { + if (this.matchToStr(match).equals(str)) { + return match; + } + } + return null; + } + + @Override + public void save() { + HttpBreakpointMessage brk = + new HttpBreakpointMessage( + this.getStringValue(FIELD_STRING), + this.strToLoc(this.getStringValue(FIELD_LOCATION)), + this.strToMatch(this.getStringValue(FIELD_MATCH)), + this.getBoolValue(FIELD_INVERSE), + this.getBoolValue(FIELD_IGNORECASE)); + + if (add) { + breakPointsManager.addBreakpoint(brk); + dispose(); + } else { + breakPointsManager.editBreakpoint(breakpoint, brk); + breakpoint = null; + dispose(); + } + } + + @Override + public String validateFields() { + if (this.isEmptyField(FIELD_STRING)) { + return Constant.messages.getString("brk.brkpoint.error.nostr"); + } + if (Match.regex.equals(this.strToMatch(this.getStringValue(FIELD_MATCH)))) { + try { + Pattern.compile(this.getStringValue(FIELD_STRING)); + } catch (Exception e) { + return Constant.messages.getString("brk.brkpoint.error.regex"); + } + } + if (this.getStringValue(FIELD_STRING).contains("#") + && Location.url.equals(this.strToLoc(this.getStringValue(FIELD_LOCATION))) + && Match.contains.equals(this.strToMatch(this.getStringValue(FIELD_MATCH)))) { + return Constant.messages.getString("brk.brkpoint.warn.urlfragment"); + } + return null; + } + + @Override + public void cancelPressed() { + dispose(); + } + + @Override + public String getHelpIndex() { + return "ui.dialogs.addbreak"; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImpl.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImpl.java new file mode 100644 index 00000000000..064f6497a8b --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImpl.java @@ -0,0 +1,219 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2016 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.addon.brk.impl.http; + +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.control.Control.Mode; +import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.addon.brk.BreakpointManagementInterface; +import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.utils.Stats; + +public class HttpBreakpointManagementDaemonImpl implements BreakpointManagementInterface { + + private boolean breakRequest; + private boolean breakResponse; + private boolean request; + private HttpMessage msg; + private boolean step; + private boolean stepping; + private boolean drop; + + @Override + public boolean isBreakRequest() { + return breakRequest; + } + + @Override + public boolean isBreakResponse() { + return breakResponse; + } + + @Override + public boolean isBreakAll() { + return (breakRequest && breakResponse); + } + + @Override + public void breakpointHit() { + // Ignore + } + + @Override + public boolean isHoldMessage(Message aMessage) { + if (step) { + step = false; + return false; + } + if (stepping) { + return true; + } + if (drop) { + return false; + } + if (aMessage instanceof HttpMessage) { + HttpMessage msg = (HttpMessage) aMessage; + if (msg.getResponseHeader().isEmpty()) { + // Its a request + if (this.isBreakRequest()) { + return true; + } + } else if (this.isBreakResponse()) { + return true; + } + } + return false; + } + + @Override + public boolean isStepping() { + return stepping; + } + + @Override + public boolean isToBeDropped() { + if (drop) { + drop = false; + return true; + } + return false; + } + + @Override + public void setMessage(Message msg, boolean isRequest) { + if (msg instanceof HttpMessage) { + switch (Control.getSingleton().getMode()) { + case safe: + throw new IllegalStateException("Not allowed in safe mode"); + case protect: + if (!msg.isInScope()) { + throw new IllegalStateException( + "Not allowed in protected mode for out of scope message"); + } + break; + case standard: + break; + case attack: + break; + } + HttpMessage httpMsg = (HttpMessage) msg; + if (this.msg == null) { + this.msg = httpMsg; + this.request = isRequest; + } else { + if (isRequest) { + this.msg.setRequestHeader(httpMsg.getRequestHeader()); + this.msg.setRequestBody(httpMsg.getRequestBody()); + } else { + this.msg.setResponseHeader(httpMsg.getResponseHeader()); + this.msg.setResponseBody(httpMsg.getResponseBody()); + } + } + } else { + throw new IllegalArgumentException("Not an HttpMessage"); + } + } + + @Override + public boolean isRequest() { + return this.request; + } + + @Override + public Message getMessage() { + return this.msg; + } + + @Override + public void saveMessage(boolean isRequest) { + // Ignore + } + + @Override + public void clearAndDisableRequest() { + this.msg = null; + } + + @Override + public void clearAndDisableResponse() { + this.msg = null; + } + + @Override + public void init() {} + + @Override + public void reset() { + // Ignore + } + + @Override + public void sessionModeChanged(Mode mode) { + breakRequest = false; + breakResponse = false; + msg = null; + step = false; + stepping = false; + drop = false; + } + + @Override + public void setBreakAllRequests(boolean brk) { + this.breakRequest = brk; + } + + @Override + public void setBreakAllResponses(boolean brk) { + this.breakResponse = brk; + } + + @Override + public void setBreakAll(boolean brk) { + this.setBreakAllRequests(brk); + this.setBreakAllResponses(brk); + } + + @Override + public void step() { + this.step = true; + this.stepping = true; + Stats.incCounter(ExtensionBreak.BREAK_POINT_STEP_STATS); + } + + @Override + public void cont() { + this.setBreakAllRequests(false); + this.setBreakAllResponses(false); + this.step = false; + this.stepping = false; + } + + @Override + public void drop() { + this.drop = true; + Stats.incCounter(ExtensionBreak.BREAK_POINT_DROP_STATS); + } + + @Override + public void breakpointDisplayed() { + // Ignore + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointMessage.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointMessage.java new file mode 100644 index 00000000000..cf9299d7fc6 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointMessage.java @@ -0,0 +1,252 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk.impl.http; + +import java.util.regex.Pattern; +import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.addon.brk.AbstractBreakPointMessage; +import org.zaproxy.zap.extension.httppanel.Message; + +public class HttpBreakpointMessage extends AbstractBreakPointMessage { + + public enum Location { + url, + request_header, + request_body, + response_header, + response_body + } + + public enum Match { + contains, + regex + } + + private static final Logger LOGGER = LogManager.getLogger(HttpBreakpointMessage.class); + + private static final String TYPE = "HTTP"; + + private String string; + private Pattern pattern; + private Location location; + private Match match; + private boolean inverse; + private boolean ignoreCase; + + public HttpBreakpointMessage( + String string, Location location, Match match, boolean inverse, boolean ignoreCase) { + super(); + this.string = string; + this.location = location; + this.match = match; + this.inverse = inverse; + this.ignoreCase = ignoreCase; + + compilePattern(); + } + + @Override + public String getType() { + return TYPE; + } + + public String getString() { + return string; + } + + public void setString(String str) { + this.string = str; + compilePattern(); + } + + public Pattern getPattern() { + return pattern; + } + + public void setPattern(Pattern pattern) { + this.pattern = pattern; + } + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } + + public Match getMatch() { + return match; + } + + public void setMatch(Match match) { + this.match = match; + compilePattern(); + } + + public boolean isInverse() { + return inverse; + } + + public void setInverse(boolean inverse) { + this.inverse = inverse; + } + + public boolean isIgnoreCase() { + return ignoreCase; + } + + public void setIgnoreCase(boolean ignoreCase) { + this.ignoreCase = ignoreCase; + compilePattern(); + } + + @Override + public boolean match(Message aMessage, boolean isRequest, boolean onlyIfInScope) { + if (aMessage instanceof HttpMessage) { + HttpMessage message = (HttpMessage) aMessage; + + try { + String uri = message.getRequestHeader().getURI().toString(); + + if (onlyIfInScope) { + if (!Model.getSingleton().getSession().isInScope(uri)) { + return false; + } + } + + String src; + switch (location) { + default: + case url: + src = uri; + break; + case request_header: + if (!isRequest) { + return false; + } + src = message.getRequestHeader().toString(); + break; + case request_body: + if (!isRequest) { + return false; + } + src = message.getRequestBody().toString(); + break; + case response_header: + if (isRequest) { + return false; + } + src = message.getResponseHeader().toString(); + break; + case response_body: + if (isRequest) { + return false; + } + src = message.getResponseBody().toString(); + break; + } + + boolean res; + if (Match.contains.equals(this.match)) { + if (ignoreCase) { + res = src.toLowerCase().contains(string.toLowerCase()); + } else { + res = src.contains(string); + } + + } else { + res = pattern.matcher(src).find(); + } + + if (inverse) { + return !res; + } else { + return res; + } + + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + } + + return false; + } + + private void compilePattern() { + try { + if (ignoreCase) { + pattern = Pattern.compile(string, Pattern.CASE_INSENSITIVE); + } else { + pattern = Pattern.compile(string); + } + } catch (Exception e) { + // This wont be a problem if its a 'contains' match + LOGGER.debug("Potentially invalid regex", e); + } + } + + @Override + public String getDisplayMessage() { + return Constant.messages.getString("brk.brkpoint.location." + location.name()) + + ": " + + Constant.messages.getString("brk.brkpoint.match." + match.name()) + + ": " + + (ignoreCase ? Constant.messages.getString("brk.brkpoint.ignorecase.label") : "") + + (inverse ? Constant.messages.getString("brk.brkpoint.inverse.label") : "") + + string; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (obj == this) { + return true; + } + if (!(obj instanceof HttpBreakpointMessage)) { + return false; + } + HttpBreakpointMessage hbm = (HttpBreakpointMessage) obj; + return this.getString().equals(hbm.getString()) + && this.getLocation().equals(hbm.getLocation()) + && this.getMatch().equals(hbm.getMatch()) + && this.isIgnoreCase() == hbm.isIgnoreCase() + && this.isInverse() == hbm.isInverse(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(349, 631) + . // two 'randomly' chosen prime numbers + append(string) + .append(location) + .append(match) + .append(ignoreCase) + .append(inverse) + .toHashCode(); + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointsUiManagerInterface.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointsUiManagerInterface.java new file mode 100644 index 00000000000..96a56fe7a9e --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointsUiManagerInterface.java @@ -0,0 +1,162 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk.impl.http; + +import java.awt.Dimension; +import org.parosproxy.paros.db.DatabaseException; +import org.parosproxy.paros.extension.ExtensionHookMenu; +import org.parosproxy.paros.network.HttpMessage; +import org.parosproxy.paros.view.View; +import org.zaproxy.addon.brk.BreakpointMessageInterface; +import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; +import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.httppanel.Message; +import org.zaproxy.zap.model.StructuralSiteNode; + +public class HttpBreakpointsUiManagerInterface implements BreakpointsUiManagerInterface { + + private BreakAddEditDialog breakDialog = null; + + private ExtensionBreak extensionBreak; + + private PopupMenuAddBreakSites popupMenuAddBreakSites = null; + private PopupMenuAddBreakHistory popupMenuAddBreakHistory = null; + + public HttpBreakpointsUiManagerInterface( + ExtensionHookMenu hookMenu, ExtensionBreak extensionBreak) { + this.extensionBreak = extensionBreak; + + hookMenu.addPopupMenuItem(getPopupMenuAddBreakSites()); + hookMenu.addPopupMenuItem(getPopupMenuAddBreakHistory()); + } + + @Override + public Class getMessageClass() { + return HttpMessage.class; + } + + @Override + public Class getBreakpointClass() { + return HttpBreakpointMessage.class; + } + + @Override + public String getType() { + return "HTTP"; + } + + @Override + public void handleAddBreakpoint(Message aMessage) { + showAddDialog(aMessage); + } + + public void handleAddBreakpoint(String url) { + showAddDialog(url, HttpBreakpointMessage.Match.regex); + } + + void addBreakpoint(HttpBreakpointMessage breakpoint) { + extensionBreak.addBreakpoint(breakpoint); + } + + @Override + public void handleEditBreakpoint(BreakpointMessageInterface breakpoint) { + showEditDialog((HttpBreakpointMessage) breakpoint); + } + + void editBreakpoint( + BreakpointMessageInterface oldBreakpoint, BreakpointMessageInterface newBreakpoint) { + extensionBreak.editBreakpoint(oldBreakpoint, newBreakpoint); + } + + @Override + public void handleRemoveBreakpoint(BreakpointMessageInterface breakpoint) { + extensionBreak.removeBreakpoint(breakpoint); + } + + @Override + public void reset() {} + + private void populateAddDialogAndSetVisible(String url, HttpBreakpointMessage.Match match) { + breakDialog.init( + new HttpBreakpointMessage( + url, HttpBreakpointMessage.Location.url, match, false, true), + true); + breakDialog.setVisible(true); + } + + private void showAddDialog(Message aMessage) { + HttpBreakpointMessage.Match match = HttpBreakpointMessage.Match.regex; + HttpMessage msg = (HttpMessage) aMessage; + String regex = ""; + + if (msg.getHistoryRef() != null && msg.getHistoryRef().getSiteNode() != null) { + try { + regex = + new StructuralSiteNode(msg.getHistoryRef().getSiteNode()) + .getRegexPattern(false); + } catch (DatabaseException e) { + // Ignore + } + } + if (regex.length() == 0 && msg.getRequestHeader().getURI() != null) { + // Just use the escaped url + regex = msg.getRequestHeader().getURI().toString(); + match = HttpBreakpointMessage.Match.contains; + } + this.showAddDialog(regex, match); + } + + private void showAddDialog(String url, HttpBreakpointMessage.Match match) { + if (breakDialog == null) { + breakDialog = + new BreakAddEditDialog( + this, View.getSingleton().getMainFrame(), new Dimension(407, 255)); + } + populateAddDialogAndSetVisible(url, match); + } + + private void populateEditDialogAndSetVisible(HttpBreakpointMessage breakpoint) { + breakDialog.init(breakpoint, false); + breakDialog.setVisible(true); + } + + private void showEditDialog(HttpBreakpointMessage breakpoint) { + if (breakDialog == null) { + breakDialog = + new BreakAddEditDialog( + this, View.getSingleton().getMainFrame(), new Dimension(407, 255)); + } + populateEditDialogAndSetVisible(breakpoint); + } + + private PopupMenuAddBreakSites getPopupMenuAddBreakSites() { + if (popupMenuAddBreakSites == null) { + popupMenuAddBreakSites = new PopupMenuAddBreakSites(this); + } + return popupMenuAddBreakSites; + } + + private PopupMenuAddBreakHistory getPopupMenuAddBreakHistory() { + if (popupMenuAddBreakHistory == null) { + popupMenuAddBreakHistory = new PopupMenuAddBreakHistory(extensionBreak); + } + return popupMenuAddBreakHistory; + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakHistory.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakHistory.java new file mode 100644 index 00000000000..e791c598c1b --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakHistory.java @@ -0,0 +1,63 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk.impl.http; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.db.DatabaseException; +import org.parosproxy.paros.model.HistoryReference; +import org.parosproxy.paros.network.HttpMalformedHeaderException; +import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.view.messagecontainer.http.HttpMessageContainer; +import org.zaproxy.zap.view.popup.PopupMenuItemHistoryReferenceContainer; + +@SuppressWarnings("serial") +public class PopupMenuAddBreakHistory extends PopupMenuItemHistoryReferenceContainer { + + private static final long serialVersionUID = -1984801437717248474L; + + private static final Logger LOGGER = LogManager.getLogger(PopupMenuAddBreakHistory.class); + + private final ExtensionBreak extension; + + public PopupMenuAddBreakHistory(ExtensionBreak extension) { + super(Constant.messages.getString("brk.add.popup")); + + this.extension = extension; + } + + @Override + public boolean isEnableForInvoker(Invoker invoker, HttpMessageContainer httpMessageContainer) { + return (invoker == Invoker.HISTORY_PANEL); + } + + @Override + public void performAction(HistoryReference href) { + try { + extension.addUiBreakpoint(href.getHttpMessage()); + } catch (HttpMalformedHeaderException | DatabaseException e) { + LOGGER.error(e.getMessage(), e); + extension + .getView() + .showWarningDialog(Constant.messages.getString("brk.add.error.history")); + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakSites.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakSites.java new file mode 100644 index 00000000000..73502af3167 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/PopupMenuAddBreakSites.java @@ -0,0 +1,55 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2010 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.addon.brk.impl.http; + +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.db.DatabaseException; +import org.parosproxy.paros.model.SiteNode; +import org.zaproxy.zap.model.StructuralSiteNode; +import org.zaproxy.zap.view.messagecontainer.http.HttpMessageContainer; +import org.zaproxy.zap.view.popup.PopupMenuItemSiteNodeContainer; + +@SuppressWarnings("serial") +public class PopupMenuAddBreakSites extends PopupMenuItemSiteNodeContainer { + + private static final long serialVersionUID = -7635703590177283587L; + + private HttpBreakpointsUiManagerInterface uiManager; + + public PopupMenuAddBreakSites(HttpBreakpointsUiManagerInterface uiManager) { + super(Constant.messages.getString("brk.add.popup")); + + this.uiManager = uiManager; + } + + @Override + public boolean isEnableForInvoker(Invoker invoker, HttpMessageContainer httpMessageContainer) { + return (invoker == Invoker.SITES_PANEL); + } + + @Override + public void performAction(SiteNode sn) { + try { + uiManager.handleAddBreakpoint(new StructuralSiteNode(sn).getRegexPattern(false)); + } catch (DatabaseException e) { + // Ignore + } + } +} diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/ProxyListenerBreak.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/ProxyListenerBreak.java new file mode 100644 index 00000000000..cb60af929d0 --- /dev/null +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/impl/http/ProxyListenerBreak.java @@ -0,0 +1,99 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2012 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.addon.brk.impl.http; + +import org.parosproxy.paros.core.proxy.ProxyListener; +import org.parosproxy.paros.extension.history.ProxyListenerLog; +import org.parosproxy.paros.model.Model; +import org.parosproxy.paros.model.Session; +import org.parosproxy.paros.network.HttpHeader; +import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.addon.brk.ExtensionBreak; + +public class ProxyListenerBreak implements ProxyListener { + + // Should be the last one before the listener that saves the HttpMessage to + // the DB, this way the HttpMessage will be correctly shown to the user (to + // edit it) because it could have been changed by other ProxyListener. + public static final int PROXY_LISTENER_ORDER = ProxyListenerLog.PROXY_LISTENER_ORDER - 1; + + private Model model = null; + private ExtensionBreak extension = null; + + public ProxyListenerBreak(Model model, ExtensionBreak extension) { + this.model = model; + this.extension = extension; + } + + @Override + public int getArrangeableListenerOrder() { + return PROXY_LISTENER_ORDER; + } + + @Override + public boolean onHttpRequestSend(HttpMessage msg) { + if (isSkipImage(msg.getRequestHeader())) { + return true; + } + + if (extension.isInScopeOnly()) { + // Cant use msg,isInScope() as it wont have been initialised + Session session = Model.getSingleton().getSession(); + if (!session.isInScope(msg.getRequestHeader().getURI().toString())) { + return true; + } + } + + if (extension.messageReceivedFromClient(msg)) { + return true; + } + + return false; + } + + @Override + public boolean onHttpResponseReceive(HttpMessage msg) { + if (isSkipImage(msg.getRequestHeader()) || isSkipImage(msg.getResponseHeader())) { + return true; + } + + if (extension.isInScopeOnly()) { + // Cant use msg,isInScope() as it wont have been initialised + Session session = Model.getSingleton().getSession(); + if (!session.isInScope(msg.getRequestHeader().getURI().toString())) { + return true; + } + } + + if (extension.messageReceivedFromServer(msg)) { + return true; + } + + return false; + } + + private boolean isSkipImage(HttpHeader header) { + if (header.isImage() && !model.getOptionsParam().getViewParam().isProcessImages()) { + return true; + } + + return false; + } +} diff --git a/addOns/brk/src/test/java/org/zaproxy/addon/brk/BreakpointMessageHandler2UnitTest.java b/addOns/brk/src/test/java/org/zaproxy/addon/brk/BreakpointMessageHandler2UnitTest.java new file mode 100644 index 00000000000..6df58089725 --- /dev/null +++ b/addOns/brk/src/test/java/org/zaproxy/addon/brk/BreakpointMessageHandler2UnitTest.java @@ -0,0 +1,259 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2020 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.addon.brk; + +import static java.util.Arrays.asList; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.zaproxy.zap.extension.httppanel.Message; + +/** Unit test for {@link BreakpointMessageHandler2}. */ +class BreakpointMessageHandler2UnitTest { + + private BreakpointManagementInterface breakpointManagementInterface; + + private BreakpointMessageHandler2 breakpointMessageHandler; + + @BeforeEach + void setup() { + breakpointManagementInterface = mock(BreakpointManagementInterface.class); + breakpointMessageHandler = new BreakpointMessageHandler2(breakpointManagementInterface); + breakpointMessageHandler.setEnabledBreakpoints(Collections.emptyList()); + breakpointMessageHandler.setEnabledIgnoreRules(Collections.emptyList()); + } + + @ParameterizedTest + @MethodSource("requestAndOnlyIfInScope") + void shouldBeBreakpointIfMessageForceIntercept(boolean request, boolean onlyIfInScope) { + // Given + Message message = mock(Message.class); + given(message.isForceIntercept()).willReturn(true); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, onlyIfInScope); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldNotBeBreakpointIfIgnoreRuleMatch(boolean request) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(true); + given(breakpointManagementInterface.isBreakRequest()).willReturn(true); + given(breakpointManagementInterface.isBreakResponse()).willReturn(true); + + BreakpointMessageInterface skipBreakpoint = mock(BreakpointMessageInterface.class); + given(skipBreakpoint.isEnabled()).willReturn(true); + given(skipBreakpoint.match(message, request, false)).willReturn(true); + List ignoreRules = Arrays.asList(skipBreakpoint); + breakpointMessageHandler.setEnabledIgnoreRules(ignoreRules); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldBeBreakpointIfIgnoreRulesDoNotMatch(boolean request) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(true); + given(breakpointManagementInterface.isBreakRequest()).willReturn(true); + given(breakpointManagementInterface.isBreakResponse()).willReturn(true); + + BreakpointMessageInterface skipBreakpoint = mock(BreakpointMessageInterface.class); + given(skipBreakpoint.isEnabled()).willReturn(true); + given(skipBreakpoint.match(message, request, false)).willReturn(false); + List ignoreRules = Arrays.asList(skipBreakpoint); + breakpointMessageHandler.setEnabledIgnoreRules(ignoreRules); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldBeBreakpointIfIgnoreRulesMatchButNotEnable(boolean request) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(true); + given(breakpointManagementInterface.isBreakRequest()).willReturn(true); + given(breakpointManagementInterface.isBreakResponse()).willReturn(true); + + BreakpointMessageInterface skipBreakpoint = mock(BreakpointMessageInterface.class); + given(skipBreakpoint.isEnabled()).willReturn(false); + given(skipBreakpoint.match(message, request, false)).willReturn(true); + List ignoreRules = Arrays.asList(skipBreakpoint); + breakpointMessageHandler.setEnabledIgnoreRules(ignoreRules); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldNotFailWithoutIgnoreRules(boolean request) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(false); + boolean onlyIfInScope = true; + breakpointMessageHandler.setEnabledIgnoreRules(null); + // When + boolean breakpoint = + assertDoesNotThrow( + () -> + breakpointMessageHandler.isBreakpoint( + message, request, onlyIfInScope)); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldNotBeBreakpointIfMessageNotInScopeWithOnlyIfInScope(boolean request) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(false); + boolean onlyIfInScope = true; + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, onlyIfInScope); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @Test + void shouldBeBreakpointIfRequestAndBreakingOnAllRequests() { + // Given + Message message = mock(Message.class); + given(breakpointManagementInterface.isBreakRequest()).willReturn(true); + boolean request = true; + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @Test + void shouldNotBeBreakpointIfNotRequestAndBreakingOnAllRequests() { + // Given + Message message = mock(Message.class); + given(breakpointManagementInterface.isBreakRequest()).willReturn(true); + boolean request = false; + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @Test + void shouldBeBreakpointIfResponseAndBreakingOnAllResponses() { + // Given + Message message = mock(Message.class); + given(breakpointManagementInterface.isBreakResponse()).willReturn(true); + boolean request = false; + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @Test + void shouldNotBeBreakpointIfNotResponseAndBreakingOnAllResponses() { + // Given + Message message = mock(Message.class); + given(breakpointManagementInterface.isBreakResponse()).willReturn(true); + boolean request = true; + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @ParameterizedTest + @ValueSource(strings = {"true", "false"}) + void shouldBeBreakpointIfStepping(boolean request) { + // Given + Message message = mock(Message.class); + given(breakpointManagementInterface.isStepping()).willReturn(true); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, false); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + @ParameterizedTest + @MethodSource("requestAndOnlyIfInScope") + void shouldNotBeBreakpointIfBreakpointNotHit(boolean request, boolean onlyIfInScope) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(onlyIfInScope); + BreakpointMessageInterface breakpointMessage = mock(BreakpointMessageInterface.class); + given(breakpointMessage.match(message, request, onlyIfInScope)).willReturn(false); + breakpointMessageHandler.setEnabledBreakpoints(asList(breakpointMessage)); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, onlyIfInScope); + // Then + assertThat(breakpoint, is(equalTo(false))); + } + + @ParameterizedTest + @MethodSource("requestAndOnlyIfInScope") + void shouldBeBreakpointIfAtLeastOneBreakpointHit(boolean request, boolean onlyIfInScope) { + // Given + Message message = mock(Message.class); + given(message.isInScope()).willReturn(onlyIfInScope); + BreakpointMessageInterface breakpointMessage = mock(BreakpointMessageInterface.class); + given(breakpointMessage.match(message, request, onlyIfInScope)).willReturn(true); + breakpointMessageHandler.setEnabledBreakpoints( + asList(mock(BreakpointMessageInterface.class), breakpointMessage)); + // When + boolean breakpoint = breakpointMessageHandler.isBreakpoint(message, request, onlyIfInScope); + // Then + assertThat(breakpoint, is(equalTo(true))); + } + + static Stream requestAndOnlyIfInScope() { + return Stream.of( + arguments(true, true), + arguments(true, false), + arguments(false, false), + arguments(false, true)); + } +} diff --git a/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java b/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java new file mode 100644 index 00000000000..a0a9c6e24de --- /dev/null +++ b/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java @@ -0,0 +1,149 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2016 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.addon.brk.impl.http; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.parosproxy.paros.network.HttpHeader; +import org.parosproxy.paros.network.HttpMalformedHeaderException; +import org.parosproxy.paros.network.HttpMessage; +import org.parosproxy.paros.network.HttpResponseHeader; +import org.zaproxy.zap.WithConfigsTest; + +class HttpBreakpointManagementDaemonImplUnitTest extends WithConfigsTest { + + private static String OK_RESPONSE = + "HTTP/1.1 200 OK" + + HttpHeader.CRLF + + "Connection: close" + + HttpHeader.CRLF + + HttpHeader.CRLF; + + private HttpBreakpointManagementDaemonImpl impl; + + @BeforeEach + void setUp() throws Exception { + impl = new HttpBreakpointManagementDaemonImpl(); + } + + @Test + void shouldInitBreakPointsToFalseOnInit() { + assertFalse(impl.isBreakAll()); + assertFalse(impl.isBreakRequest()); + assertFalse(impl.isBreakResponse()); + } + + @Test + void shouldBreakOnAllHttpRequestsAndResponses() throws HttpMalformedHeaderException { + impl.setBreakAll(true); + HttpMessage msg = new HttpMessage(); + assertTrue(impl.isHoldMessage(msg)); + + HttpResponseHeader resHeader = new HttpResponseHeader(OK_RESPONSE); + msg.setResponseHeader(resHeader); + assertTrue(impl.isHoldMessage(msg)); + } + + @Test + void shouldBreakOnJustHttpRequests() throws HttpMalformedHeaderException { + impl.setBreakAllRequests(true); + HttpMessage msg = new HttpMessage(); + assertTrue(impl.isHoldMessage(msg)); + + HttpResponseHeader resHeader = new HttpResponseHeader(OK_RESPONSE); + msg.setResponseHeader(resHeader); + assertFalse(impl.isHoldMessage(msg)); + } + + @Test + void shouldBreakOnJustHttpResponses() throws HttpMalformedHeaderException { + impl.setBreakAllResponses(true); + HttpMessage msg = new HttpMessage(); + assertFalse(impl.isHoldMessage(msg)); + + HttpResponseHeader resHeader = new HttpResponseHeader(OK_RESPONSE); + msg.setResponseHeader(resHeader); + assertTrue(impl.isHoldMessage(msg)); + } + + @Test + void shouldStep() throws HttpMalformedHeaderException { + impl.setBreakAll(true); + HttpMessage msg = new HttpMessage(); + assertTrue(impl.isHoldMessage(msg)); + + impl.step(); + assertTrue(impl.isStepping()); + // False the first time + assertFalse(impl.isHoldMessage(msg)); + // Then true for subsequent times + assertTrue(impl.isHoldMessage(msg)); + assertTrue(impl.isStepping()); + + HttpResponseHeader resHeader = new HttpResponseHeader(OK_RESPONSE); + msg.setResponseHeader(resHeader); + + impl.step(); + assertTrue(impl.isStepping()); + // False the first time + assertFalse(impl.isHoldMessage(msg)); + // Then true for subsequent times + assertTrue(impl.isHoldMessage(msg)); + assertTrue(impl.isStepping()); + } + + @Test + void shouldClearBreaksOnContinue() throws HttpMalformedHeaderException { + impl.setBreakAll(true); + HttpMessage msg = new HttpMessage(); + assertTrue(impl.isHoldMessage(msg)); + + impl.cont(); + assertFalse(impl.isHoldMessage(msg)); + assertFalse(impl.isBreakAll()); + assertFalse(impl.isBreakRequest()); + assertFalse(impl.isBreakResponse()); + + assertFalse(impl.isHoldMessage(msg)); + // Deliberate duplicate check due to the side effects of stepping + assertFalse(impl.isHoldMessage(msg)); + assertFalse(impl.isStepping()); + } + + @Test + void shouldDrop() throws HttpMalformedHeaderException { + impl.setBreakAll(true); + HttpMessage msg = new HttpMessage(); + assertTrue(impl.isHoldMessage(msg)); + + impl.drop(); + assertTrue(impl.isToBeDropped()); + assertFalse(impl.isToBeDropped()); + assertFalse(impl.isToBeDropped()); + + impl.drop(); + assertTrue(impl.isToBeDropped()); + assertFalse(impl.isToBeDropped()); + assertFalse(impl.isToBeDropped()); + } +} diff --git a/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java b/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java index 24b58bdf8c0..1658a9a842e 100644 --- a/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java +++ b/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java @@ -133,7 +133,7 @@ import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiElement; import org.zaproxy.zap.extension.api.ApiImplementor; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.utils.ZapPortNumberSpinner; public class ExtensionNetwork extends ExtensionAdaptor implements CommandLineListener { diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 43251368fdc..0729b2d2b39 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -58,7 +58,7 @@ import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiResponse; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java index 56b3b3fd590..34894dbac13 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; +import org.zaproxy.addon.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java index 7cef59bb4f5..c98c494c287 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.addon.brk.BreakpointManagementInterface; +import org.zaproxy.addon.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java index c09e0cc667d..7a2b3024c9d 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; -import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointMessageInterface; +import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java index b05cbf234b3..3e1e2c80a0f 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.plugnhack.ClientsPanel; import org.zaproxy.zap.extension.plugnhack.MessageListTableModel; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java index 471fb431a23..c858a922e0e 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.BreakpointsPanel; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointsPanel; +import org.zaproxy.addon.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java index 4b2ca432d9b..29f95edeb37 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java @@ -67,8 +67,8 @@ import org.parosproxy.paros.view.View; import org.zaproxy.zap.PersistentConnectionListener; import org.zaproxy.zap.extension.alert.ExtensionAlert; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointMessageHandler2; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java index 89416974c7e..3d62fb47771 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java @@ -54,7 +54,7 @@ import org.zaproxy.zap.extension.api.ApiResponseList; import org.zaproxy.zap.extension.api.ApiResponseSet; import org.zaproxy.zap.extension.api.ApiView; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketProxy.Initiator; import org.zaproxy.zap.extension.websocket.WebSocketProxy.State; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java index 429a8182891..6efc8cbd59a 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; import org.zaproxy.zap.extension.websocket.ui.WebSocketMessagesViewModel; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java index fe173ccfbd2..4e8c8efb4ea 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.BreakpointsPanel; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointsPanel; +import org.zaproxy.addon.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java index 5a2d6336fbf..46c877d9411 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java @@ -23,7 +23,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; +import org.zaproxy.addon.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessage.Direction; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java index 964ddccca29..b728d47ecd9 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.websocket.brk; -import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.addon.brk.BreakpointManagementInterface; +import org.zaproxy.addon.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessage; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java index 06e3ad9dfd4..d9d57af0db3 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.websocket.brk; -import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; -import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointMessageInterface; +import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; import org.zaproxy.zap.extension.websocket.ui.WebSocketPanel; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java index 5e9d2852593..bbc32d7d93e 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java @@ -21,7 +21,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.addon.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.websocket.ExtensionWebSocket; import org.zaproxy.zap.extension.websocket.WebSocketException; import org.zaproxy.zap.extension.websocket.WebSocketFuzzMessageDTO; From 588975db103fb24c84d5362c37db9c44eacf421e Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 01:19:58 +0530 Subject: [PATCH 02/24] update gradle files to import break addon Signed-off-by: aryangupta701 --- addOns/network/network.gradle.kts | 1 + addOns/plugnhack/plugnhack.gradle.kts | 1 + addOns/websocket/websocket.gradle.kts | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/addOns/network/network.gradle.kts b/addOns/network/network.gradle.kts index 4da40b4a1f6..d1433d5770c 100644 --- a/addOns/network/network.gradle.kts +++ b/addOns/network/network.gradle.kts @@ -60,6 +60,7 @@ spotless { } dependencies { + zapAddOn("break") val nettyVersion = "4.1.100.Final" implementation("io.netty:netty-codec:$nettyVersion") implementation("io.netty:netty-handler:$nettyVersion") diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 1c1f65d906b..96b16fe5aa5 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -43,4 +43,5 @@ zapAddOn { dependencies { zapAddOn("network") zapAddOn("requester") + zapAddOn("break") } diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index e294e4b5608..b3f6787601a 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -50,6 +50,7 @@ zapAddOn { dependencies { zapAddOn("fuzz") zapAddOn("requester") - + zapAddOn("break") + testImplementation(project(":testutils")) } From d2a4b6d265702959de1548fefd5c2f00184e3457 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 01:25:53 +0530 Subject: [PATCH 03/24] update gradle files to import break addon Signed-off-by: aryangupta701 --- addOns/network/network.gradle.kts | 2 +- addOns/plugnhack/plugnhack.gradle.kts | 2 +- addOns/websocket/websocket.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addOns/network/network.gradle.kts b/addOns/network/network.gradle.kts index d1433d5770c..3effee08a45 100644 --- a/addOns/network/network.gradle.kts +++ b/addOns/network/network.gradle.kts @@ -60,7 +60,7 @@ spotless { } dependencies { - zapAddOn("break") + zapAddOn("brk") val nettyVersion = "4.1.100.Final" implementation("io.netty:netty-codec:$nettyVersion") implementation("io.netty:netty-handler:$nettyVersion") diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 96b16fe5aa5..99ef56b7cd4 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -43,5 +43,5 @@ zapAddOn { dependencies { zapAddOn("network") zapAddOn("requester") - zapAddOn("break") + zapAddOn("brk") } diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index b3f6787601a..2a653c692a0 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -50,7 +50,7 @@ zapAddOn { dependencies { zapAddOn("fuzz") zapAddOn("requester") - zapAddOn("break") + zapAddOn("brk") testImplementation(project(":testutils")) } From 2dbb0f917ffaafa8d86bed2b915e6b2b4ae97d78 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 01:36:20 +0530 Subject: [PATCH 04/24] update gradle files to import break addon Signed-off-by: aryangupta701 --- addOns/brk/brk.gradle.kts | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/addOns/brk/brk.gradle.kts b/addOns/brk/brk.gradle.kts index e9fa30e268d..1a6d7ed04df 100644 --- a/addOns/brk/brk.gradle.kts +++ b/addOns/brk/brk.gradle.kts @@ -1,40 +1,13 @@ -description = "Exposes client (browser) side information in ZAP using Firefox and Chrome extensions." +description = "Allows you to add breakpoints" zapAddOn { - addOnName.set("Break") - + addOnName.set("brk") manifest { author.set("ZAP Dev Team") url.set("https://www.zaproxy.org/docs/desktop/addons/brk/") - extensions { - - } - dependencies { - addOns { - register("selenium") { - version.set(">=15.14.0") - } - register("network") { - version.set(">=0.8.0") - } - register("commonlib") - } - } - } -} - -crowdin { - configuration { - val resourcesPath = "org/zaproxy/addon/${zapAddOn.addOnId.get()}/resources/" - tokens.put("%messagesPath%", resourcesPath) - tokens.put("%helpPath%", resourcesPath) } } dependencies { - zapAddOn("commonlib") - zapAddOn("selenium") - zapAddOn("network") - testImplementation(project(":testutils")) } From ea4848c1dfa04ddf8de76cfe5a27148adc111197 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 01:49:56 +0530 Subject: [PATCH 05/24] update gradle files to import break addon Signed-off-by: aryangupta701 --- addOns/brk/gradle.properties | 2 +- addOns/network/network.gradle.kts | 8 ++++++++ addOns/plugnhack/plugnhack.gradle.kts | 5 ++++- addOns/websocket/websocket.gradle.kts | 3 +++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/addOns/brk/gradle.properties b/addOns/brk/gradle.properties index 2a0ce7fc7a6..0ea36b1d480 100644 --- a/addOns/brk/gradle.properties +++ b/addOns/brk/gradle.properties @@ -1,2 +1,2 @@ -version=0.8.0 +version=0.1.0 release=false diff --git a/addOns/network/network.gradle.kts b/addOns/network/network.gradle.kts index 3effee08a45..0b64a728c63 100644 --- a/addOns/network/network.gradle.kts +++ b/addOns/network/network.gradle.kts @@ -30,6 +30,14 @@ zapAddOn { libs.from(brotli) libs.from(hc) } + + dependencies { + addOns { + register("brk") { + version.set(">= 0.1.0") + } + } + } } apiClientGen { diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 99ef56b7cd4..0f2f85dca23 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -15,9 +15,12 @@ zapAddOn { register("network") { version.set(">= 0.2.0") } + register("brk") { + version.set(">= 0.1.0") + } } } - + extensions { register("org.zaproxy.zap.extension.plugnhack.manualsend.ExtensionPlugNHackManualSend") { classnames { diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index 2a653c692a0..7e31c4062a8 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -22,6 +22,9 @@ zapAddOn { register("fuzz") { version.set("2.* | 13.*") } + register("brk") { + version.set(">= 0.1.0") + } } } } From b9f37b5b7188d6cac83a81fd5e344a6a015363f3 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 22:04:07 +0530 Subject: [PATCH 06/24] fix build issue Signed-off-by: aryangupta701 --- addOns/brk/CHANGELOG.md | 4 +++- .../HttpBreakpointManagementDaemonImplUnitTest.java | 4 ++-- addOns/network/network.gradle.kts | 10 +--------- .../org/zaproxy/addon/network/ExtensionNetwork.java | 2 +- settings.gradle.kts | 1 + 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/addOns/brk/CHANGELOG.md b/addOns/brk/CHANGELOG.md index a1d458d43a6..bd46ab61fb1 100644 --- a/addOns/brk/CHANGELOG.md +++ b/addOns/brk/CHANGELOG.md @@ -3,4 +3,6 @@ All notable changes to this add-on will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## Unreleased \ No newline at end of file +## Unreleased + +## [0.1.0] - 2024-01-14 \ No newline at end of file diff --git a/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java b/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java index a0a9c6e24de..aae3c8744e8 100644 --- a/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java +++ b/addOns/brk/src/test/java/org/zaproxy/addon/brk/impl/http/HttpBreakpointManagementDaemonImplUnitTest.java @@ -28,9 +28,9 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.network.HttpResponseHeader; -import org.zaproxy.zap.WithConfigsTest; +import org.zaproxy.zap.testutils.TestUtils; -class HttpBreakpointManagementDaemonImplUnitTest extends WithConfigsTest { +class HttpBreakpointManagementDaemonImplUnitTest extends TestUtils { private static String OK_RESPONSE = "HTTP/1.1 200 OK" diff --git a/addOns/network/network.gradle.kts b/addOns/network/network.gradle.kts index 0b64a728c63..8a1015ef9c2 100644 --- a/addOns/network/network.gradle.kts +++ b/addOns/network/network.gradle.kts @@ -30,14 +30,7 @@ zapAddOn { libs.from(brotli) libs.from(hc) } - - dependencies { - addOns { - register("brk") { - version.set(">= 0.1.0") - } - } - } + } apiClientGen { @@ -68,7 +61,6 @@ spotless { } dependencies { - zapAddOn("brk") val nettyVersion = "4.1.100.Final" implementation("io.netty:netty-codec:$nettyVersion") implementation("io.netty:netty-handler:$nettyVersion") diff --git a/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java b/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java index 1658a9a842e..24b58bdf8c0 100644 --- a/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java +++ b/addOns/network/src/main/java/org/zaproxy/addon/network/ExtensionNetwork.java @@ -133,7 +133,7 @@ import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiElement; import org.zaproxy.zap.extension.api.ApiImplementor; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.utils.ZapPortNumberSpinner; public class ExtensionNetwork extends ExtensionAdaptor implements CommandLineListener { diff --git a/settings.gradle.kts b/settings.gradle.kts index 82373b4f2d0..77ca25dacbc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -35,6 +35,7 @@ var addOns = listOf( "authstats", "automation", "beanshell", + "brk", "browserView", "bruteforce", "bugtracker", From b85bde3bc32bc1623630bb15210ec620dc6f6185 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 22:05:00 +0530 Subject: [PATCH 07/24] fix build issue Signed-off-by: aryangupta701 --- addOns/network/network.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/addOns/network/network.gradle.kts b/addOns/network/network.gradle.kts index 8a1015ef9c2..4da40b4a1f6 100644 --- a/addOns/network/network.gradle.kts +++ b/addOns/network/network.gradle.kts @@ -30,7 +30,6 @@ zapAddOn { libs.from(brotli) libs.from(hc) } - } apiClientGen { From d60761b4aeb0e693d2d6b404f0b4dbcff5ca888d Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Sun, 14 Jan 2024 23:01:10 +0530 Subject: [PATCH 08/24] spotless apply Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 2 +- .../zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java | 2 +- .../zaproxy/zap/extension/websocket/ExtensionWebSocket.java | 4 ++-- .../org/zaproxy/zap/extension/websocket/WebSocketAPI.java | 2 +- addOns/websocket/websocket.gradle.kts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 0f2f85dca23..add0db4a5ea 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -20,7 +20,7 @@ zapAddOn { } } } - + extensions { register("org.zaproxy.zap.extension.plugnhack.manualsend.ExtensionPlugNHackManualSend") { classnames { diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 0729b2d2b39..c2ec395ff08 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -52,13 +52,13 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.addon.network.ExtensionNetwork; import org.zaproxy.addon.network.server.ServerInfo; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiResponse; -import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java index 29f95edeb37..cb94a16e867 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java @@ -65,10 +65,10 @@ import org.parosproxy.paros.network.HttpSender; import org.parosproxy.paros.view.AbstractParamPanel; import org.parosproxy.paros.view.View; -import org.zaproxy.zap.PersistentConnectionListener; -import org.zaproxy.zap.extension.alert.ExtensionAlert; import org.zaproxy.addon.brk.BreakpointMessageHandler2; import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.PersistentConnectionListener; +import org.zaproxy.zap.extension.alert.ExtensionAlert; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java index 3d62fb47771..ac0bf8b24ae 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java @@ -40,6 +40,7 @@ import org.parosproxy.paros.db.DatabaseException; import org.parosproxy.paros.network.HttpHeader; import org.parosproxy.paros.network.HttpMessage; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.eventBus.Event; import org.zaproxy.zap.eventBus.EventConsumer; @@ -54,7 +55,6 @@ import org.zaproxy.zap.extension.api.ApiResponseList; import org.zaproxy.zap.extension.api.ApiResponseSet; import org.zaproxy.zap.extension.api.ApiView; -import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketProxy.Initiator; import org.zaproxy.zap.extension.websocket.WebSocketProxy.State; diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index 7e31c4062a8..4bf21831648 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -53,7 +53,7 @@ zapAddOn { dependencies { zapAddOn("fuzz") zapAddOn("requester") - zapAddOn("brk") + zapAddOn("brk") testImplementation(project(":testutils")) } From 0806a0a671903d03aa28efddaae23a959d89a906 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 14:53:53 +0530 Subject: [PATCH 09/24] update gradle.kts for websocket and plugnhack Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 12 ++++++++++++ addOns/websocket/websocket.gradle.kts | 16 +++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index add0db4a5ea..f812b05ec08 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -34,6 +34,18 @@ zapAddOn { } } } + register("org.zaproxy.addon.brk.ExtensionBreak") { + classnames { + allowed.set(listOf("org.zaproxy.addon.brk.ExtensionBreak")) + } + dependencies { + addOns { + register("brk") { + version.set("0.1.0*") + } + } + } + } } } diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index 4bf21831648..28ad56ca2dc 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -22,9 +22,6 @@ zapAddOn { register("fuzz") { version.set("2.* | 13.*") } - register("brk") { - version.set(">= 0.1.0") - } } } } @@ -41,6 +38,19 @@ zapAddOn { } } } + + register("org.zaproxy.addon.brk.ExtensionBreak") { + classnames { + allowed.set(listOf("org.zaproxy.addon.brk.ExtensionBreak")) + } + dependencies { + addOns { + register("brk") { + version.set("0.1.0*") + } + } + } + } } } From c9ab78b86a49f1734a60851ac2106fddfc6a9d05 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 14:54:47 +0530 Subject: [PATCH 10/24] update gradle.kts for websocket and plugnhack Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 3 --- 1 file changed, 3 deletions(-) diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index f812b05ec08..881222a781f 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -15,9 +15,6 @@ zapAddOn { register("network") { version.set(">= 0.2.0") } - register("brk") { - version.set(">= 0.1.0") - } } } From d57128eee37621646d4f9d915ff2b272f88be0f5 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 15:59:20 +0530 Subject: [PATCH 11/24] remove plugnhack and websocket changes Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 13 ------------- .../zap/extension/plugnhack/ExtensionPlugNHack.java | 2 +- .../plugnhack/brk/ClientBreakpointMessage.java | 2 +- .../brk/ClientBreakpointMessageHandler.java | 4 ++-- .../brk/ClientBreakpointsUiManagerInterface.java | 6 +++--- .../plugnhack/brk/PopupMenuAddBreakClient.java | 2 +- .../extension/plugnhack/brk/PopupMenuEditBreak.java | 4 ++-- .../zap/extension/websocket/ExtensionWebSocket.java | 4 ++-- .../zap/extension/websocket/WebSocketAPI.java | 2 +- .../websocket/brk/PopupMenuAddBreakWebSocket.java | 2 +- .../websocket/brk/WebSocketBreakpointMessage.java | 2 +- .../brk/WebSocketBreakpointMessageHandler.java | 4 ++-- .../brk/WebSocketBreakpointsUiManagerInterface.java | 6 +++--- .../websocket/brk/WebSocketProxyListenerBreak.java | 2 +- addOns/websocket/websocket.gradle.kts | 12 ------------ 15 files changed, 21 insertions(+), 46 deletions(-) diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 881222a781f..1c1f65d906b 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -31,18 +31,6 @@ zapAddOn { } } } - register("org.zaproxy.addon.brk.ExtensionBreak") { - classnames { - allowed.set(listOf("org.zaproxy.addon.brk.ExtensionBreak")) - } - dependencies { - addOns { - register("brk") { - version.set("0.1.0*") - } - } - } - } } } @@ -55,5 +43,4 @@ zapAddOn { dependencies { zapAddOn("network") zapAddOn("requester") - zapAddOn("brk") } diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index c2ec395ff08..036e56565f8 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -52,7 +52,7 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.addon.network.ExtensionNetwork; import org.zaproxy.addon.network.server.ServerInfo; import org.zaproxy.zap.ZAP; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java index 34894dbac13..56b3b3fd590 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.addon.brk.AbstractBreakPointMessage; +import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java index c98c494c287..7cef59bb4f5 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.addon.brk.BreakpointManagementInterface; -import org.zaproxy.addon.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java index 7a2b3024c9d..c09e0cc667d 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.addon.brk.BreakpointMessageInterface; -import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; +import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java index 3e1e2c80a0f..b05cbf234b3 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.plugnhack.ClientsPanel; import org.zaproxy.zap.extension.plugnhack.MessageListTableModel; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java index c858a922e0e..471fb431a23 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.BreakpointsPanel; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointsPanel; +import org.zaproxy.zap.extension.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java index cb94a16e867..a0170e23dc0 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java @@ -65,8 +65,8 @@ import org.parosproxy.paros.network.HttpSender; import org.parosproxy.paros.view.AbstractParamPanel; import org.parosproxy.paros.view.View; -import org.zaproxy.addon.brk.BreakpointMessageHandler2; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.PersistentConnectionListener; import org.zaproxy.zap.extension.alert.ExtensionAlert; import org.zaproxy.zap.extension.help.ExtensionHelp; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java index ac0bf8b24ae..418172318fa 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java @@ -40,7 +40,7 @@ import org.parosproxy.paros.db.DatabaseException; import org.parosproxy.paros.network.HttpHeader; import org.parosproxy.paros.network.HttpMessage; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.eventBus.Event; import org.zaproxy.zap.eventBus.EventConsumer; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java index 6efc8cbd59a..429a8182891 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuAddBreakWebSocket.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; import org.zaproxy.zap.extension.websocket.ui.WebSocketMessagesViewModel; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java index 46c877d9411..5a2d6336fbf 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessage.java @@ -23,7 +23,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.addon.brk.AbstractBreakPointMessage; +import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessage.Direction; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java index b728d47ecd9..964ddccca29 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.websocket.brk; -import org.zaproxy.addon.brk.BreakpointManagementInterface; -import org.zaproxy.addon.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessage; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java index d9d57af0db3..06e3ad9dfd4 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.websocket.brk; -import org.zaproxy.addon.brk.BreakpointMessageInterface; -import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; +import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketMessageDTO; import org.zaproxy.zap.extension.websocket.ui.WebSocketPanel; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java index bbc32d7d93e..5e9d2852593 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/WebSocketProxyListenerBreak.java @@ -21,7 +21,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.zaproxy.addon.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.websocket.ExtensionWebSocket; import org.zaproxy.zap.extension.websocket.WebSocketException; import org.zaproxy.zap.extension.websocket.WebSocketFuzzMessageDTO; diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index 28ad56ca2dc..85e1f137862 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -39,18 +39,6 @@ zapAddOn { } } - register("org.zaproxy.addon.brk.ExtensionBreak") { - classnames { - allowed.set(listOf("org.zaproxy.addon.brk.ExtensionBreak")) - } - dependencies { - addOns { - register("brk") { - version.set("0.1.0*") - } - } - } - } } } From 9cdbb2c3b9df0719041173aff36b76867ef956b7 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 16:12:05 +0530 Subject: [PATCH 12/24] spotless apply Signed-off-by: aryangupta701 --- .../zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java | 2 +- .../zaproxy/zap/extension/websocket/ExtensionWebSocket.java | 4 ++-- .../org/zaproxy/zap/extension/websocket/WebSocketAPI.java | 2 +- addOns/websocket/websocket.gradle.kts | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 036e56565f8..43251368fdc 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -52,13 +52,13 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; -import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.addon.network.ExtensionNetwork; import org.zaproxy.addon.network.server.ServerInfo; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiResponse; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java index a0170e23dc0..4b2ca432d9b 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/ExtensionWebSocket.java @@ -65,10 +65,10 @@ import org.parosproxy.paros.network.HttpSender; import org.parosproxy.paros.view.AbstractParamPanel; import org.parosproxy.paros.view.View; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; -import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.PersistentConnectionListener; import org.zaproxy.zap.extension.alert.ExtensionAlert; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java index 418172318fa..89416974c7e 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/WebSocketAPI.java @@ -40,7 +40,6 @@ import org.parosproxy.paros.db.DatabaseException; import org.parosproxy.paros.network.HttpHeader; import org.parosproxy.paros.network.HttpMessage; -import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.eventBus.Event; import org.zaproxy.zap.eventBus.EventConsumer; @@ -55,6 +54,7 @@ import org.zaproxy.zap.extension.api.ApiResponseList; import org.zaproxy.zap.extension.api.ApiResponseSet; import org.zaproxy.zap.extension.api.ApiView; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.websocket.WebSocketProxy.Initiator; import org.zaproxy.zap.extension.websocket.WebSocketProxy.State; diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index 85e1f137862..fc25579bedd 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -38,7 +38,6 @@ zapAddOn { } } } - } } From ce80232c09143b8423487e3801851b340843b151 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 16:13:23 +0530 Subject: [PATCH 13/24] spotless apply Signed-off-by: aryangupta701 --- .../zap/extension/websocket/brk/PopupMenuEditBreak.java | 4 ++-- addOns/websocket/websocket.gradle.kts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java index 4e8c8efb4ea..fe173ccfbd2 100644 --- a/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java +++ b/addOns/websocket/src/main/java/org/zaproxy/zap/extension/websocket/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.BreakpointsPanel; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointsPanel; +import org.zaproxy.zap.extension.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { diff --git a/addOns/websocket/websocket.gradle.kts b/addOns/websocket/websocket.gradle.kts index fc25579bedd..e294e4b5608 100644 --- a/addOns/websocket/websocket.gradle.kts +++ b/addOns/websocket/websocket.gradle.kts @@ -50,7 +50,6 @@ zapAddOn { dependencies { zapAddOn("fuzz") zapAddOn("requester") - zapAddOn("brk") - + testImplementation(project(":testutils")) } From 3278af7a90d9f0ab4b048ddfdaed69e456c356e7 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Mon, 15 Jan 2024 16:52:51 +0530 Subject: [PATCH 14/24] update help Signed-off-by: aryangupta701 --- .../resources/help/contents/addbreak.html | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html new file mode 100644 index 00000000000..f4111036bdf --- /dev/null +++ b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html @@ -0,0 +1,37 @@ + + + + + +Add/Edit Breakpoint dialog + + + +

Add/Edit Breakpoint dialog

+ +A breakpoint is defined by the following fields: + +
    +
  • Location - where the String is checked in the + HTTP message: URL, Request Header, Request Body, + Response Header, or Response Body.
  • +
  • Match - how the String is interpreted, Regex + or Contains, for regular expression or exact match, respectively, in the Location. + The regular expression does not need to match the whole content of the Location.
  • +
  • String - the string that triggers the breakpoint.
  • +
  • Inverse - if the result of the Match should be + the inverse.
  • +
  • Ignore case - if the case of the String should be + ignored.
  • +
+ +If you proxy a HTTP message that matches a breakpoint then ZAP will intercept it and allow you to change either the request +or the response. + +

+Note: ZAP will warn and prevent adding breakpoints with a fragment identifier component (#), if +the breakpoint has match Contains and location URL. Such breakpoint would not work because the +fragment identifier is not sent to the server. + + + From 33ee68149858414f11ce5bb15e98c9c700074742 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Wed, 14 Feb 2024 23:44:13 +0100 Subject: [PATCH 15/24] migrate Messages.properties Signed-off-by: aryangupta701 --- .../org/zaproxy/addon/brk/Messages.properties | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties diff --git a/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties b/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties new file mode 100644 index 00000000000..2f149ea1a19 --- /dev/null +++ b/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties @@ -0,0 +1,103 @@ + +break.api.action.addHttpBreakpoint = Adds a custom HTTP breakpoint. The string is the string to match. Location may be one of: url, request_header, request_body, response_header or response_body. Match may be: contains or regex. Inverse (match) may be true or false. Lastly, ignorecase (when matching the string) may be true or false. +break.api.action.addHttpBreakpoint.param.ignorecase = +break.api.action.addHttpBreakpoint.param.inverse = +break.api.action.addHttpBreakpoint.param.location = +break.api.action.addHttpBreakpoint.param.match = +break.api.action.addHttpBreakpoint.param.string = +break.api.action.break = Controls the global break functionality. The type may be one of: http-all, http-request or http-response. The state may be true (for turning break on for the specified type) or false (for turning break off). Scope is not currently used. +break.api.action.break.param.scope = +break.api.action.break.param.state = +break.api.action.break.param.type = +break.api.action.continue = Submits the currently intercepted message and unsets the global request/response breakpoints +break.api.action.drop = Drops the currently intercepted message +break.api.action.removeHttpBreakpoint = Removes the specified breakpoint +break.api.action.removeHttpBreakpoint.param.ignorecase = +break.api.action.removeHttpBreakpoint.param.inverse = +break.api.action.removeHttpBreakpoint.param.location = +break.api.action.removeHttpBreakpoint.param.match = +break.api.action.removeHttpBreakpoint.param.string = +break.api.action.setHttpMessage = Overwrites the currently intercepted message with the data provided +break.api.action.setHttpMessage.param.httpBody = +break.api.action.setHttpMessage.param.httpHeader = +break.api.action.step = Submits the currently intercepted message, the next request or response will automatically be intercepted +break.api.desc = +break.api.pconn.waitForHttpBreak = Waits until an HTTP breakpoint has been hit, at which point it returns the message. Poll is the number of milliseconds ZAP will pause between checking for breakpoints being hit (default 500). If keepalive is zero or less then the response will be returned as a Server Sent Event, otherwise it is used as the frequency in seconds at which 'keepalive' events should be returned and the response is sent as a standard response. +break.api.view.httpMessage = Returns the HTTP message currently intercepted (if any) +break.api.view.isBreakAll = Returns True if ZAP will break on both requests and responses +break.api.view.isBreakRequest = Returns True if ZAP will break on requests +break.api.view.isBreakResponse = Returns True if ZAP will break on responses + +brk.add.button.add = Add +brk.add.button.cancel = Cancel +brk.add.error.history = Error getting History +brk.add.popup = Break... +brk.add.title = Add Breakpoint +brk.alwaysOnTop.message = By default ZAP will remain on top of all other windows when a breakpoint is hit.\nPress 'Cancel' to disable this feature.\nThis option can changed via Tools/Breakpoints +brk.brkpoint.add.title = Add Breakpoint +brk.brkpoint.edit.title = Edit Breakpoint +brk.brkpoint.error.nostr = You must supply a string +brk.brkpoint.error.regex = Invalid regular expression +brk.brkpoint.ignorecase.label = Ignore Case: +brk.brkpoint.inverse.label = Inverse: +brk.brkpoint.location.label = Location: +brk.brkpoint.location.request_body = Request Body +brk.brkpoint.location.request_header = Request Header +brk.brkpoint.location.response_body = Response Body +brk.brkpoint.location.response_header = Response Header +brk.brkpoint.location.url = URL +brk.brkpoint.match.contains = Contains +brk.brkpoint.match.label = Match: +brk.brkpoint.match.regex = Regex +brk.brkpoint.onscope = Break if out of scope +brk.brkpoint.string.label = String: +brk.brkpoint.warn.urlfragment = Pattern shouldn't include URL fragment (#) +brk.checkBox.fixHostHeader = Update Host Header +brk.checkBox.fixLength = Update Content Length +brk.desc = Allows you to intercept and modify requests and responses +brk.dialogue.confirmDropMessage.button.cancel.label = Cancel +brk.dialogue.confirmDropMessage.button.confirm.label = Drop +brk.dialogue.confirmDropMessage.message = Are you sure you want to drop the trapped message? +brk.dialogue.confirmDropMessage.option.dontAskAgain = Don't ask again +brk.dialogue.confirmDropMessage.title = Confirm Drop Trapped Message +brk.edit.button.save = Save +brk.edit.popup = Edit... +brk.edit.title = Edit Breakpoint +brk.name = Breakpoint Extension +brk.optionspanel.name = Breakpoints +brk.optionspanel.option.alwaysOnTop.label = ZAP always on top when breakpoint hit. +brk.optionspanel.option.breakmode.dual.label = Separate Request and Response Buttons +brk.optionspanel.option.breakmode.label = Break Buttons Mode: +brk.optionspanel.option.breakmode.simple.label = Single Combined Button +brk.optionspanel.option.confirmDropMessage.label = Confirm drop trapped message. +brk.optionspanel.option.cssAndFontsUrlRegex.label = CSS and Fonts URL Regex: +brk.optionspanel.option.inScopeOnly.label = Only break on messages in scope. +brk.optionspanel.option.javaScriptUrlRegex.label = Javascript URL Regex: +brk.optionspanel.option.multimediaUrlRegex.label = Multimedia URL Regex: +brk.optionspanel.option.notpossibletoshowtip = Cannot show these buttons when break buttons are only shown in the main toolbar. +brk.optionspanel.option.showBreakFilteringButtons.label = Show buttons to select the requests you don't want ZAP to break on. +brk.panel.mnemonic = b +brk.panel.title = Breakpoints +brk.panel.warn.datainvalid = Unable to set the data to the message. +brk.remove.popup = Remove +brk.table.header.condition = Condition +brk.table.header.enabled = Enabled +brk.table.header.type = Type +brk.toolbar.button.all.set = Set Break on All Requests and Responses +brk.toolbar.button.all.unset = Unset break on all requests and responses +brk.toolbar.button.bin = Bin Request or Response +brk.toolbar.button.brkOnlyOnScope.set = Set break only in scope +brk.toolbar.button.brkOnlyOnScope.unset = Unset break only in scope +brk.toolbar.button.brkcssfonts.set = Set can break on CSS and Fonts +brk.toolbar.button.brkcssfonts.unset = Set ignore breaks on CSS and Fonts +brk.toolbar.button.brkjavascript.set = Set can break on JavaScript +brk.toolbar.button.brkjavascript.unset = Set ignore breaks on JavaScript files +brk.toolbar.button.brkmultimedia.set = Set can break on Multimedia +brk.toolbar.button.brkmultimedia.unset = Set ignore breaks on Multimedia +brk.toolbar.button.brkpoint = Add a custom HTTP breakpoint... +brk.toolbar.button.cont = Submit and Continue to Next Breakpoint +brk.toolbar.button.request.set = Set break on all requests +brk.toolbar.button.request.unset = Unset break on all requests +brk.toolbar.button.response.set = Set break on all responses +brk.toolbar.button.response.unset = Unset break on all responses +brk.toolbar.button.step = Submit and Step to Next Request or Response From a0c9113f9dd26fe723a85699cdba8bdf0798e965 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 00:06:22 +0100 Subject: [PATCH 16/24] spotless apply Signed-off-by: aryangupta701 --- .../org/zaproxy/addon/brk/Messages.properties | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties b/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties index 2f149ea1a19..3c566681184 100644 --- a/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties +++ b/addOns/brk/src/main/resources/org/zaproxy/addon/brk/Messages.properties @@ -1,27 +1,27 @@ break.api.action.addHttpBreakpoint = Adds a custom HTTP breakpoint. The string is the string to match. Location may be one of: url, request_header, request_body, response_header or response_body. Match may be: contains or regex. Inverse (match) may be true or false. Lastly, ignorecase (when matching the string) may be true or false. -break.api.action.addHttpBreakpoint.param.ignorecase = -break.api.action.addHttpBreakpoint.param.inverse = -break.api.action.addHttpBreakpoint.param.location = -break.api.action.addHttpBreakpoint.param.match = -break.api.action.addHttpBreakpoint.param.string = +break.api.action.addHttpBreakpoint.param.ignorecase = +break.api.action.addHttpBreakpoint.param.inverse = +break.api.action.addHttpBreakpoint.param.location = +break.api.action.addHttpBreakpoint.param.match = +break.api.action.addHttpBreakpoint.param.string = break.api.action.break = Controls the global break functionality. The type may be one of: http-all, http-request or http-response. The state may be true (for turning break on for the specified type) or false (for turning break off). Scope is not currently used. -break.api.action.break.param.scope = -break.api.action.break.param.state = -break.api.action.break.param.type = +break.api.action.break.param.scope = +break.api.action.break.param.state = +break.api.action.break.param.type = break.api.action.continue = Submits the currently intercepted message and unsets the global request/response breakpoints break.api.action.drop = Drops the currently intercepted message break.api.action.removeHttpBreakpoint = Removes the specified breakpoint -break.api.action.removeHttpBreakpoint.param.ignorecase = -break.api.action.removeHttpBreakpoint.param.inverse = -break.api.action.removeHttpBreakpoint.param.location = -break.api.action.removeHttpBreakpoint.param.match = -break.api.action.removeHttpBreakpoint.param.string = +break.api.action.removeHttpBreakpoint.param.ignorecase = +break.api.action.removeHttpBreakpoint.param.inverse = +break.api.action.removeHttpBreakpoint.param.location = +break.api.action.removeHttpBreakpoint.param.match = +break.api.action.removeHttpBreakpoint.param.string = break.api.action.setHttpMessage = Overwrites the currently intercepted message with the data provided -break.api.action.setHttpMessage.param.httpBody = -break.api.action.setHttpMessage.param.httpHeader = +break.api.action.setHttpMessage.param.httpBody = +break.api.action.setHttpMessage.param.httpHeader = break.api.action.step = Submits the currently intercepted message, the next request or response will automatically be intercepted -break.api.desc = +break.api.desc = break.api.pconn.waitForHttpBreak = Waits until an HTTP breakpoint has been hit, at which point it returns the message. Poll is the number of milliseconds ZAP will pause between checking for breakpoints being hit (default 500). If keepalive is zero or less then the response will be returned as a Server Sent Event, otherwise it is used as the frequency in seconds at which 'keepalive' events should be returned and the response is sent as a standard response. break.api.view.httpMessage = Returns the HTTP message currently intercepted (if any) break.api.view.isBreakAll = Returns True if ZAP will break on both requests and responses From b0b0b05ce0dd611e2ce9e33b598dbaa9a8f247f7 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 00:18:15 +0100 Subject: [PATCH 17/24] update help Signed-off-by: aryangupta701 --- .../resources/help/contents/addbreak.html | 0 .../help/contents/images/break_add.png | Bin 0 -> 644 bytes .../extension/brk/resources/help/helpset.hs | 41 ++++++++++++++++++ .../extension/brk/resources/help/index.xml | 9 ++++ .../zap/extension/brk/resources/help/map.jhm | 9 ++++ .../zap/extension/brk/resources/help/toc.xml | 12 +++++ 6 files changed, 71 insertions(+) rename addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/{fuzz => brk}/resources/help/contents/addbreak.html (100%) create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/contents/images/break_add.png create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/helpset.hs create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/index.xml create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/map.jhm create mode 100644 addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/toc.xml diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/contents/addbreak.html similarity index 100% rename from addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/fuzz/resources/help/contents/addbreak.html rename to addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/contents/addbreak.html diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/contents/images/break_add.png b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/contents/images/break_add.png new file mode 100644 index 0000000000000000000000000000000000000000..e08dead3fab8b88d428394987179687e9a4ae4f5 GIT binary patch literal 644 zcmV-~0(Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyk; z4j?H56cf(?00IO_L_t(I%dL~YYZGA{#y^RI)Jg-*V1_ORI#jgO;$Vfq9la7K=^z~( zS|O0ZsVJggC6_^TaVSpu2RIam;!xDk-oXuZ2ublL7_+L;(%T`58siI{ZqcOS~JLZxAvS8XBDN9%u9Vs1IF#idW1=HwA z>2x(ESupKhfDodT%;zDBNaphhA)H_-*9!@ja)uDX8PJpf5&(a0UNHb?Xl_nBhKKRj z*8$9KhBGuj5A8Mpex(9no__VgO~kwWzA0`SXq0nGH9&u;8V3=XTAA2$H!Y%bTw?|B}8nR(Z6 z5A!Dn1EMh0i&P4lO})-!4)_7|Rq*p_#sHji%geC6-LIUPA+h%WI)DJ~YHu?B{{8Z( zA;M6bx3<9dX?PwD&ja7roPgEhq7FFR!k5W2Mihq5`IQye*Z|;bt=2on#Ke0Cp?4NS zKnRpkh;9oXCr+u0R&OsNgdhk4+U+({N}j%~=z!Yz2^%O~ znwp}%vjbpGH{`*zpP=I2AKtpg;}>rsLO(I8S?p>SRn2nbW#SR){truW2X*9sa4hbj ehyV#Z*WSOJ7TrQ#9ksCl0000 + + + Active Scan Rules - Alpha | ZAP Extension + + + top + + + + + TOC + + org.zaproxy.zap.extension.help.ZapTocView + toc.xml + + + + Index + + javax.help.IndexView + index.xml + + + + Search + + javax.help.SearchView + + JavaHelpSearch + + + + + Favorites + + javax.help.FavoritesView + + diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/index.xml b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/index.xml new file mode 100644 index 00000000000..40f59c20433 --- /dev/null +++ b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/index.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/map.jhm b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/map.jhm new file mode 100644 index 00000000000..43accad8642 --- /dev/null +++ b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/map.jhm @@ -0,0 +1,9 @@ + + + + + + + diff --git a/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/toc.xml b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/toc.xml new file mode 100644 index 00000000000..d61534fae2b --- /dev/null +++ b/addOns/brk/src/main/javahelp/org/zaproxy/zap/extension/brk/resources/help/toc.xml @@ -0,0 +1,12 @@ + + + + + + + + + + From afdc09c5632e3fa4a72ee59e25ab869726f69456 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 01:11:26 +0100 Subject: [PATCH 18/24] update plugNHack to use Brk addon Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 14 +++++ .../plugnhack/ExtensionPlugNHack.java | 27 +++------- .../brk/ClientBreakpointMessage.java | 2 +- .../brk/ClientBreakpointMessageHandler.java | 4 +- .../ClientBreakpointsUiManagerInterface.java | 6 +-- .../plugnhack/brk/ExtensionPlugNHackBrk.java | 51 +++++++++++++++++++ .../brk/PopupMenuAddBreakClient.java | 2 +- .../plugnhack/brk/PopupMenuEditBreak.java | 4 +- 8 files changed, 81 insertions(+), 29 deletions(-) create mode 100644 addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index 1c1f65d906b..df7829ca8c9 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -31,6 +31,19 @@ zapAddOn { } } } + + register("org.zaproxy.zap.extension.plugnhack.brk.ExtensionPlugNHackBrk") { + classnames { + allowed.set(listOf("org.zaproxy.zap.extension.plugnhack.brk")) + } + dependencies { + addOns { + register("brk") { + version.set(">=0.1") + } + } + } + } } } @@ -43,4 +56,5 @@ zapAddOn { dependencies { zapAddOn("network") zapAddOn("requester") + zapAddOn("brk") } diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index f28cf0332e2..6634e3b428a 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -51,13 +51,13 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.addon.network.ExtensionNetwork; import org.zaproxy.addon.network.server.ServerInfo; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiResponse; -import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; @@ -157,6 +157,8 @@ public class ExtensionPlugNHack extends ExtensionAdaptor private ExtensionNetwork extensionNetwork; + ExtensionBreak extBreak; + /* * TODO * Handle mode @@ -212,21 +214,9 @@ private void startTimeoutThread() { @Override public void run() { this.setName("ZAP-pnh-timeout"); - // Can't init extBreak here - Control wont have been initialized - boolean ctrlInit = false; - ExtensionBreak extBreak = null; while (!shutdown) { try { sleep(poll); - - if (!ctrlInit && Control.getSingleton() != null) { - extBreak = - (ExtensionBreak) - Control.getSingleton() - .getExtensionLoader() - .getExtension(ExtensionBreak.NAME); - ctrlInit = true; - } if (extBreak != null && (extBreak.getBreakpointManagementInterface() .isBreakRequest() @@ -290,7 +280,6 @@ public void hook(ExtensionHook extensionHook) { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // setup Breakpoints - ExtensionBreak extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); if (extBreak != null) { // setup custom breakpoint handler brkMessageHandler = @@ -338,7 +327,6 @@ public void unload() { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // clear up Breakpoints - ExtensionBreak extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); if (extBreak != null) { extBreak.removeBreakpointsUiManager(getBrkManager()); } @@ -906,11 +894,6 @@ protected void messageChanged(ClientMessage msg) { protected ClientBreakpointsUiManagerInterface getBrkManager() { if (brkManager == null) { - ExtensionBreak extBreak = - (ExtensionBreak) - Control.getSingleton() - .getExtensionLoader() - .getExtension(ExtensionBreak.NAME); if (extBreak != null) { brkManager = new ClientBreakpointsUiManagerInterface(this, extBreak); } @@ -960,4 +943,8 @@ public void setClientConfig(MonitoredPage page, String key, Object value) { cmsg.set("value", value); this.mpm.send(cmsg); } + + public void setExtensionBreak(ExtensionBreak brk) { + extBreak = brk; + } } diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java index 56b3b3fd590..34894dbac13 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; +import org.zaproxy.addon.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java index 7cef59bb4f5..c98c494c287 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; -import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; +import org.zaproxy.addon.brk.BreakpointManagementInterface; +import org.zaproxy.addon.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java index c09e0cc667d..7a2b3024c9d 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; -import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointMessageInterface; +import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java new file mode 100644 index 00000000000..798e056eb7b --- /dev/null +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java @@ -0,0 +1,51 @@ +package org.zaproxy.zap.extension.plugnhack.brk; + + +import java.util.List; +import org.parosproxy.paros.Constant; +import org.parosproxy.paros.control.Control; +import org.parosproxy.paros.extension.Extension; +import org.parosproxy.paros.extension.ExtensionAdaptor; +import org.parosproxy.paros.extension.ExtensionHook; +import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; + +public class ExtensionPlugNHackBrk extends ExtensionAdaptor { + + private static final List> DEPENDENCIES = + List.of(ExtensionPlugNHack.class, ExtensionBreak.class); + + @Override + public String getUIName() { + return Constant.messages.getString("quickstart.spider.name"); + } + + @Override + public String getDescription() { + return Constant.messages.getString("quickstart.spider.desc"); + } + + @Override + public List> getDependencies() { + return DEPENDENCIES; + } + + @Override + public void hook(ExtensionHook extensionHook) { + getExtension(ExtensionPlugNHack.class).setExtensionBreak(getExtension(ExtensionBreak.class)); + } + + private static T getExtension(Class clazz) { + return Control.getSingleton().getExtensionLoader().getExtension(clazz); + } + + @Override + public boolean canUnload() { + return true; + } + + @Override + public void unload() { + getExtension(ExtensionPlugNHack.class).setExtensionBreak(null); + } +} diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java index b05cbf234b3..3e1e2c80a0f 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.zap.extension.plugnhack.ClientsPanel; import org.zaproxy.zap.extension.plugnhack.MessageListTableModel; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java index 471fb431a23..c858a922e0e 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.zap.extension.brk.BreakpointsPanel; -import org.zaproxy.zap.extension.brk.ExtensionBreak; +import org.zaproxy.addon.brk.BreakpointsPanel; +import org.zaproxy.addon.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { From 20d4e314227125f6548c6f2af16384a8da670913 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 01:13:09 +0100 Subject: [PATCH 19/24] emptry commit Signed-off-by: aryangupta701 From 6bd584fcc55780a6b831bf0410af7364eea1080f Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 01:19:51 +0100 Subject: [PATCH 20/24] update plugNHack to use Brk addon Signed-off-by: aryangupta701 --- .../plugnhack/ExtensionPlugNHack.java | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 6634e3b428a..4f5ee3e30fb 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -159,7 +159,13 @@ public class ExtensionPlugNHack extends ExtensionAdaptor ExtensionBreak extBreak; - /* + static boolean coreBrkDisabled; + + static { + coreBrkDisabled = ExtensionBreak.class.getAnnotation(Deprecated.class) != null; + } + + /* * TODO * Handle mode */ @@ -214,14 +220,26 @@ private void startTimeoutThread() { @Override public void run() { this.setName("ZAP-pnh-timeout"); + // Can't init extBreak here - Control wont have been initialized + boolean ctrlInit = false; while (!shutdown) { try { sleep(poll); + + if (!ctrlInit && Control.getSingleton() != null && !coreBrkDisabled) { + extBreak = + (ExtensionBreak) + Control.getSingleton() + .getExtensionLoader() + .getExtension(ExtensionBreak.NAME); + ctrlInit = true; + } + if (extBreak != null && (extBreak.getBreakpointManagementInterface() - .isBreakRequest() - || extBreak.getBreakpointManagementInterface() - .isBreakResponse())) { + .isBreakRequest() + || extBreak.getBreakpointManagementInterface() + .isBreakResponse())) { // Dont timeout pages while global breakpoints set // TODO find a solution for custom break points too continue; @@ -280,6 +298,10 @@ public void hook(ExtensionHook extensionHook) { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // setup Breakpoints + if(!coreBrkDisabled) { + extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); + } + if (extBreak != null) { // setup custom breakpoint handler brkMessageHandler = @@ -327,6 +349,9 @@ public void unload() { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // clear up Breakpoints + if(!coreBrkDisabled) { + extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); + } if (extBreak != null) { extBreak.removeBreakpointsUiManager(getBrkManager()); } @@ -468,12 +493,12 @@ public boolean onHttpResponseReceive(HttpMessage msg) { + SCRIPT_START + this.getPnhScript() + SCRIPT_END - .replace(REPLACE_ROOT_TOKEN, this.getApiRoot()) - .replace(REPLACE_ID_TOKEN, page.getId()) - .replace( - REPLACE_NONCE, - API.getInstance() - .getLongLivedNonce(SCRIPT_API)) + .replace(REPLACE_ROOT_TOKEN, this.getApiRoot()) + .replace(REPLACE_ID_TOKEN, page.getId()) + .replace( + REPLACE_NONCE, + API.getInstance() + .getLongLivedNonce(SCRIPT_API)) + body.substring(endHeadTag); msg.setResponseBody(body); msg.getResponseHeader().setContentLength(body.length()); @@ -894,6 +919,13 @@ protected void messageChanged(ClientMessage msg) { protected ClientBreakpointsUiManagerInterface getBrkManager() { if (brkManager == null) { + if(!coreBrkDisabled) { + extBreak = + (ExtensionBreak) + Control.getSingleton() + .getExtensionLoader() + .getExtension(ExtensionBreak.NAME); + } if (extBreak != null) { brkManager = new ClientBreakpointsUiManagerInterface(this, extBreak); } @@ -943,8 +975,4 @@ public void setClientConfig(MonitoredPage page, String key, Object value) { cmsg.set("value", value); this.mpm.send(cmsg); } - - public void setExtensionBreak(ExtensionBreak brk) { - extBreak = brk; - } } From a8dcbf9454fa29f09c53561c633db22f12735630 Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Thu, 15 Feb 2024 01:33:04 +0100 Subject: [PATCH 21/24] update plugNHack to use Brk addon Signed-off-by: aryangupta701 --- .../plugnhack/ExtensionPlugNHack.java | 30 ++++++++++--------- .../plugnhack/brk/ExtensionPlugNHackBrk.java | 23 ++++++++++++-- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 4f5ee3e30fb..38641862e9e 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -165,7 +165,7 @@ public class ExtensionPlugNHack extends ExtensionAdaptor coreBrkDisabled = ExtensionBreak.class.getAnnotation(Deprecated.class) != null; } - /* + /* * TODO * Handle mode */ @@ -226,7 +226,9 @@ public void run() { try { sleep(poll); - if (!ctrlInit && Control.getSingleton() != null && !coreBrkDisabled) { + if (!ctrlInit + && Control.getSingleton() != null + && !coreBrkDisabled) { extBreak = (ExtensionBreak) Control.getSingleton() @@ -237,9 +239,9 @@ public void run() { if (extBreak != null && (extBreak.getBreakpointManagementInterface() - .isBreakRequest() - || extBreak.getBreakpointManagementInterface() - .isBreakResponse())) { + .isBreakRequest() + || extBreak.getBreakpointManagementInterface() + .isBreakResponse())) { // Dont timeout pages while global breakpoints set // TODO find a solution for custom break points too continue; @@ -298,7 +300,7 @@ public void hook(ExtensionHook extensionHook) { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // setup Breakpoints - if(!coreBrkDisabled) { + if (!coreBrkDisabled) { extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); } @@ -349,7 +351,7 @@ public void unload() { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // clear up Breakpoints - if(!coreBrkDisabled) { + if (!coreBrkDisabled) { extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); } if (extBreak != null) { @@ -493,12 +495,12 @@ public boolean onHttpResponseReceive(HttpMessage msg) { + SCRIPT_START + this.getPnhScript() + SCRIPT_END - .replace(REPLACE_ROOT_TOKEN, this.getApiRoot()) - .replace(REPLACE_ID_TOKEN, page.getId()) - .replace( - REPLACE_NONCE, - API.getInstance() - .getLongLivedNonce(SCRIPT_API)) + .replace(REPLACE_ROOT_TOKEN, this.getApiRoot()) + .replace(REPLACE_ID_TOKEN, page.getId()) + .replace( + REPLACE_NONCE, + API.getInstance() + .getLongLivedNonce(SCRIPT_API)) + body.substring(endHeadTag); msg.setResponseBody(body); msg.getResponseHeader().setContentLength(body.length()); @@ -919,7 +921,7 @@ protected void messageChanged(ClientMessage msg) { protected ClientBreakpointsUiManagerInterface getBrkManager() { if (brkManager == null) { - if(!coreBrkDisabled) { + if (!coreBrkDisabled) { extBreak = (ExtensionBreak) Control.getSingleton() diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java index 798e056eb7b..baceed17e3a 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java @@ -1,6 +1,24 @@ +/* + * Zed Attack Proxy (ZAP) and its related class files. + * + * ZAP is an HTTP/HTTPS proxy for assessing web application security. + * + * Copyright 2024 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.extension.plugnhack.brk; - import java.util.List; import org.parosproxy.paros.Constant; import org.parosproxy.paros.control.Control; @@ -32,7 +50,8 @@ public List> getDependencies() { @Override public void hook(ExtensionHook extensionHook) { - getExtension(ExtensionPlugNHack.class).setExtensionBreak(getExtension(ExtensionBreak.class)); + getExtension(ExtensionPlugNHack.class) + .setExtensionBreak(getExtension(ExtensionBreak.class)); } private static T getExtension(Class clazz) { From 04f3dbb43113d7bd85bd83e8f779727958e15c1a Mon Sep 17 00:00:00 2001 From: aryangupta701 Date: Tue, 27 Feb 2024 21:12:36 +0100 Subject: [PATCH 22/24] revert plugnhack changes Signed-off-by: aryangupta701 --- addOns/plugnhack/plugnhack.gradle.kts | 14 ---- .../plugnhack/ExtensionPlugNHack.java | 37 +++------- .../brk/ClientBreakpointMessage.java | 2 +- .../brk/ClientBreakpointMessageHandler.java | 4 +- .../ClientBreakpointsUiManagerInterface.java | 6 +- .../plugnhack/brk/ExtensionPlugNHackBrk.java | 70 ------------------- .../brk/PopupMenuAddBreakClient.java | 2 +- .../plugnhack/brk/PopupMenuEditBreak.java | 4 +- 8 files changed, 19 insertions(+), 120 deletions(-) delete mode 100644 addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java diff --git a/addOns/plugnhack/plugnhack.gradle.kts b/addOns/plugnhack/plugnhack.gradle.kts index df7829ca8c9..1c1f65d906b 100644 --- a/addOns/plugnhack/plugnhack.gradle.kts +++ b/addOns/plugnhack/plugnhack.gradle.kts @@ -31,19 +31,6 @@ zapAddOn { } } } - - register("org.zaproxy.zap.extension.plugnhack.brk.ExtensionPlugNHackBrk") { - classnames { - allowed.set(listOf("org.zaproxy.zap.extension.plugnhack.brk")) - } - dependencies { - addOns { - register("brk") { - version.set(">=0.1") - } - } - } - } } } @@ -56,5 +43,4 @@ zapAddOn { dependencies { zapAddOn("network") zapAddOn("requester") - zapAddOn("brk") } diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java index 38641862e9e..f28cf0332e2 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/ExtensionPlugNHack.java @@ -51,13 +51,13 @@ import org.parosproxy.paros.network.HttpMalformedHeaderException; import org.parosproxy.paros.network.HttpMessage; import org.parosproxy.paros.view.View; -import org.zaproxy.addon.brk.ExtensionBreak; import org.zaproxy.addon.network.ExtensionNetwork; import org.zaproxy.addon.network.server.ServerInfo; import org.zaproxy.zap.ZAP; import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiResponse; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.help.ExtensionHelp; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.httppanel.component.HttpPanelComponentInterface; @@ -157,14 +157,6 @@ public class ExtensionPlugNHack extends ExtensionAdaptor private ExtensionNetwork extensionNetwork; - ExtensionBreak extBreak; - - static boolean coreBrkDisabled; - - static { - coreBrkDisabled = ExtensionBreak.class.getAnnotation(Deprecated.class) != null; - } - /* * TODO * Handle mode @@ -222,13 +214,12 @@ public void run() { this.setName("ZAP-pnh-timeout"); // Can't init extBreak here - Control wont have been initialized boolean ctrlInit = false; + ExtensionBreak extBreak = null; while (!shutdown) { try { sleep(poll); - if (!ctrlInit - && Control.getSingleton() != null - && !coreBrkDisabled) { + if (!ctrlInit && Control.getSingleton() != null) { extBreak = (ExtensionBreak) Control.getSingleton() @@ -236,7 +227,6 @@ public void run() { .getExtension(ExtensionBreak.NAME); ctrlInit = true; } - if (extBreak != null && (extBreak.getBreakpointManagementInterface() .isBreakRequest() @@ -300,10 +290,7 @@ public void hook(ExtensionHook extensionHook) { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // setup Breakpoints - if (!coreBrkDisabled) { - extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); - } - + ExtensionBreak extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); if (extBreak != null) { // setup custom breakpoint handler brkMessageHandler = @@ -351,9 +338,7 @@ public void unload() { ExtensionLoader extLoader = Control.getSingleton().getExtensionLoader(); // clear up Breakpoints - if (!coreBrkDisabled) { - extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); - } + ExtensionBreak extBreak = (ExtensionBreak) extLoader.getExtension(ExtensionBreak.NAME); if (extBreak != null) { extBreak.removeBreakpointsUiManager(getBrkManager()); } @@ -921,13 +906,11 @@ protected void messageChanged(ClientMessage msg) { protected ClientBreakpointsUiManagerInterface getBrkManager() { if (brkManager == null) { - if (!coreBrkDisabled) { - extBreak = - (ExtensionBreak) - Control.getSingleton() - .getExtensionLoader() - .getExtension(ExtensionBreak.NAME); - } + ExtensionBreak extBreak = + (ExtensionBreak) + Control.getSingleton() + .getExtensionLoader() + .getExtension(ExtensionBreak.NAME); if (extBreak != null) { brkManager = new ClientBreakpointsUiManagerInterface(this, extBreak); } diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java index 34894dbac13..56b3b3fd590 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessage.java @@ -22,7 +22,7 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import org.parosproxy.paros.Constant; -import org.zaproxy.addon.brk.AbstractBreakPointMessage; +import org.zaproxy.zap.extension.brk.AbstractBreakPointMessage; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java index c98c494c287..7cef59bb4f5 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointMessageHandler.java @@ -19,8 +19,8 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.addon.brk.BreakpointManagementInterface; -import org.zaproxy.addon.brk.BreakpointMessageHandler2; +import org.zaproxy.zap.extension.brk.BreakpointManagementInterface; +import org.zaproxy.zap.extension.brk.BreakpointMessageHandler2; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java index 7a2b3024c9d..c09e0cc667d 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ClientBreakpointsUiManagerInterface.java @@ -19,9 +19,9 @@ */ package org.zaproxy.zap.extension.plugnhack.brk; -import org.zaproxy.addon.brk.BreakpointMessageInterface; -import org.zaproxy.addon.brk.BreakpointsUiManagerInterface; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointMessageInterface; +import org.zaproxy.zap.extension.brk.BreakpointsUiManagerInterface; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.httppanel.Message; import org.zaproxy.zap.extension.plugnhack.ClientMessage; import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java deleted file mode 100644 index baceed17e3a..00000000000 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/ExtensionPlugNHackBrk.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Zed Attack Proxy (ZAP) and its related class files. - * - * ZAP is an HTTP/HTTPS proxy for assessing web application security. - * - * Copyright 2024 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.extension.plugnhack.brk; - -import java.util.List; -import org.parosproxy.paros.Constant; -import org.parosproxy.paros.control.Control; -import org.parosproxy.paros.extension.Extension; -import org.parosproxy.paros.extension.ExtensionAdaptor; -import org.parosproxy.paros.extension.ExtensionHook; -import org.zaproxy.addon.brk.ExtensionBreak; -import org.zaproxy.zap.extension.plugnhack.ExtensionPlugNHack; - -public class ExtensionPlugNHackBrk extends ExtensionAdaptor { - - private static final List> DEPENDENCIES = - List.of(ExtensionPlugNHack.class, ExtensionBreak.class); - - @Override - public String getUIName() { - return Constant.messages.getString("quickstart.spider.name"); - } - - @Override - public String getDescription() { - return Constant.messages.getString("quickstart.spider.desc"); - } - - @Override - public List> getDependencies() { - return DEPENDENCIES; - } - - @Override - public void hook(ExtensionHook extensionHook) { - getExtension(ExtensionPlugNHack.class) - .setExtensionBreak(getExtension(ExtensionBreak.class)); - } - - private static T getExtension(Class clazz) { - return Control.getSingleton().getExtensionLoader().getExtension(clazz); - } - - @Override - public boolean canUnload() { - return true; - } - - @Override - public void unload() { - getExtension(ExtensionPlugNHack.class).setExtensionBreak(null); - } -} diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java index 3e1e2c80a0f..b05cbf234b3 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuAddBreakClient.java @@ -25,7 +25,7 @@ import org.apache.logging.log4j.Logger; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.ExtensionBreak; import org.zaproxy.zap.extension.plugnhack.ClientsPanel; import org.zaproxy.zap.extension.plugnhack.MessageListTableModel; diff --git a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java index c858a922e0e..471fb431a23 100644 --- a/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java +++ b/addOns/plugnhack/src/main/java/org/zaproxy/zap/extension/plugnhack/brk/PopupMenuEditBreak.java @@ -22,8 +22,8 @@ import java.awt.Component; import org.parosproxy.paros.Constant; import org.parosproxy.paros.extension.ExtensionPopupMenuItem; -import org.zaproxy.addon.brk.BreakpointsPanel; -import org.zaproxy.addon.brk.ExtensionBreak; +import org.zaproxy.zap.extension.brk.BreakpointsPanel; +import org.zaproxy.zap.extension.brk.ExtensionBreak; @SuppressWarnings("serial") public class PopupMenuEditBreak extends ExtensionPopupMenuItem { From 55c442800f525a8f95dfbbfc2fd7422959c894a7 Mon Sep 17 00:00:00 2001 From: Aryan Gupta Date: Sat, 23 Mar 2024 17:50:31 +0100 Subject: [PATCH 23/24] set break options handler in core Signed-off-by: Aryan Gupta --- .../org/zaproxy/addon/brk/ExtensionBreak.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java b/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java index 07a98a58374..ee895ff5c31 100644 --- a/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java +++ b/addOns/brk/src/main/java/org/zaproxy/addon/brk/ExtensionBreak.java @@ -22,6 +22,9 @@ import java.awt.Component; import java.awt.EventQueue; import java.awt.event.KeyEvent; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -43,6 +46,7 @@ import org.parosproxy.paros.extension.ExtensionHookView; import org.parosproxy.paros.extension.OptionsChangedListener; import org.parosproxy.paros.extension.SessionChangedListener; +import org.parosproxy.paros.extension.option.ExtensionOption; import org.parosproxy.paros.model.HistoryReference; import org.parosproxy.paros.model.OptionsParam; import org.parosproxy.paros.model.Session; @@ -115,6 +119,32 @@ public String getUIName() { @Override public void init() { serialisationRequiredListeners = Collections.synchronizedList(new ArrayList<>(1)); + try { + ExtensionOption extOption = + Control.getSingleton().getExtensionLoader().getExtension(ExtensionOption.class); + Class breakOptionsHandlerClass = + getClass() + .getClassLoader() + .loadClass("org.parosproxy.paros.extension.option.BreakOptionsHandler"); + Method method = + extOption + .getClass() + .getDeclaredMethod("setBreakOptionsHandler", breakOptionsHandlerClass); + method.invoke( + extOption, + Proxy.newProxyInstance( + breakOptionsHandlerClass.getClassLoader(), + new Class[] {breakOptionsHandlerClass}, + (proxy, m, args) -> { + getOptionsParam().setShowIgnoreFilesButtons((Boolean) args[0]); + return null; + })); + } catch (NoSuchMethodException + | IllegalAccessException + | InvocationTargetException + | ClassNotFoundException e) { + throw new RuntimeException(e); + } } public BreakpointManagementInterface getBreakpointManagementInterface() { From 6f516db4ccdc318242c01461963ca4321312e3c7 Mon Sep 17 00:00:00 2001 From: Aryan Gupta Date: Tue, 26 Mar 2024 15:20:15 +0100 Subject: [PATCH 24/24] Update addOns/brk/CHANGELOG.md Co-authored-by: Rick M Signed-off-by: Aryan Gupta --- addOns/brk/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/addOns/brk/CHANGELOG.md b/addOns/brk/CHANGELOG.md index bd46ab61fb1..35236720953 100644 --- a/addOns/brk/CHANGELOG.md +++ b/addOns/brk/CHANGELOG.md @@ -5,4 +5,3 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased -## [0.1.0] - 2024-01-14 \ No newline at end of file