postParameterList = new ArrayList<>();
- for (int i = 0; i < parameterCount; i++) {
- String parameter = body.substring(from, index);
- parameter = parameter.replace("&", "");
-
- String[] parameterSplit = parameter.split(Pattern.quote("="));
- if (parameterSplit.length > 1) {
- String name = parameterSplit[0];
- String value = parameterSplit[1];
- postParameterList.add(new KeyValuePair(name, value));
- from = index;
- index = body.indexOf("&", index + 1);
- if (index == -1) {
- index = body.length();
- }
- }
- }
- for (String keyword : Config.tokenKeywords) {
- for (KeyValuePair postParameter : postParameterList) {
- if (keyword.equals(postParameter.getName()) && TokenChecker.isValidJWT(postParameter.getValue())) {
- return postParameter;
- }
- }
- }
- return null;
- }
-
- @Override
- public String getToken() {
- return found ? token : "";
- }
-
- @Override
- public byte[] replaceToken(String newToken) {
- body = replaceTokenImpl(newToken, body);
- return getHelpers().buildHttpMessage(getHeaders(), body.getBytes());
- }
-
- public String replaceTokenImpl(String newToken, String body) {
- boolean replaced = false;
- // we cannot use the location of parameter, as the body might have changed, thus
- // we need to search for it again
- KeyValuePair postJWT = getJWTFromPostBody();
- for (String keyword : Config.tokenKeywords) {
- if (keyword.equals(postJWT.getName())) {
- String toReplace = postJWT.getNameAsParam() + postJWT.getValue();
- body = body.replace(toReplace, postJWT.getNameAsParam() + newToken);
- replaced = true;
- }
- }
- if (!replaced) {
- Output.outputError("Could not replace token in post body.");
- }
- return body;
- }
-
-}
diff --git a/src/burp/BurpExtender.java b/src/burp/BurpExtender.java
deleted file mode 100644
index f700f5c..0000000
--- a/src/burp/BurpExtender.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package burp;
-
-import app.controllers.ContextMenuController;
-import app.controllers.HighLightController;
-import app.controllers.JWTInterceptTabController;
-import app.controllers.JWTSuiteTabController;
-import app.controllers.JWTTabController;
-import app.helpers.Config;
-import app.helpers.Output;
-import gui.JWTInterceptTab;
-import gui.JWTSuiteTab;
-import gui.JWTViewTab;
-import gui.RSyntaxTextAreaFactory;
-import model.JWTInterceptModel;
-import model.JWTSuiteTabModel;
-import model.JWTTabModel;
-import model.Settings;
-
-public class BurpExtender implements IBurpExtender, IMessageEditorTabFactory {
-
- private IBurpExtenderCallbacks callbacks;
- private RSyntaxTextAreaFactory rSyntaxTextAreaFactory;
-
- @Override
- public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
- this.callbacks = callbacks;
-
- Output.initialise(callbacks.getStdout(), callbacks.getStderr());
- Output.output("JWT4B says hi!");
- rSyntaxTextAreaFactory = new RSyntaxTextAreaFactory(callbacks);
-
-
- callbacks.setExtensionName(Settings.EXTENSION_NAME);
- callbacks.registerMessageEditorTabFactory(this);
-
- Config.loadConfig();
-
- final HighLightController marker = new HighLightController(callbacks);
- callbacks.registerHttpListener(marker);
-
- // Suite Tab
- JWTSuiteTabModel jwtSTM = new JWTSuiteTabModel();
- JWTSuiteTab jwtST = new JWTSuiteTab(jwtSTM, rSyntaxTextAreaFactory);
- JWTSuiteTabController jstC = new JWTSuiteTabController(jwtSTM, jwtST);
- callbacks.addSuiteTab(jstC);
-
- // Context Menu
- ContextMenuController cmC = new ContextMenuController(jstC);
- callbacks.registerContextMenuFactory(cmC);
- }
-
- @Override
- public IMessageEditorTab createNewInstance(IMessageEditorController controller, boolean editable) {
- IMessageEditorTab jwtTC;
- if (editable) { // Intercept
- JWTInterceptModel jwtSTM = new JWTInterceptModel();
- JWTInterceptTab jwtST = new JWTInterceptTab(jwtSTM, rSyntaxTextAreaFactory);
- jwtTC = new JWTInterceptTabController(callbacks, jwtSTM, jwtST);
- } else {
- JWTTabModel jwtTM = new JWTTabModel();
- JWTViewTab jwtVT = new JWTViewTab(jwtTM, rSyntaxTextAreaFactory);
- jwtTC = new JWTTabController(callbacks, jwtTM, jwtVT);
- }
- return jwtTC;
- }
-
- public IBurpExtenderCallbacks getCallbacks() {
- return callbacks;
- }
-}
diff --git a/src/burp/api/montoya/BurpExtension.java b/src/burp/api/montoya/BurpExtension.java
new file mode 100644
index 0000000..c22a314
--- /dev/null
+++ b/src/burp/api/montoya/BurpExtension.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya;
+
+/**
+ * All extensions must implement this interface.
+ *
+ * Implementations must be declared public, and must provide a default (public, no-argument) constructor.
+ */
+public interface BurpExtension
+{
+ /**
+ * Invoked when the extension is loaded. Any registered handlers will only be enabled once this method has completed.
+ *
+ * @param api The API implementation to access the functionality of Burp Suite.
+ */
+ void initialize(MontoyaApi api);
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/MontoyaApi.java b/src/burp/api/montoya/MontoyaApi.java
new file mode 100644
index 0000000..23190ad
--- /dev/null
+++ b/src/burp/api/montoya/MontoyaApi.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya;
+
+import burp.api.montoya.burpsuite.BurpSuite;
+import burp.api.montoya.collaborator.Collaborator;
+import burp.api.montoya.comparer.Comparer;
+import burp.api.montoya.decoder.Decoder;
+import burp.api.montoya.extension.Extension;
+import burp.api.montoya.http.Http;
+import burp.api.montoya.intruder.Intruder;
+import burp.api.montoya.logging.Logging;
+import burp.api.montoya.organizer.Organizer;
+import burp.api.montoya.persistence.Persistence;
+import burp.api.montoya.proxy.Proxy;
+import burp.api.montoya.repeater.Repeater;
+import burp.api.montoya.scanner.Scanner;
+import burp.api.montoya.scope.Scope;
+import burp.api.montoya.sitemap.SiteMap;
+import burp.api.montoya.ui.UserInterface;
+import burp.api.montoya.utilities.Utilities;
+import burp.api.montoya.websocket.WebSockets;
+
+/**
+ * This interface is used by Burp Suite to pass a set of methods to extensions that can be used
+ * to perform various actions within Burp. When an extension is loaded, Burp invokes its
+ * {@link BurpExtension#initialize(MontoyaApi)} method and passes an instance
+ * of the {@link MontoyaApi} interface. The extension may then invoke the
+ * methods of this interface as required in order to extend Burp's
+ * functionality.
+ */
+public interface MontoyaApi
+{
+ /**
+ * Access functionality related to the Burp Suite application.
+ *
+ * @return An implementation of the BurpSuite interface which exposes application-level functionality.
+ */
+ BurpSuite burpSuite();
+
+ /**
+ * [Professional only] Access the functionality of the Collaborator.
+ *
+ * @return An implementation of the Collaborator interface which exposes Collaborator functionality.
+ */
+ Collaborator collaborator();
+
+ /**
+ * Access the functionality of the Comparer.
+ *
+ * @return An implementation of the Comparer interface which exposes Comparer functionality.
+ */
+ Comparer comparer();
+
+ /**
+ * Access the functionality of the Decoder.
+ *
+ * @return An implementation of the Decoder interface which exposes Decoder functionality.
+ */
+ Decoder decoder();
+
+ /**
+ * Access functionality related to your extension.
+ *
+ * @return An implementation of the Extension interface which exposes extension functionality.
+ */
+ Extension extension();
+
+ /**
+ * Access the functionality related to HTTP requests and responses.
+ *
+ * @return An implementation of the Http interface which exposes http functionality.
+ */
+ Http http();
+
+ /**
+ * Access the functionality of the Intruder.
+ *
+ * @return An implementation of the Comparer interface which exposes Comparer functionality.
+ */
+ Intruder intruder();
+
+ /**
+ * Access the functionality related to logging and events.
+ *
+ * @return An implementation of the Logging interface which exposes logging functionality.
+ */
+ Logging logging();
+
+ /**
+ * Access the functionality of the Organizer.
+ *
+ * @return An implementation of the Organizer interface which exposes Organizer functionality.
+ */
+ Organizer organizer();
+
+ /**
+ * Access the functionality related to persistence.
+ *
+ * @return An implementation of the Persistence interface which exposes persistence functionality.
+ */
+ Persistence persistence();
+
+ /**
+ * Access the functionality of the Proxy.
+ *
+ * @return An implementation of the Proxy interface which exposes Proxy functionality.
+ */
+ Proxy proxy();
+
+ /**
+ * Access the functionality of the Repeater.
+ *
+ * @return An implementation of the Repeater interface which exposes Repeater functionality.
+ */
+ Repeater repeater();
+
+ /**
+ * [Professional only] Access the functionality of the Scanner.
+ *
+ * @return An implementation of the Scanner interface which exposes Scanner functionality.
+ */
+ Scanner scanner();
+
+ /**
+ * Access the functionality related to Burp's suite-wide target scope.
+ *
+ * @return An implementation of the Scope interface which exposes scope functionality.
+ */
+ Scope scope();
+
+ /**
+ * Access the functionality of the Site Map.
+ *
+ * @return An implementation of the SiteMap interface which exposes sitemap functionality.
+ */
+ SiteMap siteMap();
+
+ /**
+ * Access the functionality related to the user interface.
+ *
+ * @return An implementation of the UserInterface interface which exposes user interface functionality.
+ */
+ UserInterface userInterface();
+
+ /**
+ * Access additional utilities.
+ *
+ * @return An implementation of the Utilities interface which exposes additional utilities.
+ */
+ Utilities utilities();
+
+ /**
+ * Access the functionality related to WebSockets and messages.
+ *
+ * @return An implementation of the WebSockets interface which exposes WebSocket functionality.
+ */
+ WebSockets websockets();
+}
diff --git a/src/burp/api/montoya/burpsuite/BurpSuite.java b/src/burp/api/montoya/burpsuite/BurpSuite.java
new file mode 100644
index 0000000..5aa4901
--- /dev/null
+++ b/src/burp/api/montoya/burpsuite/BurpSuite.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.burpsuite;
+
+import burp.api.montoya.core.Version;
+
+import java.util.List;
+
+/**
+ * Provides access to functionality related to the Burp Suite application.
+ */
+public interface BurpSuite
+{
+ /**
+ * Retrieve information about the version of Burp in which the
+ * extension is running. It can be used by extensions to dynamically adjust
+ * their behavior depending on the functionality and APIs supported by the
+ * current version.
+ *
+ * @return The Burp {@link Version}.
+ */
+ Version version();
+
+ /**
+ * Export current project-level configuration in JSON format.
+ * This is the same format that can be saved and loaded via
+ * the Burp user interface. To include only certain sections of the
+ * configuration, you can optionally supply the path to each section that
+ * should be included, for example: "project_options.connections". If no
+ * paths are provided, then the entire configuration will be saved.
+ *
+ * @param paths A list of Strings representing the path to each
+ * configuration section that should be included.
+ *
+ * @return A String representing the current configuration in JSON format.
+ */
+ String exportProjectOptionsAsJson(String... paths);
+
+ /**
+ * Import a new project-level configuration from the JSON String provided.
+ * This is the same format that can be saved and
+ * loaded via the Burp user interface. Partial configurations are
+ * acceptable, and any settings not specified will be left unmodified.
+ *
+ * Any user-level configuration options contained in the input will be
+ * ignored.
+ *
+ * @param json A JSON String containing the new configuration.
+ */
+ void importProjectOptionsFromJson(String json);
+
+ /**
+ * Export current user-level configuration in JSON format.
+ * This is the same format that can be saved and loaded via
+ * the Burp user interface. To include only certain sections of the
+ * configuration, you can optionally supply the path to each section that
+ * should be included, for example: "user_options.connections". If no
+ * paths are provided, then the entire configuration will be saved.
+ *
+ * @param paths A list of Strings representing the path to each
+ * configuration section that should be included.
+ *
+ * @return A String representing the current configuration in JSON format.
+ */
+ String exportUserOptionsAsJson(String... paths);
+
+ /**
+ * Import a new user-level configuration from the JSON String provided.
+ * This is the same format that can be saved and
+ * loaded via the Burp user interface. Partial configurations are
+ * acceptable, and any settings not specified will be left unmodified.
+ *
+ * Any project-level configuration options contained in the input will be
+ * ignored.
+ *
+ * @param json A JSON String containing the new configuration.
+ */
+ void importUserOptionsFromJson(String json);
+
+ /**
+ * Command line arguments that were passed to Burp on startup.
+ *
+ * @return The command line arguments that were passed to Burp on startup.
+ */
+ List commandLineArguments();
+
+ /**
+ * Shut down Burp programmatically.
+ *
+ * @param options The shutdown options for shutting down Burp
+ * programmatically. For example {@link ShutdownOptions#PROMPT_USER} will
+ * display a dialog to the user allowing them to confirm or cancel the
+ * shutdown.
+ */
+ void shutdown(ShutdownOptions... options);
+
+ /**
+ * Access the functionality of the task execution engine.
+ *
+ * @return An implementation of the TaskExecutionEngine interface which exposes task execution engine functionality.
+ */
+ TaskExecutionEngine taskExecutionEngine();
+}
diff --git a/src/burp/api/montoya/burpsuite/ShutdownOptions.java b/src/burp/api/montoya/burpsuite/ShutdownOptions.java
new file mode 100644
index 0000000..e3011b9
--- /dev/null
+++ b/src/burp/api/montoya/burpsuite/ShutdownOptions.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.burpsuite;
+
+/**
+ * Shutdown options that can be used when calling {@link BurpSuite#shutdown(ShutdownOptions...)}.
+ */
+public enum ShutdownOptions
+{
+ /**
+ * Display a dialog to the user allowing them to confirm or cancel the shutdown
+ */
+ PROMPT_USER
+}
diff --git a/src/burp/api/montoya/burpsuite/TaskExecutionEngine.java b/src/burp/api/montoya/burpsuite/TaskExecutionEngine.java
new file mode 100644
index 0000000..086855e
--- /dev/null
+++ b/src/burp/api/montoya/burpsuite/TaskExecutionEngine.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.burpsuite;
+
+/**
+ * Provides access to the task execution engine.
+ */
+public interface TaskExecutionEngine
+{
+ /**
+ * Task execution engine state
+ */
+ enum TaskExecutionEngineState
+ {
+ RUNNING, PAUSED
+ }
+
+ /**
+ * Retrieves the current state of the task execution engine.
+ *
+ * @return current state
+ */
+ TaskExecutionEngineState getState();
+
+ /**
+ * Sets the task execution engine state
+ *
+ * @param state new state
+ */
+ void setState(TaskExecutionEngineState state);
+}
diff --git a/src/burp/api/montoya/collaborator/Collaborator.java b/src/burp/api/montoya/collaborator/Collaborator.java
new file mode 100644
index 0000000..5cdbe90
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/Collaborator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * [Professional only] Provides access to the facilities of Burp Collaborator.
+ */
+public interface Collaborator
+{
+ /**
+ * Create a new Burp Collaborator client
+ * that can be used to generate Burp Collaborator payloads and poll the
+ * Collaborator server for any network interactions that result from using
+ * those payloads.
+ *
+ * @return A new instance of {@link CollaboratorClient} that can be used to
+ * generate Collaborator payloads and retrieve interactions.
+ */
+ CollaboratorClient createClient();
+
+ /**
+ * Restore a {@link CollaboratorClient} from a previous
+ * session. This allows you to retrieve the interactions that were identified
+ * from a specific payloads.
+ *
+ * @param secretKey The key to restore the {@link CollaboratorClient} from the previous session.
+ *
+ * @return A new instance of {@link CollaboratorClient} that can be used to
+ * generate Collaborator payloads and retrieve interactions.
+ */
+ CollaboratorClient restoreClient(SecretKey secretKey);
+
+ /**
+ * Obtain Burp's default Collaborator payload generator.
+ * This enables you to generate Collaborator payloads that are linked to the Collaborator tab.
+ * Any interactions are shown in the Collaborator results tab that was open when the payload was generated.
+ *
+ * @return The current instance of Burp's default {@link CollaboratorPayloadGenerator}.
+ */
+ CollaboratorPayloadGenerator defaultPayloadGenerator();
+}
diff --git a/src/burp/api/montoya/collaborator/CollaboratorClient.java b/src/burp/api/montoya/collaborator/CollaboratorClient.java
new file mode 100644
index 0000000..85adbf3
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/CollaboratorClient.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import java.util.List;
+
+/**
+ * Burp Collaborator client
+ * that can be used to generate Burp Collaborator payloads and poll the
+ * Collaborator server for any network interactions that result from using
+ * those payloads. Extensions can obtain new instances of this class by
+ * calling {@link Collaborator#createClient()}.
+ *
+ * Note that each Burp Collaborator client is tied to the Collaborator
+ * server configuration that was in place at the time the client was created.
+ *
+ */
+public interface CollaboratorClient extends CollaboratorPayloadGenerator
+{
+ /**
+ * Generate new Burp Collaborator payloads. Options
+ * can be specified to alter the way the payloads are generated. If no
+ * options are specified, generated payloads will include the server
+ * location.
+ *
+ * @param options The optional payload options to apply
+ *
+ * @return The generated payload.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ @Override
+ CollaboratorPayload generatePayload(PayloadOption... options);
+
+ /**
+ * Generate new Burp Collaborator payloads with custom data.
+ * The custom data can be retrieved from any {@link Interaction} triggered.
+ * Options can be specified to alter the way the payloads are generated. If no
+ * options are specified, generated payloads will include the server location.
+ *
+ * @param customData The custom data to add to the payload. Maximum size is 16 characters. Must be alphanumeric.
+ * @param options The optional payload options to apply
+ *
+ * @return The generated payload.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ CollaboratorPayload generatePayload(String customData, PayloadOption... options);
+
+ /**
+ * Retrieve all Collaborator server interactions
+ * resulting from payloads that were generated for this client.
+ *
+ * @return The Collaborator interactions that have occurred resulting from
+ * payloads that were generated for this client.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ List getAllInteractions();
+
+ /**
+ * Retrieve filtered Collaborator server
+ * interactions resulting from payloads that were generated for this
+ * client. Only interactions matching the supplied filter will be returned.
+ *
+ * @param filter The filter that will be applied to each interaction.
+ *
+ * @return The filtered Collaborator interactions resulting from payloads
+ * that were generated for this client.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ List getInteractions(InteractionFilter filter);
+
+ /**
+ * Retrieve the details of the Collaborator server
+ * associated with this client.
+ *
+ * @return The Collaborator server details.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ CollaboratorServer server();
+
+ /**
+ * Secret key that is associated with this client context.
+ * The key can be used to re-create this client again with the interaction data if required.
+ *
+ * @return The {@link SecretKey} that is associated with this Collaborator client.
+ */
+ SecretKey getSecretKey();
+}
diff --git a/src/burp/api/montoya/collaborator/CollaboratorPayload.java b/src/burp/api/montoya/collaborator/CollaboratorPayload.java
new file mode 100644
index 0000000..1e48c9b
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/CollaboratorPayload.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import java.util.Optional;
+
+/**
+ * Burp Collaborator payload.
+ */
+public interface CollaboratorPayload
+{
+ /**
+ * Payload's interaction id.
+ *
+ * @return The interaction id of the payload.
+ */
+ InteractionId id();
+
+ /**
+ * Custom data from the payload.
+ *
+ * @return The payload's custom data.
+ */
+ Optional customData();
+
+ /**
+ * Optional instance of CollaboratorServer describing the
+ * server location for this payload. If the payload was generated without
+ * the server location this method will return an empty Optional.
+ *
+ * @return Details of the collaborator server referenced in the payload
+ * or empty if the payload was generated without the server location.
+ */
+ Optional server();
+
+ /**
+ * The payload.
+ *
+ * @return The payload string.
+ */
+ @Override
+ String toString();
+}
diff --git a/src/burp/api/montoya/collaborator/CollaboratorPayloadGenerator.java b/src/burp/api/montoya/collaborator/CollaboratorPayloadGenerator.java
new file mode 100644
index 0000000..01d0045
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/CollaboratorPayloadGenerator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Burp Collaborator payload generator
+ * that can be used to generate Burp Collaborator payloads.
+ */
+public interface CollaboratorPayloadGenerator
+{
+ /**
+ * Generate new Burp Collaborator payloads. Options
+ * can be specified to alter the way the payloads are generated. If no
+ * options are specified, generated payloads will include the server
+ * location.
+ *
+ * @param options The optional payload options to apply
+ *
+ * @return The generated payload.
+ *
+ * @throws IllegalStateException if Burp Collaborator is disabled
+ */
+ CollaboratorPayload generatePayload(PayloadOption... options);
+}
diff --git a/src/burp/api/montoya/collaborator/CollaboratorServer.java b/src/burp/api/montoya/collaborator/CollaboratorServer.java
new file mode 100644
index 0000000..93d7410
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/CollaboratorServer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Provides details of the Collaborator server associated with
+ * this client.
+ */
+public interface CollaboratorServer
+{
+ /**
+ * Address of the Collaborator server.
+ *
+ * @return The hostname or IP address of the Collaborator server.
+ */
+ String address();
+
+ /**
+ * Indicates whether the server address is an IP address.
+ *
+ * @return {@code true} if the address is an IP address; {@code false}
+ * otherwise.
+ */
+ boolean isLiteralAddress();
+}
diff --git a/src/burp/api/montoya/collaborator/DnsDetails.java b/src/burp/api/montoya/collaborator/DnsDetails.java
new file mode 100644
index 0000000..245b4ad
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/DnsDetails.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import burp.api.montoya.core.ByteArray;
+
+/**
+ * Provides information about a DNS interaction detected by Burp
+ * Collaborator.
+ */
+public interface DnsDetails
+{
+ /**
+ * DNS query type.
+ *
+ * @return The type of DNS query performed by the interaction.
+ */
+ DnsQueryType queryType();
+
+ /**
+ * Raw DNS query.
+ *
+ * @return The raw DNS query sent to the Collaborator server.
+ */
+ ByteArray query();
+}
diff --git a/src/burp/api/montoya/collaborator/DnsQueryType.java b/src/burp/api/montoya/collaborator/DnsQueryType.java
new file mode 100644
index 0000000..1c4870b
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/DnsQueryType.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Domain Name System (DNS) query types.
+ */
+public enum DnsQueryType
+{
+ /**
+ * Address Record
+ */
+ A,
+ /**
+ * IPv6 address record
+ */
+ AAAA,
+ /**
+ * All cached records
+ */
+ ALL,
+ /**
+ * Certification Authority Authorization
+ */
+ CAA,
+ /**
+ * Canonical name record
+ */
+ CNAME,
+ /**
+ * DNS Key record
+ */
+ DNSKEY,
+ /**
+ * Delegation signer
+ */
+ DS,
+ /**
+ * Host Information
+ */
+ HINFO,
+ /**
+ * HTTPS Binding
+ */
+ HTTPS,
+ /**
+ * Mail exchange record
+ */
+ MX,
+ /**
+ * Naming Authority Pointer
+ */
+ NAPTR,
+ /**
+ * Name Server Record
+ */
+ NS,
+ /**
+ * PTR Resource Record
+ */
+ PTR,
+ /**
+ * Start of authority record
+ */
+ SOA,
+ /**
+ * Service locator
+ */
+ SRV,
+ /**
+ * Text record
+ */
+ TXT,
+ /**
+ * Unknown / Not Mapped / Obsolete
+ */
+ UNKNOWN
+
+}
diff --git a/src/burp/api/montoya/collaborator/HttpDetails.java b/src/burp/api/montoya/collaborator/HttpDetails.java
new file mode 100644
index 0000000..004fe32
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/HttpDetails.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import burp.api.montoya.http.HttpProtocol;
+import burp.api.montoya.http.message.HttpRequestResponse;
+
+/**
+ * Provides information about an HTTP interaction detected by
+ * Burp Collaborator.
+ */
+public interface HttpDetails
+{
+ /**
+ * HTTP protocol.
+ *
+ * @return The HTTP protocol used by the interaction.
+ */
+ HttpProtocol protocol();
+
+ /**
+ * HTTP request and response.
+ *
+ * @return The HTTP request sent to the Collaborator server and the
+ * server's response.
+ */
+ HttpRequestResponse requestResponse();
+}
diff --git a/src/burp/api/montoya/collaborator/Interaction.java b/src/burp/api/montoya/collaborator/Interaction.java
new file mode 100644
index 0000000..130d022
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/Interaction.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import java.net.InetAddress;
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+/**
+ * Provides details of an interaction with the Burp Collaborator
+ * server.
+ */
+public interface Interaction
+{
+ /**
+ * Interaction id.
+ *
+ * @return The interaction id.
+ */
+ InteractionId id();
+
+ /**
+ * Interaction Type.
+ *
+ * @return The type of interaction.
+ */
+ InteractionType type();
+
+ /**
+ * Timestamp of the interaction.
+ *
+ * @return The timestamp of the interaction.
+ */
+ ZonedDateTime timeStamp();
+
+ /**
+ * Client IP address of the interaction.
+ *
+ * @return The IP address of the client performing the interaction.
+ */
+ InetAddress clientIp();
+
+ /**
+ * Client port of the interaction.
+ *
+ * @return The port of the client initiating the interaction.
+ */
+ int clientPort();
+
+ /**
+ * DNS interaction details.
+ *
+ * @return Details of the DNS interaction or empty if the interaction was
+ * not DNS.
+ */
+ Optional dnsDetails();
+
+ /**
+ * HTTP interaction details.
+ *
+ * @return Details of the HTTP interaction or empty if the interaction was
+ * not HTTP.
+ */
+ Optional httpDetails();
+
+ /**
+ * SMTP interaction details.
+ *
+ * @return Details of the SMTP interaction or empty if the interaction was
+ * not SMTP.
+ */
+ Optional smtpDetails();
+
+ /**
+ * Custom data from the payload.
+ *
+ * @return The custom data.
+ */
+ Optional customData();
+}
diff --git a/src/burp/api/montoya/collaborator/InteractionFilter.java b/src/burp/api/montoya/collaborator/InteractionFilter.java
new file mode 100644
index 0000000..793b431
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/InteractionFilter.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Provides a filtering mechanism for use when retrieving
+ * interactions from the Burp Collaborator server.
+ * Helper methods are provided to create filters based on the interaction id
+ * and the payload.
+ */
+public interface InteractionFilter
+{
+ /**
+ * This method is invoked for each interaction retrieved from the
+ * Collaborator server and determines whether the interaction should be
+ * included in the list of interactions returned.
+ *
+ * @param server The collaborator server that received the interaction.
+ * @param interaction The interaction details.
+ *
+ * @return {@code true} if the interaction should be included,
+ * {@code false} if not.
+ */
+ boolean matches(CollaboratorServer server, Interaction interaction);
+
+ /**
+ * Construct a InteractionFilter that matches any
+ * interaction with the specified interaction id.
+ *
+ * @param id The interaction id.
+ *
+ * @return {@code true} if the interaction has the specified id,
+ * {@code false} if not.
+ */
+ static InteractionFilter interactionIdFilter(String id)
+ {
+ return FACTORY.interactionIdFilter(id);
+ }
+
+ /**
+ * Construct an InteractionFilter that matches any
+ * interaction with the specified payload.
+ *
+ * @param payload The payload.
+ *
+ * @return {@code true} if the interaction has the specified payload,
+ * {@code false} if not.
+ */
+ static InteractionFilter interactionPayloadFilter(String payload)
+ {
+ return FACTORY.interactionPayloadFilter(payload);
+ }
+}
diff --git a/src/burp/api/montoya/collaborator/InteractionId.java b/src/burp/api/montoya/collaborator/InteractionId.java
new file mode 100644
index 0000000..8ce42ad
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/InteractionId.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+
+/**
+ * Burp Collaborator interaction id.
+ */
+public interface InteractionId
+{
+ /**
+ * Interaction id.
+ *
+ * @return The interaction id string.
+ */
+ @Override
+ String toString();
+}
diff --git a/src/burp/api/montoya/collaborator/InteractionType.java b/src/burp/api/montoya/collaborator/InteractionType.java
new file mode 100644
index 0000000..5d7352f
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/InteractionType.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Possible types of interaction with Burp Collaborator.
+ */
+public enum InteractionType
+{
+ /**
+ * Domain Name System
+ */
+ DNS,
+ /**
+ * Hypertext Transfer Protocol
+ */
+ HTTP,
+ /**
+ * Simple Mail Transfer Protocol
+ */
+ SMTP
+}
diff --git a/src/burp/api/montoya/collaborator/PayloadOption.java b/src/burp/api/montoya/collaborator/PayloadOption.java
new file mode 100644
index 0000000..6dba718
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/PayloadOption.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Options that can be specified when generating Burp Collaborator payloads.
+ */
+public enum PayloadOption
+{
+ /**
+ * Generate a payload excluding the server location
+ */
+ WITHOUT_SERVER_LOCATION
+}
diff --git a/src/burp/api/montoya/collaborator/SecretKey.java b/src/burp/api/montoya/collaborator/SecretKey.java
new file mode 100644
index 0000000..f3f634a
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/SecretKey.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Secret key that is associated with a {@link CollaboratorClient}
+ */
+public interface SecretKey
+{
+ /**
+ * Secret key in string form.
+ *
+ * @return The base64 encoded secret key.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create an instance of {@link SecretKey} which
+ * you will be able to use to restore a previously created {@link CollaboratorClient}
+ * with the {@link Collaborator#restoreClient(SecretKey)} method.
+ *
+ * @param encodedKey The base64 encoded raw secret key.
+ *
+ * @return An instance of {@link SecretKey} wrapping the provided secret key.
+ */
+ static SecretKey secretKey(String encodedKey)
+ {
+ return FACTORY.secretKey(encodedKey);
+ }
+}
diff --git a/src/burp/api/montoya/collaborator/SmtpDetails.java b/src/burp/api/montoya/collaborator/SmtpDetails.java
new file mode 100644
index 0000000..6826f76
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/SmtpDetails.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * SMTP interaction detected by Burp Collaborator.
+ */
+public interface SmtpDetails
+{
+ /**
+ * SMTP protocol.
+ *
+ * @return The protocol used by the interaction.
+ */
+ SmtpProtocol protocol();
+
+ /**
+ * SMTP conversation.
+ *
+ * @return The SMTP conversation between the client and the Collaborator
+ * server.
+ */
+ String conversation();
+}
diff --git a/src/burp/api/montoya/collaborator/SmtpProtocol.java b/src/burp/api/montoya/collaborator/SmtpProtocol.java
new file mode 100644
index 0000000..c498b1e
--- /dev/null
+++ b/src/burp/api/montoya/collaborator/SmtpProtocol.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.collaborator;
+
+/**
+ * Simple Mail Transfer Protocol (SMTP) protocols.
+ */
+public enum SmtpProtocol
+{
+ /**
+ * Simple Mail Transfer Protocol
+ */
+ SMTP,
+ /**
+ * Simple Mail Transfer Protocol Secure
+ */
+ SMTPS
+}
diff --git a/src/burp/api/montoya/comparer/Comparer.java b/src/burp/api/montoya/comparer/Comparer.java
new file mode 100644
index 0000000..94bf555
--- /dev/null
+++ b/src/burp/api/montoya/comparer/Comparer.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.comparer;
+
+import burp.api.montoya.core.ByteArray;
+
+/**
+ * Provides access to the functionality of the Comparer tool.
+ */
+public interface Comparer
+{
+ /**
+ * Send data to the Comparer tool.
+ *
+ * @param data The data to be sent to Comparer.
+ */
+ void sendToComparer(ByteArray... data);
+}
diff --git a/src/burp/api/montoya/core/Annotations.java b/src/burp/api/montoya/core/Annotations.java
new file mode 100644
index 0000000..5fc447f
--- /dev/null
+++ b/src/burp/api/montoya/core/Annotations.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Annotations stored with requests and responses in Burp Suite.
+ */
+public interface Annotations
+{
+ /**
+ * @return the notes
+ */
+ String notes();
+
+ /**
+ * @return True if there are any notes for this HTTP request and response.
+ */
+ boolean hasNotes();
+
+ /**
+ * @return True if there is a highlight color for this HTTP request and response.
+ */
+ boolean hasHighlightColor();
+
+ /**
+ * Set (mutate) the current annotations notes value
+ *
+ * @param notes the notes to set on the current annotations
+ */
+ void setNotes(String notes);
+
+ /**
+ * @return the highlight color;
+ */
+ HighlightColor highlightColor();
+
+ /**
+ * Set (mutate) the current annotations highlight color value
+ *
+ * @param highlightColor the highlight color to set on the current annotations
+ */
+ void setHighlightColor(HighlightColor highlightColor);
+
+ /**
+ * Create a copy of the annotations with new notes.
+ *
+ * @param notes The new notes.
+ *
+ * @return The new annotations.
+ */
+ Annotations withNotes(String notes);
+
+ /**
+ * Create a copy of the annotations with a new highlight color.
+ *
+ * @param highlightColor The new highlight color.
+ *
+ * @return The new annotations.
+ */
+ Annotations withHighlightColor(HighlightColor highlightColor);
+
+ /**
+ * Create a new empty annotations.
+ *
+ * @return The annotations.
+ */
+ static Annotations annotations()
+ {
+ return FACTORY.annotations();
+ }
+
+ /**
+ * Create a new annotations with notes.
+ *
+ * @param notes The notes of the annotations
+ *
+ * @return The annotations.
+ */
+ static Annotations annotations(String notes)
+ {
+ return FACTORY.annotations(notes);
+ }
+
+ /**
+ * Create a new annotations with a highlight color.
+ *
+ * @param highlightColor The highlight color of the annotations
+ *
+ * @return The annotations.
+ */
+ static Annotations annotations(HighlightColor highlightColor)
+ {
+ return FACTORY.annotations(highlightColor);
+ }
+
+ /**
+ * Create a new annotations with notes and a highlight color.
+ *
+ * @param notes The notes of the annotations
+ * @param highlightColor The highlight color of the annotations
+ *
+ * @return The annotations.
+ */
+ static Annotations annotations(String notes, HighlightColor highlightColor)
+ {
+ return FACTORY.annotations(notes, highlightColor);
+ }
+}
diff --git a/src/burp/api/montoya/core/BurpSuiteEdition.java b/src/burp/api/montoya/core/BurpSuiteEdition.java
new file mode 100644
index 0000000..11f35ba
--- /dev/null
+++ b/src/burp/api/montoya/core/BurpSuiteEdition.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Editions of Burp Suite.
+ */
+public enum BurpSuiteEdition
+{
+ /**
+ * Burp Suite professional edition
+ */
+ PROFESSIONAL("Professional"),
+ /**
+ * Burp Suite community edition
+ */
+ COMMUNITY_EDITION("Community Edition"),
+ /**
+ * Burp Suite enterprise edition
+ */
+ ENTERPRISE_EDITION("Enterprise Edition");
+
+ private final String displayName;
+
+ BurpSuiteEdition(String displayName)
+ {
+ this.displayName = displayName;
+ }
+
+ /**
+ * @return displayName for this edition of Burp Suite.
+ */
+ public String displayName()
+ {
+ return displayName;
+ }
+}
diff --git a/src/burp/api/montoya/core/ByteArray.java b/src/burp/api/montoya/core/ByteArray.java
new file mode 100644
index 0000000..3cfcb3a
--- /dev/null
+++ b/src/burp/api/montoya/core/ByteArray.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+
+import java.util.regex.Pattern;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp ByteArray with various methods for querying and manipulating byte arrays.
+ */
+public interface ByteArray extends Iterable
+{
+ /**
+ * Access the byte stored at the provided index.
+ *
+ * @param index Index of the byte to be retrieved.
+ *
+ * @return The byte at the index.
+ */
+ byte getByte(int index);
+
+ /**
+ * Sets the byte at the provided index to the provided byte.
+ *
+ * @param index Index of the byte to be set.
+ * @param value The byte to be set.
+ */
+ void setByte(int index, byte value);
+
+ /**
+ * Sets the byte at the provided index to the provided narrowed integer value.
+ *
+ * @param index Index of the byte to be set.
+ * @param value The integer value to be set after a narrowing primitive conversion to a byte.
+ */
+ void setByte(int index, int value);
+
+ /**
+ * Sets bytes starting at the specified index to the provided bytes.
+ *
+ * @param index The index of the first byte to set.
+ * @param data The byte[] or sequence of bytes to be set.
+ */
+ void setBytes(int index, byte... data);
+
+ /**
+ * Sets bytes starting at the specified index to the provided integers after narrowing primitive conversion to bytes.
+ *
+ * @param index The index of the first byte to set.
+ * @param data The int[] or the sequence of integers to be set after a narrowing primitive conversion to bytes.
+ */
+ void setBytes(int index, int... data);
+
+ /**
+ * Sets bytes starting at the specified index to the provided bytes.
+ *
+ * @param index The index of the first byte to set.
+ * @param byteArray The {@code ByteArray} object holding the provided bytes.
+ */
+ void setBytes(int index, ByteArray byteArray);
+
+ /**
+ * Number of bytes stored in the {@code ByteArray}.
+ *
+ * @return Length of the {@code ByteArray}.
+ */
+ int length();
+
+ /**
+ * Copy of all bytes
+ *
+ * @return Copy of all bytes.
+ */
+ byte[] getBytes();
+
+ /**
+ * New ByteArray with all bytes between the start index (inclusive) and the end index (exclusive).
+ *
+ * @param startIndexInclusive The inclusive start index of retrieved range.
+ * @param endIndexExclusive The exclusive end index of retrieved range.
+ *
+ * @return ByteArray containing all bytes in the specified range.
+ */
+ ByteArray subArray(int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * New ByteArray with all bytes in the specified range.
+ *
+ * @param range The {@link Range} of bytes to be returned.
+ *
+ * @return ByteArray containing all bytes in the specified range.
+ */
+ ByteArray subArray(Range range);
+
+ /**
+ * Create a copy of the {@code ByteArray}
+ *
+ * @return New {@code ByteArray} with a copy of the wrapped bytes.
+ */
+ ByteArray copy();
+
+ /**
+ * Create a copy of the {@code ByteArray} in temporary file.
+ * This method is used to save the {@code ByteArray} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code ByteArray} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code ByteArray} instance stored in temporary file.
+ */
+ ByteArray copyToTempFile();
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(ByteArray searchTerm);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(String searchTerm);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(ByteArray searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(ByteArray searchTerm, boolean caseSensitive, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified term.
+ * It works on byte-based data in a way that is similar to the way the native Java method {@link String#indexOf(String)} works on String-based data.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(String searchTerm, boolean caseSensitive, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified pattern.
+ *
+ * @param pattern The pattern to be matched.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(Pattern pattern);
+
+ /**
+ * Searches the data in the ByteArray for the first occurrence of a specified pattern.
+ *
+ * @param pattern The pattern to be matched.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The offset of the first occurrence of the pattern within the specified bounds, or -1 if no match is found.
+ */
+ int indexOf(Pattern pattern, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ *
+ * @return The count of all matches of the pattern.
+ */
+ int countMatches(ByteArray searchTerm);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ *
+ * @return The count of all matches of the pattern.
+ */
+ int countMatches(String searchTerm);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return The count of all matches of the pattern.
+ */
+ int countMatches(ByteArray searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return The count of all matches of the pattern.
+ */
+ int countMatches(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The count of all matches of the pattern within the specified bounds.
+ */
+ int countMatches(ByteArray searchTerm, boolean caseSensitive, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The count of all matches of the pattern within the specified bounds.
+ */
+ int countMatches(String searchTerm, boolean caseSensitive, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified pattern.
+ *
+ * @param pattern The pattern to be matched.
+ *
+ * @return The count of all matches of the pattern within the specified bounds.
+ */
+ int countMatches(Pattern pattern);
+
+ /**
+ * Searches the data in the ByteArray and counts all matches for a specified pattern.
+ *
+ * @param pattern The pattern to be matched.
+ * @param startIndexInclusive The inclusive start index for the search.
+ * @param endIndexExclusive The exclusive end index for the search.
+ *
+ * @return The count of all matches of the pattern within the specified bounds.
+ */
+ int countMatches(Pattern pattern, int startIndexInclusive, int endIndexExclusive);
+
+ /**
+ * Convert the bytes of the ByteArray into String form using the encoding specified by Burp Suite.
+ *
+ * @return The converted data in String form.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code ByteArray} appended with the provided bytes.
+ *
+ * @param data The byte[] or sequence of bytes to append.
+ */
+ ByteArray withAppended(byte... data);
+
+ /**
+ * Create a copy of the {@code ByteArray} appended with the provided integers after narrowing primitive conversion to bytes.
+ *
+ * @param data The int[] or sequence of integers to append after narrowing primitive conversion to bytes.
+ */
+ ByteArray withAppended(int... data);
+
+ /**
+ * Create a copy of the {@code ByteArray} appended with the provided text as bytes.
+ *
+ * @param text The string to append.
+ */
+ ByteArray withAppended(String text);
+
+ /**
+ * Create a copy of the {@code ByteArray} appended with the provided ByteArray.
+ *
+ * @param byteArray The ByteArray to append.
+ */
+ ByteArray withAppended(ByteArray byteArray);
+
+ /**
+ * Create a new {@code ByteArray} with the provided length.
+ *
+ * @param length array length.
+ *
+ * @return New {@code ByteArray} with the provided length.
+ */
+ static ByteArray byteArrayOfLength(int length)
+ {
+ return FACTORY.byteArrayOfLength(length);
+ }
+
+ /**
+ * Create a new {@code ByteArray} with the provided byte data.
+ *
+ * @param data byte[] to wrap, or sequence of bytes to wrap.
+ *
+ * @return New {@code ByteArray} wrapping the provided byte array.
+ */
+ static ByteArray byteArray(byte... data)
+ {
+ return FACTORY.byteArray(data);
+ }
+
+ /**
+ * Create a new {@code ByteArray} with the provided integers after a narrowing primitive conversion to bytes.
+ *
+ * @param data int[] to wrap or sequence of integers to wrap.
+ *
+ * @return New {@code ByteArray} wrapping the provided data after a narrowing primitive conversion to bytes.
+ */
+ static ByteArray byteArray(int... data)
+ {
+ return FACTORY.byteArray(data);
+ }
+
+ /**
+ * Create a new {@code ByteArray} from the provided text using the encoding specified by Burp Suite.
+ *
+ * @param text the text for the byte array.
+ *
+ * @return New {@code ByteArray} holding a copy of the text as bytes.
+ */
+ static ByteArray byteArray(String text)
+ {
+ return FACTORY.byteArray(text);
+ }
+}
+
diff --git a/src/burp/api/montoya/core/HighlightColor.java b/src/burp/api/montoya/core/HighlightColor.java
new file mode 100644
index 0000000..c7ac10c
--- /dev/null
+++ b/src/burp/api/montoya/core/HighlightColor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Colors that can be used for highlights in Burp Suite.
+ */
+public enum HighlightColor
+{
+ NONE("None"),
+ RED("Red"),
+ ORANGE("Orange"),
+ YELLOW("Yellow"),
+ GREEN("Green"),
+ CYAN("Cyan"),
+ BLUE("Blue"),
+ PINK("Pink"),
+ MAGENTA("Magenta"),
+ GRAY("Gray");
+
+ private final String displayName;
+
+ HighlightColor(String displayName)
+ {
+ this.displayName = displayName;
+ }
+
+ /**
+ * @return displayName of highlightColor
+ */
+ public String displayName()
+ {
+ return displayName;
+ }
+
+ /**
+ * Create HighlightColor from display name string.
+ *
+ * @param colorName Color's display name
+ *
+ * @return highlight color instance
+ */
+ public static HighlightColor highlightColor(String colorName)
+ {
+ return FACTORY.highlightColor(colorName);
+ }
+}
diff --git a/src/burp/api/montoya/core/Marker.java b/src/burp/api/montoya/core/Marker.java
new file mode 100644
index 0000000..bd9329a
--- /dev/null
+++ b/src/burp/api/montoya/core/Marker.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Marker containing a range representing interesting data in requests and responses.
+ */
+public interface Marker
+{
+ /**
+ * @return The range of the marker.
+ */
+ Range range();
+
+ /**
+ * Create a marker object with a range.
+ *
+ * @param range The range of the marker.
+ *
+ * @return The marker with the range.
+ */
+ static Marker marker(Range range)
+ {
+ return FACTORY.marker(range);
+ }
+
+ /**
+ * Create a marker object from two indices representing a range.
+ *
+ * @param startIndexInclusive The start index of the range inclusive of this value.
+ * @param endIndexExclusive The end index of the range exclusive of this value.
+ *
+ * @return The marker with the range.
+ */
+ static Marker marker(int startIndexInclusive, int endIndexExclusive)
+ {
+ return FACTORY.marker(startIndexInclusive, endIndexExclusive);
+ }
+}
diff --git a/src/burp/api/montoya/core/Range.java b/src/burp/api/montoya/core/Range.java
new file mode 100644
index 0000000..f16ac2f
--- /dev/null
+++ b/src/burp/api/montoya/core/Range.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Range of integer values between two values in which the range includes the start value but excludes the end value.
+ */
+public interface Range
+{
+ /**
+ * @return the inclusive start index
+ */
+ int startIndexInclusive();
+
+ /**
+ * @return the exclusive end index
+ */
+ int endIndexExclusive();
+
+ /**
+ * @param index The index to test.
+ *
+ * @return True if the index is in the range.
+ */
+ boolean contains(int index);
+
+ /**
+ * Create a range object from two indices.
+ *
+ * @param startIndexInclusive The start index of the range inclusive of this value.
+ * @param endIndexExclusive The end index of the range exclusive of this value.
+ *
+ * @return The range.
+ */
+ static Range range(int startIndexInclusive, int endIndexExclusive)
+ {
+ return FACTORY.range(startIndexInclusive, endIndexExclusive);
+ }
+}
diff --git a/src/burp/api/montoya/core/Registration.java b/src/burp/api/montoya/core/Registration.java
new file mode 100644
index 0000000..6759c33
--- /dev/null
+++ b/src/burp/api/montoya/core/Registration.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Returned when an object is registered by an extension in Burp Suite.
+ */
+public interface Registration
+{
+ /**
+ * Determines whether the object registered by the extension is currently registered.
+ *
+ * @return Returns {@code true} if the object is registered.
+ */
+ boolean isRegistered();
+
+ /**
+ * Remove the object registered by the extension.
+ */
+ void deregister();
+}
diff --git a/src/burp/api/montoya/core/Task.java b/src/burp/api/montoya/core/Task.java
new file mode 100644
index 0000000..bdc0640
--- /dev/null
+++ b/src/burp/api/montoya/core/Task.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Task on the Dashboard.
+ */
+public interface Task
+{
+ /**
+ * Delete the task.
+ */
+ void delete();
+
+ /**
+ * @return the current status message of the task
+ */
+ String statusMessage();
+}
diff --git a/src/burp/api/montoya/core/ToolSource.java b/src/burp/api/montoya/core/ToolSource.java
new file mode 100644
index 0000000..3230c22
--- /dev/null
+++ b/src/burp/api/montoya/core/ToolSource.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Tool that is the source of an object.
+ */
+public interface ToolSource
+{
+ /**
+ * @return the tool type.
+ */
+ ToolType toolType();
+
+ /**
+ * Determine whether this tool source is from a specified tool.
+ *
+ * @param toolType The tool types to check.
+ *
+ * @return Returns {@code true} if this tool source is from any of the
+ * specified tool types.
+ */
+ boolean isFromTool(ToolType... toolType);
+}
diff --git a/src/burp/api/montoya/core/ToolType.java b/src/burp/api/montoya/core/ToolType.java
new file mode 100644
index 0000000..d4e639f
--- /dev/null
+++ b/src/burp/api/montoya/core/ToolType.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Tools in Burp Suite.
+ */
+public enum ToolType
+{
+ SUITE("Suite"),
+ TARGET("Target"),
+ PROXY("Proxy"),
+ SCANNER("Scanner"),
+ INTRUDER("Intruder"),
+ REPEATER("Repeater"),
+ LOGGER("Logger"),
+ SEQUENCER("Sequencer"),
+ DECODER("Decoder"),
+ COMPARER("Comparer"),
+ EXTENSIONS("Extensions"),
+ RECORDED_LOGIN_REPLAYER("Recorded login replayer"),
+ ORGANIZER("Organizer");
+
+ private final String toolName;
+
+ ToolType(String toolName)
+ {
+ this.toolName = toolName;
+ }
+
+ /**
+ * @return The tool name.
+ */
+ public String toolName()
+ {
+ return toolName;
+ }
+
+ /**
+ * @return The tool name.
+ */
+ @Override
+ public String toString()
+ {
+ return toolName;
+ }
+}
diff --git a/src/burp/api/montoya/core/Version.java b/src/burp/api/montoya/core/Version.java
new file mode 100644
index 0000000..cb1b200
--- /dev/null
+++ b/src/burp/api/montoya/core/Version.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.core;
+
+/**
+ * Product version.
+ * e.g. Burp Suite Professional 2022.8.1-9320
+ */
+public interface Version
+{
+ /**
+ * The product name (e.g. Burp Suite Professional).
+ *
+ * @return The product name.
+ */
+ String name();
+
+ /**
+ * The major version (e.g. 2022.8).
+ *
+ * @return The major version.
+ * @deprecated use {@link #toString()} or {@link #buildNumber()} instead.
+ */
+ @Deprecated(forRemoval = true)
+ String major();
+
+ /**
+ * The minor version (e.g. 1).
+ *
+ * @return The minor version.
+ * @deprecated use {@link #toString()} or {@link #buildNumber()} instead.
+ */
+ @Deprecated(forRemoval = true)
+ String minor();
+
+ /**
+ * The build number (e.g. 9320).
+ *
+ * @return The build number.
+ * @deprecated use {@link #toString()} or {@link #buildNumber()} instead.
+ */
+ @Deprecated(forRemoval = true)
+ String build();
+
+ /**
+ * Build number for Burp Suite. You can use this to determine compatibility with different versions of Burp Suite. Do not parse this information, because the format of the number may change.
+ *
+ * @return The build number.
+ */
+ long buildNumber();
+
+ /**
+ * The edition of Burp Suite
+ *
+ * @return The edition of Burp Suite
+ */
+ BurpSuiteEdition edition();
+
+ /**
+ * The human-readable version string. Do not parse this information, because the format may change. See also: {@link #buildNumber()}.
+ *
+ * @return The human-readable version string.
+ */
+ @Override
+ String toString();
+}
diff --git a/src/burp/api/montoya/decoder/Decoder.java b/src/burp/api/montoya/decoder/Decoder.java
new file mode 100644
index 0000000..b46425a
--- /dev/null
+++ b/src/burp/api/montoya/decoder/Decoder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.decoder;
+
+import burp.api.montoya.core.ByteArray;
+
+/**
+ * Provides access to the functionality of the Decoder tool.
+ */
+public interface Decoder
+{
+ /**
+ * Send data to the Decoder tool.
+ *
+ * @param data The data to be sent to Decoder.
+ */
+ void sendToDecoder(ByteArray data);
+}
diff --git a/src/burp/api/montoya/extension/Extension.java b/src/burp/api/montoya/extension/Extension.java
new file mode 100644
index 0000000..5a7b398
--- /dev/null
+++ b/src/burp/api/montoya/extension/Extension.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.extension;
+
+import burp.api.montoya.core.Registration;
+
+/**
+ * Provides access to functionality related to your Extension.
+ */
+public interface Extension
+{
+ /**
+ * Set the display name for the current extension.
+ * This will be displayed within the user interface for the Extensions tool and
+ * will be used to identify persisted data.
+ *
+ * @param extensionName the name of the extension
+ */
+ void setName(String extensionName);
+
+ /**
+ * Absolute path name of the file from which the current extension was loaded.
+ *
+ * @return The absolute path name of the file from which the current
+ * extension was loaded.
+ */
+ String filename();
+
+ /**
+ * Determines whether the current extension was loaded as a BApp.
+ *
+ * @return Returns {@code true} if the current extension was loaded as
+ * a BApp.
+ */
+ boolean isBapp();
+
+ /**
+ * Unload the extension from Burp Suite.
+ */
+ void unload();
+
+ /**
+ * Register a handler which will be notified of changes to the extension's state.
+ * Note: Any extensions that start
+ * background threads or open system resources (such as files or database
+ * connections) should register a listener and terminate threads / close
+ * resources when the extension is unloaded.
+ *
+ * @param handler An object created by the extension that implements the
+ * {@link ExtensionUnloadingHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerUnloadingHandler(ExtensionUnloadingHandler handler);
+}
diff --git a/src/burp/api/montoya/extension/ExtensionUnloadingHandler.java b/src/burp/api/montoya/extension/ExtensionUnloadingHandler.java
new file mode 100644
index 0000000..f8a8863
--- /dev/null
+++ b/src/burp/api/montoya/extension/ExtensionUnloadingHandler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.extension;
+
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Extension#registerUnloadingHandler(ExtensionUnloadingHandler)} to
+ * register an extension unload handler. The handler will be notified when an
+ * extension is unloaded.
+ * Note: Any extensions that start background
+ * threads or open system resources (such as files or database connections)
+ * should register a handler and terminate threads / close resources when the
+ * extension is unloaded.
+ */
+public interface ExtensionUnloadingHandler
+{
+ /**
+ * This method is invoked when the extension is unloaded.
+ */
+ void extensionUnloaded();
+}
diff --git a/src/burp/api/montoya/http/Http.java b/src/burp/api/montoya/http/Http.java
new file mode 100644
index 0000000..e8435d7
--- /dev/null
+++ b/src/burp/api/montoya/http/Http.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http;
+
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.http.handler.HttpHandler;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.analysis.ResponseKeywordsAnalyzer;
+import burp.api.montoya.http.message.responses.analysis.ResponseVariationsAnalyzer;
+import burp.api.montoya.http.sessions.CookieJar;
+import burp.api.montoya.http.sessions.SessionHandlingAction;
+
+import java.util.List;
+
+/**
+ * Provides access HTTP related functionality of Burp.
+ */
+public interface Http
+{
+ /**
+ * Register a handler which will perform an action when a request is about to be sent
+ * or a response was received by any Burp tool.
+ *
+ * @param handler An object created by the extension that implements {@link HttpHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerHttpHandler(HttpHandler handler);
+
+ /**
+ * Register a custom session handler. Each registered handler will be available
+ * within the session handling rule UI for the user to select as a rule action. Users can choose to invoke a
+ * handler directly in its own right, or following execution of a macro.
+ *
+ * @param sessionHandlingAction An object created by the extension that implements {@link SessionHandlingAction} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerSessionHandlingAction(SessionHandlingAction sessionHandlingAction);
+
+ /**
+ * Send HTTP requests and retrieve their responses.
+ *
+ * @param request The full HTTP request.
+ *
+ * @return An object that implements the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the response.
+ */
+ HttpRequestResponse sendRequest(HttpRequest request);
+
+ /**
+ * Send HTTP requests and retrieve their responses.
+ *
+ * @param request The full HTTP request.
+ * @param httpMode An {@link HttpMode} enum value which indicates how a request should be sent.
+ *
+ * @return An object that implements the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the response.
+ */
+ HttpRequestResponse sendRequest(HttpRequest request, HttpMode httpMode);
+
+ /**
+ * Send HTTP requests and retrieve their responses.
+ *
+ * @param request The full HTTP request.
+ * @param httpMode An {@link HttpMode} enum value which indicates how a request should be sent.
+ * @param connectionId The identifier for the connection you want to use.
+ *
+ * @return An object that implements the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the response.
+ */
+ HttpRequestResponse sendRequest(HttpRequest request, HttpMode httpMode, String connectionId);
+
+ /**
+ * Send HTTP request with specific request options and retrieve its response.
+ *
+ * @param request The full HTTP request.
+ * @param requestOptions A {@link RequestOptions} value which indicates how a request should be sent.
+ *
+ * @return An object that implements the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the response.
+ */
+ HttpRequestResponse sendRequest(HttpRequest request, RequestOptions requestOptions);
+
+ /**
+ * Send HTTP requests in parallel and retrieve their responses.
+ *
+ * @param requests The list of full HTTP requests.
+ *
+ * @return A list of objects that implement the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the responses.
+ */
+ List sendRequests(List requests);
+
+ /**
+ * Send HTTP requests in parallel and retrieve their responses.
+ *
+ * @param requests The list of full HTTP requests.
+ * @param httpMode An {@link HttpMode} enum value which indicates how a request should be sent.
+ *
+ * @return A list of objects that implement the {@link HttpRequestResponse} interface, and which the extension can query to obtain the details of the responses.
+ */
+ List sendRequests(List requests, HttpMode httpMode);
+
+ /**
+ * Create a new response keyword analyzer.
+ *
+ * @param keywords A list of keywords the analyzer will look for.
+ *
+ * @return A new {@link ResponseKeywordsAnalyzer} instance.
+ */
+ ResponseKeywordsAnalyzer createResponseKeywordsAnalyzer(List keywords);
+
+ /**
+ * Create a new response variations analyzer.
+ *
+ * @return A new {@link ResponseKeywordsAnalyzer} instance.
+ */
+ ResponseVariationsAnalyzer createResponseVariationsAnalyzer();
+
+ /**
+ * Access the Cookie Jar.
+ *
+ * @return The {@link CookieJar} instance.
+ */
+ CookieJar cookieJar();
+}
diff --git a/src/burp/api/montoya/http/HttpMode.java b/src/burp/api/montoya/http/HttpMode.java
new file mode 100644
index 0000000..b578951
--- /dev/null
+++ b/src/burp/api/montoya/http/HttpMode.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http;
+
+/**
+ * HTTP modes when sending a request.
+ */
+public enum HttpMode
+{
+ /**
+ * Use the HTTP protocol specified by the server
+ */
+ AUTO,
+ /**
+ * Use HTTP 1 protocol for the connection.
+ * Will error if server is HTTP 2 only.
+ */
+ HTTP_1,
+ /**
+ * Use HTTP 2 protocol for the connection.
+ * Will error if server is HTTP 1 only.
+ */
+ HTTP_2,
+ /**
+ * Force HTTP 2 and ignore ALPN.
+ * Will not error if server is HTTP 1 only.
+ */
+ HTTP_2_IGNORE_ALPN
+}
diff --git a/src/burp/api/montoya/http/HttpProtocol.java b/src/burp/api/montoya/http/HttpProtocol.java
new file mode 100644
index 0000000..cc09300
--- /dev/null
+++ b/src/burp/api/montoya/http/HttpProtocol.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http;
+
+/**
+ * HTTP protocols.
+ */
+public enum HttpProtocol
+{
+ /**
+ * Hypertext Transfer Protocol
+ */
+ HTTP,
+ /**
+ * Hypertext Transfer Protocol Secure
+ */
+ HTTPS
+}
diff --git a/src/burp/api/montoya/http/HttpService.java b/src/burp/api/montoya/http/HttpService.java
new file mode 100644
index 0000000..49eacd7
--- /dev/null
+++ b/src/burp/api/montoya/http/HttpService.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp HTTP service providing details about an HTTP service, to which HTTP requests can be sent.
+ */
+public interface HttpService
+{
+
+ /**
+ * @return The hostname or IP address for the service.
+ */
+ String host();
+
+ /**
+ * @return The port number for the service.
+ */
+ int port();
+
+ /**
+ * @return True if a secure protocol is used for the connection, false otherwise.
+ */
+ boolean secure();
+
+ /**
+ * Dynamically resolve the host to an IP address.
+ *
+ * @return The IP address of the host.
+ */
+ String ipAddress();
+
+ /**
+ * @return The {@code String} representation of the service.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a new instance of {@code HttpService}.
+ *
+ * @param baseUrl The URL for the service.
+ *
+ * @return A new {@code HttpService} instance.
+ *
+ * @throws IllegalArgumentException If the provided URL is invalid.
+ */
+ static HttpService httpService(String baseUrl)
+ {
+ return FACTORY.httpService(baseUrl);
+ }
+
+ /**
+ * Create a new instance of {@code HttpService}.
+ *
+ * @param host The hostname or IP address for the service.
+ * @param secure True if a secure connection is to be used.
+ *
+ * @return A new {@code HttpService} instance.
+ */
+ static HttpService httpService(String host, boolean secure)
+ {
+ return FACTORY.httpService(host, secure);
+ }
+
+ /**
+ * Create a new instance of {@code HttpService}.
+ *
+ * @param host The hostname or IP address for the service.
+ * @param port The port number for the service.
+ * @param secure True if a secure connection is to be used.
+ *
+ * @return A new {@code HttpService} instance.
+ */
+ static HttpService httpService(String host, int port, boolean secure)
+ {
+ return FACTORY.httpService(host, port, secure);
+ }
+}
diff --git a/src/burp/api/montoya/http/RequestOptions.java b/src/burp/api/montoya/http/RequestOptions.java
new file mode 100644
index 0000000..abed659
--- /dev/null
+++ b/src/burp/api/montoya/http/RequestOptions.java
@@ -0,0 +1,44 @@
+package burp.api.montoya.http;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Interface used to specify options for making HTTP requests.
+ */
+public interface RequestOptions
+{
+ /**
+ * Specify HTTP mode to be used when request sent.
+ *
+ * @param httpMode An {@link HttpMode} enum value which indicates how a request should be sent.
+ *
+ * @return request options
+ */
+ RequestOptions withHttpMode(HttpMode httpMode);
+
+ /**
+ * Specify connectionId when sending request over specific connection.
+ *
+ * @param connectionId The connection identifier to use.
+ *
+ * @return request options
+ */
+ RequestOptions withConnectionId(String connectionId);
+
+ /**
+ * Enforce upstream TLS verification when request sent.
+ *
+ * @return request options
+ */
+ RequestOptions withUpstreamTLSVerification();
+
+ /**
+ * Use to obtain a new RequestOptions instance
+ *
+ * @return request options
+ */
+ static RequestOptions requestOptions()
+ {
+ return FACTORY.requestOptions();
+ }
+}
diff --git a/src/burp/api/montoya/http/handler/HttpHandler.java b/src/burp/api/montoya/http/handler/HttpHandler.java
new file mode 100644
index 0000000..925d076
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/HttpHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import burp.api.montoya.http.Http;
+
+/**
+ * Extensions can implement this interface and then call {@link Http#registerHttpHandler} to register an HTTP handler. The handler
+ * will be notified of requests and responses made and received by any Burp tool. Extensions can perform custom analysis or modification
+ * of these messages by registering an HTTP handler.
+ */
+public interface HttpHandler
+{
+ /**
+ * Invoked by Burp when an HTTP request is about to be sent.
+ *
+ * @param requestToBeSent information about the HTTP request that is going to be sent.
+ *
+ * @return An instance of {@link RequestToBeSentAction}.
+ */
+ RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent);
+
+ /**
+ * Invoked by Burp when an HTTP response has been received.
+ *
+ * @param responseReceived information about HTTP response that was received.
+ *
+ * @return An instance of {@link ResponseReceivedAction}.
+ */
+ ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived);
+}
diff --git a/src/burp/api/montoya/http/handler/HttpRequestToBeSent.java b/src/burp/api/montoya/http/handler/HttpRequestToBeSent.java
new file mode 100644
index 0000000..151ff5a
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/HttpRequestToBeSent.java
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.core.ToolSource;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.message.ContentType;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.params.HttpParameter;
+import burp.api.montoya.http.message.params.HttpParameterType;
+import burp.api.montoya.http.message.params.ParsedHttpParameter;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.requests.HttpTransformation;
+import burp.api.montoya.http.message.requests.MalformedRequestException;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Burp {@link HttpRequest} with additional methods to retrieve {@link Annotations} and {@link ToolSource} of the request.
+ */
+public interface HttpRequestToBeSent extends HttpRequest
+{
+ /**
+ * @return The ID for this request to be sent. The corresponding response will have an identical ID.
+ */
+ int messageId();
+
+ /**
+ * @return annotations for request/response
+ */
+ Annotations annotations();
+
+ /**
+ * @return Indicates which Burp tool sent the request.
+ */
+ ToolSource toolSource();
+
+ /**
+ * @return True if the request is in-scope.
+ */
+ @Override
+ boolean isInScope();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ @Override
+ HttpService httpService();
+
+ /**
+ * URL for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The URL in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String url();
+
+ /**
+ * HTTP method for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The HTTP method used in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String method();
+
+ /**
+ * Request path including the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path and query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String path();
+
+ /**
+ * Request path excluding the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path excluding query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String pathWithoutQuery();
+
+ /**
+ * HTTP Version text parsed from the request line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * @param header The header to check if it exists in the request.
+ *
+ * @return True if the header exists in the request.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * @return True if the request has parameters.
+ */
+ @Override
+ boolean hasParameters();
+
+ /**
+ * @return True if the request has parameters of type {@link HttpParameterType}
+ */
+ @Override
+ boolean hasParameters(HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return An instance of {@link ParsedHttpParameter} that matches the type and name specified. {@code null} if not found.
+ */
+ @Override
+ ParsedHttpParameter parameter(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to get the value from.
+ * @param type The type of the parameter to get the value from.
+ *
+ * @return The value of the parameter that matches the name and type specified. {@code null} if not found.
+ */
+ @Override
+ String parameterValue(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return {@code true} if a parameter exists that matches the name and type specified. {@code false} if not found.
+ */
+ @Override
+ boolean hasParameter(String name, HttpParameterType type);
+
+ /**
+ * @param parameter An instance of {@link HttpParameter} to match to an existing parameter.
+ *
+ * @return {@code true} if a parameter exists that matches the data within the provided {@link HttpParameter}. {@code false} if not found.
+ */
+ @Override
+ boolean hasParameter(HttpParameter parameter);
+
+ /**
+ * @return The detected content type of the request.
+ */
+ @Override
+ ContentType contentType();
+
+ /**
+ * @return The parameters contained in the request.
+ */
+ @Override
+ List parameters();
+
+ /**
+ * @param type The type of parameter that will be returned in the filtered list.
+ *
+ * @return A filtered list of {@link ParsedHttpParameter} containing only the provided type.
+ */
+ @Override
+ List parameters(HttpParameterType type);
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpRequest} in temporary file.
+ * This method is used to save the {@code HttpRequest} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code HttpRequest} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code HttpRequest} instance stored in temporary file.
+ */
+ HttpRequest copyToTempFile();
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new service.
+ *
+ * @param service An {@link HttpService} reference to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withService(HttpService service);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new path.
+ *
+ * @param path The path to use.
+ *
+ * @return A new {@code HttpRequest} instance with updated path.
+ */
+ @Override
+ HttpRequest withPath(String path);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new method.
+ *
+ * @param method the method to use
+ *
+ * @return a new {@code HttpRequest} instance with updated method.
+ */
+ @Override
+ HttpRequest withMethod(String method);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param header HTTP header to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ @Override
+ HttpRequest withHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ @Override
+ HttpRequest withHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the HTTP parameter.
+ * If the parameter exists in the request, it is updated.
+ * If the parameter doesn't exist in the request, it is added.
+ *
+ * @param parameters HTTP parameter to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated parameter.
+ */
+ @Override
+ HttpRequest withParameter(HttpParameter parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withAddedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withAddedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withRemovedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withRemovedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withUpdatedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withUpdatedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the transformation applied.
+ *
+ * @param transformation Transformation to apply.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withTransformationApplied(HttpTransformation transformation);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ @Override
+ HttpRequest withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the HTTP request.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ @Override
+ HttpRequest withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated request containing the updated header.
+ */
+ @Override
+ HttpRequest withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated request containing the updated header.
+ */
+ @Override
+ HttpRequest withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param name The name of the HTTP header to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ @Override
+ HttpRequest withRemovedHeader(String name);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param header The {@link HttpHeader} to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ @Override
+ HttpRequest withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withMarkers(Marker... markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with added default headers.
+ *
+ * @return a new {@link HttpRequest} with added default headers
+ */
+ @Override
+ HttpRequest withDefaultHeaders();
+}
diff --git a/src/burp/api/montoya/http/handler/HttpResponseReceived.java b/src/burp/api/montoya/http/handler/HttpResponseReceived.java
new file mode 100644
index 0000000..5600f86
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/HttpResponseReceived.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.core.ToolSource;
+import burp.api.montoya.http.message.Cookie;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.MimeType;
+import burp.api.montoya.http.message.StatusCodeClass;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.http.message.responses.analysis.Attribute;
+import burp.api.montoya.http.message.responses.analysis.AttributeType;
+import burp.api.montoya.http.message.responses.analysis.KeywordCount;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Burp {@link HttpResponse} with additional methods to retrieve initiating {@link HttpRequest} as well as the {@link Annotations} and {@link ToolSource} of the request.
+ */
+public interface HttpResponseReceived extends HttpResponse
+{
+ /**
+ * @return The ID for this response which is identical to the ID on the corresponding request.
+ */
+ int messageId();
+
+ /**
+ * @return initiatingRequest The HTTP request that was sent.
+ */
+ HttpRequest initiatingRequest();
+
+ /**
+ * @return Annotations for request/response.
+ */
+ Annotations annotations();
+
+ /**
+ * @return ToolSource which indicates which Burp tool sent the request.
+ */
+ ToolSource toolSource();
+
+ /**
+ * Obtain the HTTP status code contained in the response.
+ *
+ * @return HTTP status code.
+ */
+ @Override
+ short statusCode();
+
+ /**
+ * Obtain the HTTP reason phrase contained in the response for HTTP 1 messages.
+ * HTTP 2 messages will return a mapped phrase based on the status code.
+ *
+ * @return HTTP Reason phrase.
+ */
+ @Override
+ String reasonPhrase();
+
+ /**
+ * Test whether the status code is in the specified class.
+ *
+ * @param statusCodeClass The class of status code to test.
+ *
+ * @return True if the status code is in the class.
+ */
+ @Override
+ boolean isStatusCodeClass(StatusCodeClass statusCodeClass);
+
+ /**
+ * Return the HTTP Version text parsed from the response line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Obtain details of the HTTP cookies set in the response.
+ *
+ * @return A list of {@link Cookie} objects representing the cookies set in the response, if any.
+ */
+ @Override
+ List cookies();
+
+ /**
+ * @param name The name of the cookie to find.
+ *
+ * @return An instance of {@link Cookie} that matches the name provided. {@code null} if not found.
+ */
+ @Override
+ Cookie cookie(String name);
+
+ /**
+ * @param name The name of the cookie to retrieve the value from.
+ *
+ * @return The value of the cookie that matches the name provided. {@code null} if not found.
+ */
+ @Override
+ String cookieValue(String name);
+
+ /**
+ * @param name The name of the cookie to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the name provided. {@code false} if not.
+ */
+ @Override
+ boolean hasCookie(String name);
+
+ /**
+ * @param cookie An instance of {@link Cookie} to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the {@link Cookie} provided. {@code false} if not.
+ */
+ @Override
+ boolean hasCookie(Cookie cookie);
+
+ /**
+ * Obtain the MIME type of the response, as determined by Burp Suite.
+ *
+ * @return The MIME type.
+ */
+ @Override
+ MimeType mimeType();
+
+ /**
+ * Obtain the MIME type of the response, as stated in the HTTP headers.
+ *
+ * @return The stated MIME type.
+ */
+ @Override
+ MimeType statedMimeType();
+
+ /**
+ * Obtain the MIME type of the response, as inferred from the contents of the HTTP message body.
+ *
+ * @return The inferred MIME type.
+ */
+ @Override
+ MimeType inferredMimeType();
+
+ /**
+ * Retrieve the number of types given keywords appear in the response.
+ *
+ * @param keywords Keywords to count.
+ *
+ * @return List of keyword counts in the order they were provided.
+ */
+ @Override
+ List keywordCounts(String... keywords);
+
+ /**
+ * Retrieve the values of response attributes.
+ *
+ * @param types Response attributes to retrieve values for.
+ *
+ * @return List of {@link Attribute} objects.
+ */
+ @Override
+ List attributes(AttributeType... types);
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the provided status code.
+ *
+ * @param statusCode the new status code for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withStatusCode(short statusCode);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new reason phrase.
+ *
+ * @param reasonPhrase the new reason phrase for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withReasonPhrase(String reasonPhrase);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new http version.
+ *
+ * @param httpVersion the new http version for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withHttpVersion(String httpVersion);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the response.
+ *
+ * @return The updated response containing the added header.
+ */
+ @Override
+ HttpResponse withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated response containing the added header.
+ */
+ @Override
+ HttpResponse withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated response containing the updated header.
+ */
+ @Override
+ HttpResponse withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated response containing the updated header.
+ */
+ @Override
+ HttpResponse withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param header The {@link HttpHeader} to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ @Override
+ HttpResponse withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param name The name of the HTTP header to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ @Override
+ HttpResponse withRemovedHeader(String name);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ @Override
+ HttpResponse withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ @Override
+ HttpResponse withMarkers(Marker... markers);
+}
diff --git a/src/burp/api/montoya/http/handler/RequestAction.java b/src/burp/api/montoya/http/handler/RequestAction.java
new file mode 100644
index 0000000..fd25943
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/RequestAction.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+/**
+ * Action to be taken when intercepting HTTP requests.
+ */
+public enum RequestAction
+{
+ /**
+ * Causes Burp to send the request.
+ */
+ CONTINUE
+}
diff --git a/src/burp/api/montoya/http/handler/RequestToBeSentAction.java b/src/burp/api/montoya/http/handler/RequestToBeSentAction.java
new file mode 100644
index 0000000..eea31e6
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/RequestToBeSentAction.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * An instance of this interface should be returned by {@link HttpHandler#handleHttpRequestToBeSent} if a custom {@link HttpHandler} has been registered with Burp.
+ */
+public interface RequestToBeSentAction
+{
+ /**
+ * @return the action.
+ */
+ default RequestAction action()
+ {
+ return RequestAction.CONTINUE;
+ }
+
+ /**
+ * @return The HTTP request.
+ */
+ HttpRequest request();
+
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * Create a new instance of {@code RequestResult}. Annotations will not be modified.
+ *
+ * @param request An HTTP request.
+ *
+ * @return A new {@code RequestHandlerResult} instance.
+ */
+ static RequestToBeSentAction continueWith(HttpRequest request)
+ {
+ return FACTORY.requestResult(request);
+ }
+
+ /**
+ * Create a new instance of {@code RequestResult}.
+ *
+ * @param request An HTTP request.
+ * @param annotations modified annotations.
+ *
+ * @return A new {@code RequestHandlerResult} instance.
+ */
+ static RequestToBeSentAction continueWith(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.requestResult(request, annotations);
+ }
+}
diff --git a/src/burp/api/montoya/http/handler/ResponseAction.java b/src/burp/api/montoya/http/handler/ResponseAction.java
new file mode 100644
index 0000000..2f8dac5
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/ResponseAction.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+/**
+ * Action to be taken when intercepting HTTP responses.
+ */
+public enum ResponseAction
+{
+ /**
+ * Causes Burp to send the response.
+ */
+ CONTINUE
+}
diff --git a/src/burp/api/montoya/http/handler/ResponseReceivedAction.java b/src/burp/api/montoya/http/handler/ResponseReceivedAction.java
new file mode 100644
index 0000000..8a7562d
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/ResponseReceivedAction.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * An instance of this interface should be returned by {@link HttpHandler#handleHttpResponseReceived} if a custom {@link HttpHandler} has been registered with Burp.
+ */
+public interface ResponseReceivedAction
+{
+ /**
+ * @return the action.
+ */
+ default ResponseAction action()
+ {
+ return ResponseAction.CONTINUE;
+ }
+
+ /**
+ * @return The HTTP response.
+ */
+ HttpResponse response();
+
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * Create a new instance of {@code ResponseResult}. Annotations will not be modified.
+ *
+ * @param response An HTTP response.
+ *
+ * @return A new {@code ResponseResult} instance.
+ */
+ static ResponseReceivedAction continueWith(HttpResponse response)
+ {
+ return FACTORY.responseResult(response);
+ }
+
+ /**
+ * Create a new instance of {@code ResponseResult}.
+ *
+ * @param response An HTTP response.
+ * @param annotations modified annotations.
+ *
+ * @return A new {@code ResponseResult} instance.
+ */
+ static ResponseReceivedAction continueWith(HttpResponse response, Annotations annotations)
+ {
+ return FACTORY.responseResult(response, annotations);
+ }
+}
diff --git a/src/burp/api/montoya/http/handler/TimingData.java b/src/burp/api/montoya/http/handler/TimingData.java
new file mode 100644
index 0000000..9e3e304
--- /dev/null
+++ b/src/burp/api/montoya/http/handler/TimingData.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.handler;
+
+import java.time.Duration;
+import java.time.ZonedDateTime;
+
+/**
+ * Timing data
+ */
+public interface TimingData
+{
+ /**
+ * The time between when Burp sent the request and the start of the response being received.
+ *
+ * @return the duration or null if no response returned.
+ */
+ Duration timeBetweenRequestSentAndStartOfResponse();
+
+ /**
+ * The time between when Burp sent the request and the end of the response being received.
+ *
+ * @return the duration or null if no response returned or the response never completes.
+ */
+ Duration timeBetweenRequestSentAndEndOfResponse();
+
+ /**
+ * The time that Burp issued the request.
+ *
+ * @return the time that Burp issued the request.
+ */
+ ZonedDateTime timeRequestSent();
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/http/message/ContentType.java b/src/burp/api/montoya/http/message/ContentType.java
new file mode 100644
index 0000000..4930d24
--- /dev/null
+++ b/src/burp/api/montoya/http/message/ContentType.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+/**
+ * Content types recognised by Burp.
+ */
+public enum ContentType
+{
+ NONE,
+ UNKNOWN,
+ AMF,
+ JSON,
+ MULTIPART,
+ URL_ENCODED,
+ XML
+}
diff --git a/src/burp/api/montoya/http/message/Cookie.java b/src/burp/api/montoya/http/message/Cookie.java
new file mode 100644
index 0000000..eb76c2e
--- /dev/null
+++ b/src/burp/api/montoya/http/message/Cookie.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.time.ZonedDateTime;
+import java.util.Optional;
+
+/**
+ * Burp cookie able to retrieve and hold details about a cookie.
+ */
+public interface Cookie
+{
+ /**
+ * @return The name of the cookie
+ */
+ String name();
+
+ /**
+ * @return The value of the cookie.
+ */
+ String value();
+
+ /**
+ * Domain for which the cookie is in scope.
+ * Note: For cookies that have been obtained from generated responses
+ * (by calling {@link HttpResponse#httpResponse} and then {@link HttpResponse#cookies}), the domain will be {@code null} if the response
+ * did not explicitly set a domain attribute for the cookie.
+ *
+ * @return The domain for which the cookie is in scope.
+ */
+ String domain();
+
+ /**
+ * Path for which the cookie is in scope.
+ *
+ * @return The path for which the cookie is in scope or {@code null} if none is set.
+ */
+ String path();
+
+ /**
+ * Expiration time for the cookie if available.
+ *
+ * @return The expiration time for the cookie (i.e., for non-persistent session cookies).
+ */
+ Optional expiration();
+}
diff --git a/src/burp/api/montoya/http/message/HttpHeader.java b/src/burp/api/montoya/http/message/HttpHeader.java
new file mode 100644
index 0000000..c80fcea
--- /dev/null
+++ b/src/burp/api/montoya/http/message/HttpHeader.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp HTTP header able to retrieve to hold details about an HTTP header.
+ */
+public interface HttpHeader
+{
+ /**
+ * @return The name of the header.
+ */
+ String name();
+
+ /**
+ * @return The value of the header.
+ */
+ String value();
+
+ /**
+ * @return The {@code String} representation of the header.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a new instance of {@code HttpHeader} from name and value.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return A new {@code HttpHeader} instance.
+ */
+ static HttpHeader httpHeader(String name, String value)
+ {
+ return FACTORY.httpHeader(name, value);
+ }
+
+ /**
+ * Create a new instance of HttpHeader from a {@code String} header representation.
+ * It will be parsed according to the HTTP/1.1 specification for headers.
+ *
+ * @param header The {@code String} header representation.
+ *
+ * @return A new {@code HttpHeader} instance.
+ */
+ static HttpHeader httpHeader(String header)
+ {
+ return FACTORY.httpHeader(header);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/HttpMessage.java b/src/burp/api/montoya/http/message/HttpMessage.java
new file mode 100644
index 0000000..f31cce5
--- /dev/null
+++ b/src/burp/api/montoya/http/message/HttpMessage.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Burp message retrieve common information shared by {@link HttpRequest} and {@link HttpResponse}.
+ */
+public interface HttpMessage
+{
+ /**
+ * @param header The header to check if it exists in the request.
+ *
+ * @return True if the header exists in the request.
+ */
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ String headerValue(String name);
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ List headers();
+
+ /**
+ * HTTP Version text parsed from the request or response line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ String httpVersion();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ int bodyOffset();
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ String bodyToString();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ List markers();
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+}
diff --git a/src/burp/api/montoya/http/message/HttpRequestResponse.java b/src/burp/api/montoya/http/message/HttpRequestResponse.java
new file mode 100644
index 0000000..19288e2
--- /dev/null
+++ b/src/burp/api/montoya/http/message/HttpRequestResponse.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.handler.TimingData;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.requests.MalformedRequestException;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This interface is used to define a coupling between {@link HttpRequest} and {@link HttpResponse}.
+ */
+public interface HttpRequestResponse
+{
+ /**
+ * @return The HTTP request message.
+ */
+ HttpRequest request();
+
+ /**
+ * @return The HTTP response message.
+ */
+ HttpResponse response();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ HttpService httpService();
+
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * Retrieve the timing data associated with this request if available.
+ *
+ * @return The timing data.
+ */
+ Optional timingData();
+
+ /**
+ * Retrieve the URL for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The URL in the request.
+ * @throws MalformedRequestException if request is malformed.
+ * @deprecated use {@link #request()} url instead.
+ */
+ @Deprecated(forRemoval = true)
+ String url();
+
+ /**
+ * @return True if there is an HTTP response message.
+ */
+ boolean hasResponse();
+
+ /**
+ * @return The detected content type of the request.
+ * @deprecated use {@link #request()} contentType instead.
+ */
+ @Deprecated(forRemoval = true)
+ ContentType contentType();
+
+ /**
+ * HTTP status code contained in the response.
+ *
+ * @return HTTP status code or -1 if there is no response.
+ * @deprecated use {@link #response()} statusCode instead.
+ */
+ @Deprecated(forRemoval = true)
+ short statusCode();
+
+ /**
+ * @return List of request markers
+ */
+ List requestMarkers();
+
+ /**
+ * @return List of response markers
+ */
+ List responseMarkers();
+
+ /**
+ * Searches the data in the HTTP request, response and notes for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP request, response and notes for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ boolean contains(Pattern pattern);
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} in temporary file.
+ * This method is used to save the {@code HttpRequestResponse} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code HttpRequest} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code ByteArray} instance stored in temporary file.
+ */
+ HttpRequestResponse copyToTempFile();
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} with the added annotations.
+ *
+ * @param annotations annotations to add.
+ *
+ * @return A new {@code HttpRequestResponse} instance.
+ */
+ HttpRequestResponse withAnnotations(Annotations annotations);
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} with the added request markers.
+ *
+ * @param requestMarkers Request markers to add.
+ *
+ * @return A new {@code HttpRequestResponse} instance.
+ */
+ HttpRequestResponse withRequestMarkers(List requestMarkers);
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} with the added request markers.
+ *
+ * @param requestMarkers Request markers to add.
+ *
+ * @return A new {@code HttpRequestResponse} instance.
+ */
+ HttpRequestResponse withRequestMarkers(Marker... requestMarkers);
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} with the added response markers.
+ *
+ * @param responseMarkers Response markers to add.
+ *
+ * @return A new {@code HttpRequestResponse} instance.
+ */
+ HttpRequestResponse withResponseMarkers(List responseMarkers);
+
+ /**
+ * Create a copy of the {@code HttpRequestResponse} with the added response markers.
+ *
+ * @param responseMarkers Response markers to add.
+ *
+ * @return A new {@code HttpRequestResponse} instance.
+ */
+ HttpRequestResponse withResponseMarkers(Marker... responseMarkers);
+
+ /**
+ * Create a new instance of {@link HttpRequestResponse}.
+ *
+ * @param request The HTTP request.
+ * @param response The HTTP response.
+ *
+ * @return A new {@link HttpRequestResponse} instance.
+ */
+ static HttpRequestResponse httpRequestResponse(HttpRequest request, HttpResponse response)
+ {
+ return FACTORY.httpRequestResponse(request, response);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequestResponse}.
+ *
+ * @param httpRequest The HTTP request.
+ * @param httpResponse The HTTP response.
+ * @param annotations annotations.
+ *
+ * @return A new {@link HttpRequestResponse} instance.
+ */
+ static HttpRequestResponse httpRequestResponse(HttpRequest httpRequest, HttpResponse httpResponse, Annotations annotations)
+ {
+ return FACTORY.httpRequestResponse(httpRequest, httpResponse, annotations);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/MimeType.java b/src/burp/api/montoya/http/message/MimeType.java
new file mode 100644
index 0000000..20de4c3
--- /dev/null
+++ b/src/burp/api/montoya/http/message/MimeType.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message;
+
+/**
+ * MIME types that are recognised by Burp.
+ */
+public enum MimeType
+{
+ NONE("none"),
+ UNRECOGNIZED("unrecognized content"),
+ AMBIGUOUS("ambiguous"),
+ HTML("HTML"),
+ PLAIN_TEXT("plain text"),
+ CSS("CSS"),
+ SCRIPT("script"),
+ JSON("JSON"),
+ RTF("RTF"),
+ XML("XML"),
+ YAML("YAML"),
+ IMAGE_UNKNOWN("an unknown image type"),
+ IMAGE_JPEG("a JPEG image"),
+ IMAGE_GIF("a GIF image"),
+ IMAGE_PNG("a PNG image"),
+ IMAGE_BMP("a BMP image"),
+ IMAGE_TIFF("a TIFF image"),
+ IMAGE_SVG_XML("a SVG image"),
+ SOUND("sound"),
+ VIDEO("video"),
+ APPLICATION_FLASH("a flash object"),
+ APPLICATION_UNKNOWN("an unknown application type"),
+ FONT_WOFF("a WOFF font file"),
+ FONT_WOFF2("a WOFF2 font file"),
+ LEGACY_SER_AMF("");
+
+ private final String description;
+
+ MimeType(String description)
+ {
+ this.description = description;
+ }
+
+ /**
+ * @return MIME type description.
+ */
+ public String description()
+ {
+ return description;
+ }
+}
diff --git a/src/burp/api/montoya/http/message/StatusCodeClass.java b/src/burp/api/montoya/http/message/StatusCodeClass.java
new file mode 100644
index 0000000..d2dccf3
--- /dev/null
+++ b/src/burp/api/montoya/http/message/StatusCodeClass.java
@@ -0,0 +1,63 @@
+package burp.api.montoya.http.message;
+
+/**
+ * Status code classes that are defined in the HTTP standard.
+ */
+public enum StatusCodeClass
+{
+ /**
+ * Informational response (100 to 199).
+ */
+ CLASS_1XX_INFORMATIONAL_RESPONSE(100, 200),
+ /**
+ * Success (200 to 299).
+ */
+ CLASS_2XX_SUCCESS(200, 300),
+ /**
+ * Redirection (300 to 399).
+ */
+ CLASS_3XX_REDIRECTION(300, 400),
+ /**
+ * Client errors (400 to 499).
+ */
+ CLASS_4XX_CLIENT_ERRORS(400, 500),
+ /**
+ * Server errors (500 to 599).
+ */
+ CLASS_5XX_SERVER_ERRORS(500, 600);
+
+ private final int startStatusCodeInclusive;
+ private final int endStatusCodeExclusive;
+
+ StatusCodeClass(int startStatusCodeInclusive, int endStatusCodeExclusive)
+ {
+ this.startStatusCodeInclusive = startStatusCodeInclusive;
+ this.endStatusCodeExclusive = endStatusCodeExclusive;
+ }
+
+ /**
+ * @return the inclusive start status code.
+ */
+ public int startStatusCodeInclusive()
+ {
+ return startStatusCodeInclusive;
+ }
+
+ /**
+ * @return the exclusive end status code.
+ */
+ public int endStatusCodeExclusive()
+ {
+ return endStatusCodeExclusive;
+ }
+
+ /**
+ * @param statusCode The status code to test.
+ *
+ * @return True if the status code is in the status code class.
+ */
+ public boolean contains(int statusCode)
+ {
+ return startStatusCodeInclusive <= statusCode && statusCode < endStatusCodeExclusive;
+ }
+}
diff --git a/src/burp/api/montoya/http/message/params/HttpParameter.java b/src/burp/api/montoya/http/message/params/HttpParameter.java
new file mode 100644
index 0000000..602aad4
--- /dev/null
+++ b/src/burp/api/montoya/http/message/params/HttpParameter.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.params;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp HTTP parameter able to retrieve to hold details about an HTTP request parameter.
+ */
+public interface HttpParameter
+{
+ /**
+ * @return The parameter type.
+ */
+ HttpParameterType type();
+
+ /**
+ * @return The parameter name.
+ */
+ String name();
+
+ /**
+ * @return The parameter value.
+ */
+ String value();
+
+ /**
+ * Create a new Instance of {@code HttpParameter} with {@link HttpParameterType#URL} type.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ *
+ * @return A new {@code HttpParameter} instance.
+ */
+ static HttpParameter urlParameter(String name, String value)
+ {
+ return FACTORY.urlParameter(name, value);
+ }
+
+ /**
+ * Create a new Instance of {@code HttpParameter} with {@link HttpParameterType#BODY} type.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ *
+ * @return A new {@code HttpParameter} instance.
+ */
+ static HttpParameter bodyParameter(String name, String value)
+ {
+ return FACTORY.bodyParameter(name, value);
+ }
+
+ /**
+ * Create a new Instance of {@code HttpParameter} with {@link HttpParameterType#COOKIE} type.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ *
+ * @return A new {@code HttpParameter} instance.
+ */
+ static HttpParameter cookieParameter(String name, String value)
+ {
+ return FACTORY.cookieParameter(name, value);
+ }
+
+ /**
+ * Create a new Instance of {@code HttpParameter} with the specified type.
+ *
+ * @param name The parameter name.
+ * @param value The parameter value.
+ * @param type The header type.
+ *
+ * @return A new {@code HttpParameter} instance.
+ */
+ static HttpParameter parameter(String name, String value, HttpParameterType type)
+ {
+ return FACTORY.parameter(name, value, type);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/params/HttpParameterType.java b/src/burp/api/montoya/http/message/params/HttpParameterType.java
new file mode 100644
index 0000000..9cd0a1f
--- /dev/null
+++ b/src/burp/api/montoya/http/message/params/HttpParameterType.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.params;
+
+/**
+ * HTTP parameter types.
+ */
+public enum HttpParameterType
+{
+ URL,
+ BODY,
+ COOKIE,
+ XML,
+ XML_ATTRIBUTE,
+ MULTIPART_ATTRIBUTE,
+ JSON
+}
diff --git a/src/burp/api/montoya/http/message/params/ParsedHttpParameter.java b/src/burp/api/montoya/http/message/params/ParsedHttpParameter.java
new file mode 100644
index 0000000..91acc37
--- /dev/null
+++ b/src/burp/api/montoya/http/message/params/ParsedHttpParameter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.params;
+
+import burp.api.montoya.core.Range;
+
+/**
+ * Burp {@link HttpParameter} with additional details about an HTTP request parameter that has been parsed by Burp.
+ */
+public interface ParsedHttpParameter extends HttpParameter
+{
+ /**
+ * @return The parameter type.
+ */
+ @Override
+ HttpParameterType type();
+
+ /**
+ * @return The parameter name.
+ */
+ @Override
+ String name();
+
+ /**
+ * @return The parameter value.
+ */
+ @Override
+ String value();
+
+ /**
+ * Offsets of the parameter name within the HTTP request.
+ *
+ * @return The parameter name offsets.
+ */
+ Range nameOffsets();
+
+ /**
+ * Offsets of the parameter value within the HTTP request.
+ *
+ * @return The parameter value offsets.
+ */
+ Range valueOffsets();
+}
diff --git a/src/burp/api/montoya/http/message/requests/HttpRequest.java b/src/burp/api/montoya/http/message/requests/HttpRequest.java
new file mode 100644
index 0000000..261f8d3
--- /dev/null
+++ b/src/burp/api/montoya/http/message/requests/HttpRequest.java
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.requests;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.message.ContentType;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.HttpMessage;
+import burp.api.montoya.http.message.params.HttpParameter;
+import burp.api.montoya.http.message.params.HttpParameterType;
+import burp.api.montoya.http.message.params.ParsedHttpParameter;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp HTTP request able to retrieve and modify details of an HTTP request.
+ */
+public interface HttpRequest extends HttpMessage
+{
+ /**
+ * @return True if the request is in-scope.
+ */
+ boolean isInScope();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ HttpService httpService();
+
+ /**
+ * URL for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The URL in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String url();
+
+ /**
+ * HTTP method for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The HTTP method used in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String method();
+
+ /**
+ * Request path including the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path and query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String path();
+
+ /**
+ * The query for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the query, or an empty string if there is none.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String query();
+
+ /**
+ * Request path excluding the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path excluding query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String pathWithoutQuery();
+
+ /**
+ * The file extension for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the file extension, or an empty string if there is none.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ String fileExtension();
+
+ /**
+ * @return The detected content type of the request.
+ */
+ ContentType contentType();
+
+ /**
+ * @return The parameters contained in the request.
+ */
+ List parameters();
+
+ /**
+ * @param type The type of parameter that will be returned in the filtered list.
+ *
+ * @return A filtered list of {@link ParsedHttpParameter} containing only the provided type.
+ */
+ List parameters(HttpParameterType type);
+
+ /**
+ * @return True if the request has parameters.
+ */
+ boolean hasParameters();
+
+ /**
+ * @return True if the request has parameters of type {@link HttpParameterType}
+ */
+ boolean hasParameters(HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return An instance of {@link ParsedHttpParameter} that matches the type and name specified. {@code null} if not found.
+ */
+ ParsedHttpParameter parameter(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to get the value from.
+ * @param type The type of the parameter to get the value from.
+ *
+ * @return The value of the parameter that matches the name and type specified. {@code null} if not found.
+ */
+ String parameterValue(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return {@code true} if a parameter exists that matches the name and type specified. {@code false} if not found.
+ */
+ boolean hasParameter(String name, HttpParameterType type);
+
+ /**
+ * @param parameter An instance of {@link HttpParameter} to match to an existing parameter.
+ *
+ * @return {@code true} if a parameter exists that matches the data within the provided {@link HttpParameter}. {@code false} if not found.
+ */
+ boolean hasParameter(HttpParameter parameter);
+
+ /**
+ * @param header The header to check if it exists in the request.
+ *
+ * @return True if the header exists in the request.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * HTTP Version text parsed from the request or response line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpRequest} in temporary file.
+ * This method is used to save the {@code HttpRequest} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code HttpRequest} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code HttpRequest} instance stored in temporary file.
+ */
+ HttpRequest copyToTempFile();
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new service.
+ *
+ * @param service An {@link HttpService} reference to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withService(HttpService service);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new path.
+ *
+ * @param path The path to use.
+ *
+ * @return A new {@code HttpRequest} instance with updated path.
+ */
+ HttpRequest withPath(String path);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new method.
+ *
+ * @param method the method to use
+ *
+ * @return a new {@code HttpRequest} instance with updated method.
+ */
+ HttpRequest withMethod(String method);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param header HTTP header to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ HttpRequest withHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ HttpRequest withHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the HTTP parameter.
+ * If the parameter exists in the request, it is updated.
+ * If the parameter doesn't exist in the request, it is added.
+ *
+ * @param parameters HTTP parameter to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated parameter.
+ */
+ HttpRequest withParameter(HttpParameter parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withAddedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withAddedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withRemovedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withRemovedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withUpdatedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withUpdatedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the transformation applied.
+ *
+ * @param transformation Transformation to apply.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withTransformationApplied(HttpTransformation transformation);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ HttpRequest withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ HttpRequest withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the HTTP request.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ HttpRequest withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated request containing the updated header.
+ */
+ HttpRequest withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated request containing the updated header.
+ */
+ HttpRequest withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param name The name of the HTTP header to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ HttpRequest withRemovedHeader(String name);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param header The {@link HttpHeader} to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ HttpRequest withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ HttpRequest withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ HttpRequest withMarkers(Marker... markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with added default headers.
+ *
+ * @return a new {@link HttpRequest} with added default headers
+ */
+ HttpRequest withDefaultHeaders();
+
+ /**
+ * Create a new empty instance of {@link HttpRequest}.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequest()
+ {
+ return FACTORY.httpRequest();
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest}.
+ *
+ * @param request The HTTP request
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequest(ByteArray request)
+ {
+ return FACTORY.httpRequest(request);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest}.
+ *
+ * @param request The HTTP request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequest(String request)
+ {
+ return FACTORY.httpRequest(request);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest}.
+ *
+ * @param service An HTTP service for the request.
+ * @param request The HTTP request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequest(HttpService service, ByteArray request)
+ {
+ return FACTORY.httpRequest(service, request);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest}.
+ *
+ * @param service An HTTP service for the request.
+ * @param request The HTTP request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequest(HttpService service, String request)
+ {
+ return FACTORY.httpRequest(service, request);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest}.
+ *
+ * @param url A URL for the request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest httpRequestFromUrl(String url)
+ {
+ return FACTORY.httpRequestFromUrl(url);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest} containing HTTP 2 headers and body.
+ *
+ * @param service An HTTP service for the request.
+ * @param headers A list of HTTP 2 headers.
+ * @param body A body of the HTTP 2 request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest http2Request(HttpService service, List headers, ByteArray body)
+ {
+ return FACTORY.http2Request(service, headers, body);
+ }
+
+ /**
+ * Create a new instance of {@link HttpRequest} containing HTTP 2 headers and body.
+ *
+ * @param service An HTTP service for the request.
+ * @param headers A list of HTTP 2 headers.
+ * @param body A body of the HTTP 2 request.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ static HttpRequest http2Request(HttpService service, List headers, String body)
+ {
+ return FACTORY.http2Request(service, headers, body);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/requests/HttpTransformation.java b/src/burp/api/montoya/http/message/requests/HttpTransformation.java
new file mode 100644
index 0000000..085054b
--- /dev/null
+++ b/src/burp/api/montoya/http/message/requests/HttpTransformation.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.requests;
+
+/**
+ * This enum defines transformations that Burp can apply to an HTTP request.
+ */
+public enum HttpTransformation
+{
+ /**
+ * Convert a GET request into a POST request
+ * or
+ * Convert a POST request into a GET request
+ */
+ TOGGLE_METHOD
+}
diff --git a/src/burp/api/montoya/http/message/requests/MalformedRequestException.java b/src/burp/api/montoya/http/message/requests/MalformedRequestException.java
new file mode 100644
index 0000000..f09f10d
--- /dev/null
+++ b/src/burp/api/montoya/http/message/requests/MalformedRequestException.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.requests;
+
+/**
+ * This class represents an exception which is thrown when trying to retrieve attributes from a malformed request.
+ */
+public class MalformedRequestException extends RuntimeException
+{
+ public MalformedRequestException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/responses/HttpResponse.java b/src/burp/api/montoya/http/message/responses/HttpResponse.java
new file mode 100644
index 0000000..0debfef
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/HttpResponse.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.message.Cookie;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.HttpMessage;
+import burp.api.montoya.http.message.MimeType;
+import burp.api.montoya.http.message.StatusCodeClass;
+import burp.api.montoya.http.message.responses.analysis.Attribute;
+import burp.api.montoya.http.message.responses.analysis.AttributeType;
+import burp.api.montoya.http.message.responses.analysis.KeywordCount;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Burp HTTP response able to retrieve and modify details about an HTTP response.
+ */
+public interface HttpResponse extends HttpMessage
+{
+ /**
+ * Obtain the HTTP status code contained in the response.
+ *
+ * @return HTTP status code.
+ */
+ short statusCode();
+
+ /**
+ * Obtain the HTTP reason phrase contained in the response for HTTP 1 messages.
+ * HTTP 2 messages will return a mapped phrase based on the status code.
+ *
+ * @return HTTP Reason phrase.
+ */
+ String reasonPhrase();
+
+ /**
+ * Test whether the status code is in the specified class.
+ *
+ * @param statusCodeClass The class of status code to test.
+ *
+ * @return True if the status code is in the class.
+ */
+ boolean isStatusCodeClass(StatusCodeClass statusCodeClass);
+
+ /**
+ * Obtain details of the HTTP cookies set in the response.
+ *
+ * @return A list of {@link Cookie} objects representing the cookies set in the response, if any.
+ */
+ List cookies();
+
+ /**
+ * @param name The name of the cookie to find.
+ *
+ * @return An instance of {@link Cookie} that matches the name provided. {@code null} if not found.
+ */
+ Cookie cookie(String name);
+
+ /**
+ * @param name The name of the cookie to retrieve the value from.
+ *
+ * @return The value of the cookie that matches the name provided. {@code null} if not found.
+ */
+ String cookieValue(String name);
+
+ /**
+ * @param name The name of the cookie to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the name provided. {@code false} if not.
+ */
+ boolean hasCookie(String name);
+
+ /**
+ * @param cookie An instance of {@link Cookie} to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the {@link Cookie} provided. {@code false} if not.
+ */
+ boolean hasCookie(Cookie cookie);
+
+ /**
+ * Obtain the MIME type of the response, as determined by Burp Suite.
+ *
+ * @return The MIME type.
+ */
+ MimeType mimeType();
+
+ /**
+ * Obtain the MIME type of the response, as stated in the HTTP headers.
+ *
+ * @return The stated MIME type.
+ */
+ MimeType statedMimeType();
+
+ /**
+ * Obtain the MIME type of the response, as inferred from the contents of the HTTP message body.
+ *
+ * @return The inferred MIME type.
+ */
+ MimeType inferredMimeType();
+
+ /**
+ * Retrieve the number of types given keywords appear in the response.
+ *
+ * @param keywords Keywords to count.
+ *
+ * @return List of keyword counts in the order they were provided.
+ */
+ List keywordCounts(String... keywords);
+
+ /**
+ * Retrieve the values of response attributes.
+ *
+ * @param types Response attributes to retrieve values for.
+ *
+ * @return List of {@link Attribute} objects.
+ */
+ List attributes(AttributeType... types);
+
+ /**
+ * @param header The header to check if it exists in the request.
+ *
+ * @return True if the header exists in the request.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * HTTP Version text parsed from the request or response line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpResponse} in temporary file.
+ * This method is used to save the {@code HttpResponse} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code HttpResponse} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code HttpResponse} instance stored in temporary file.
+ */
+ HttpResponse copyToTempFile();
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the provided status code.
+ *
+ * @param statusCode the new status code for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ HttpResponse withStatusCode(short statusCode);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new reason phrase.
+ *
+ * @param reasonPhrase the new reason phrase for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ HttpResponse withReasonPhrase(String reasonPhrase);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new http version.
+ *
+ * @param httpVersion the new http version for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ HttpResponse withHttpVersion(String httpVersion);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ HttpResponse withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ HttpResponse withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the response.
+ *
+ * @return The updated response containing the added header.
+ */
+ HttpResponse withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated response containing the added header.
+ */
+ HttpResponse withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated response containing the updated header.
+ */
+ HttpResponse withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated response containing the updated header.
+ */
+ HttpResponse withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param header The {@link HttpHeader} to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ HttpResponse withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param name The name of the HTTP header to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ HttpResponse withRemovedHeader(String name);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ HttpResponse withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ HttpResponse withMarkers(Marker... markers);
+
+ /**
+ * Create a new empty instance of {@link HttpResponse}.
+ *
+ * @return A new {@link HttpResponse} instance.
+ */
+ static HttpResponse httpResponse()
+ {
+ return FACTORY.httpResponse();
+ }
+
+ /**
+ * Create a new instance of {@link HttpResponse}.
+ *
+ * @param response The HTTP response.
+ *
+ * @return A new {@link HttpResponse} instance.
+ */
+ static HttpResponse httpResponse(ByteArray response)
+ {
+ return FACTORY.httpResponse(response);
+ }
+
+ /**
+ * Create a new instance of {@link HttpResponse}.
+ *
+ * @param response The HTTP response.
+ *
+ * @return A new {@link HttpResponse} instance.
+ */
+ static HttpResponse httpResponse(String response)
+ {
+ return FACTORY.httpResponse(response);
+ }
+}
diff --git a/src/burp/api/montoya/http/message/responses/analysis/Attribute.java b/src/burp/api/montoya/http/message/responses/analysis/Attribute.java
new file mode 100644
index 0000000..82c5693
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/analysis/Attribute.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses.analysis;
+
+/**
+ * Burp attribute able to retrieve to hold details about HTTP response attributes.
+ */
+public interface Attribute
+{
+ /**
+ * @return The attribute type.
+ */
+ AttributeType type();
+
+ /**
+ * @return The attribute value.
+ */
+ int value();
+}
diff --git a/src/burp/api/montoya/http/message/responses/analysis/AttributeType.java b/src/burp/api/montoya/http/message/responses/analysis/AttributeType.java
new file mode 100644
index 0000000..0c3614b
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/analysis/AttributeType.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses.analysis;
+
+/**
+ * Otions that Burp can use to query attributes of HTTP responses.
+ */
+public enum AttributeType
+{
+ STATUS_CODE,
+ ETAG_HEADER,
+ LAST_MODIFIED_HEADER,
+ CONTENT_TYPE,
+ CONTENT_LENGTH,
+ COOKIE_NAMES,
+ TAG_NAMES,
+ TAG_IDS,
+ DIV_IDS,
+ BODY_CONTENT,
+ VISIBLE_TEXT,
+ WORD_COUNT,
+ VISIBLE_WORD_COUNT,
+ COMMENTS,
+ INITIAL_CONTENT,
+ CANONICAL_LINK,
+ PAGE_TITLE,
+ FIRST_HEADER_TAG,
+ HEADER_TAGS,
+ ANCHOR_LABELS,
+ INPUT_SUBMIT_LABELS,
+ BUTTON_SUBMIT_LABELS,
+ CSS_CLASSES,
+ LINE_COUNT,
+ LIMITED_BODY_CONTENT,
+ OUTBOUND_EDGE_COUNT,
+ OUTBOUND_EDGE_TAG_NAMES,
+ INPUT_IMAGE_LABELS,
+ CONTENT_LOCATION,
+ LOCATION,
+ NON_HIDDEN_FORM_INPUT_TYPES
+}
diff --git a/src/burp/api/montoya/http/message/responses/analysis/KeywordCount.java b/src/burp/api/montoya/http/message/responses/analysis/KeywordCount.java
new file mode 100644
index 0000000..324353c
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/analysis/KeywordCount.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses.analysis;
+
+/**
+ * Stores the number of types a given keyword appeared in a response.
+ */
+public interface KeywordCount
+{
+ /**
+ * @return The keyword.
+ */
+ String keyword();
+
+ /**
+ * @return The number of times the keyword appeared in a response.
+ */
+ int count();
+}
diff --git a/src/burp/api/montoya/http/message/responses/analysis/ResponseKeywordsAnalyzer.java b/src/burp/api/montoya/http/message/responses/analysis/ResponseKeywordsAnalyzer.java
new file mode 100644
index 0000000..b33bc6d
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/analysis/ResponseKeywordsAnalyzer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses.analysis;
+
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.Set;
+
+/**
+ * Analyze HTTP responses and retrieve keywords.
+ */
+public interface ResponseKeywordsAnalyzer
+{
+ /**
+ * @return A set of keywords whose counts vary between the analyzed responses.
+ */
+ Set variantKeywords();
+
+ /**
+ * @return A set of keywords whose counts do not vary between the analyzed responses.
+ */
+ Set invariantKeywords();
+
+ /**
+ * Update the analysis based on an additional response.
+ *
+ * @param response The new response to include in the analysis.
+ */
+ void updateWith(HttpResponse response);
+}
diff --git a/src/burp/api/montoya/http/message/responses/analysis/ResponseVariationsAnalyzer.java b/src/burp/api/montoya/http/message/responses/analysis/ResponseVariationsAnalyzer.java
new file mode 100644
index 0000000..039f5fa
--- /dev/null
+++ b/src/burp/api/montoya/http/message/responses/analysis/ResponseVariationsAnalyzer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.message.responses.analysis;
+
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.Set;
+
+/**
+ * Analyze HTTP responses and find variations between them, according to various attributes.
+ */
+public interface ResponseVariationsAnalyzer
+{
+ /**
+ * @return The attributes that vary between the analyzed responses.
+ */
+ Set variantAttributes();
+
+ /**
+ * @return The attributes that do not vary between the analyzed responses.
+ */
+ Set invariantAttributes();
+
+ /**
+ * Update the analysis based on an additional response.
+ *
+ * @param response The new response to include in the analysis.
+ */
+ void updateWith(HttpResponse response);
+}
diff --git a/src/burp/api/montoya/http/sessions/ActionResult.java b/src/burp/api/montoya/http/sessions/ActionResult.java
new file mode 100644
index 0000000..9451262
--- /dev/null
+++ b/src/burp/api/montoya/http/sessions/ActionResult.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.sessions;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * An instance of this interface should be returned by {@link SessionHandlingAction#performAction(SessionHandlingActionData)}.
+ */
+public interface ActionResult
+{
+ /**
+ * @return The HTTP request.
+ */
+ HttpRequest request();
+
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * Create a new instance of {@code ActionResult}.
+ * Annotations will not be modified.
+ *
+ * @param request An HTTP request.
+ *
+ * @return A new {@code ActionResult} instance.
+ */
+ static ActionResult actionResult(HttpRequest request)
+ {
+ return FACTORY.actionResult(request);
+ }
+
+ /**
+ * Create a new instance of {@code ActionResult}.
+ *
+ * @param request An HTTP request.
+ * @param annotations modified annotations.
+ *
+ * @return A new {@code ActionResult} instance.
+ */
+ static ActionResult actionResult(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.actionResult(request, annotations);
+ }
+}
diff --git a/src/burp/api/montoya/http/sessions/CookieJar.java b/src/burp/api/montoya/http/sessions/CookieJar.java
new file mode 100644
index 0000000..edccc1e
--- /dev/null
+++ b/src/burp/api/montoya/http/sessions/CookieJar.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.sessions;
+
+import burp.api.montoya.http.message.Cookie;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+
+/**
+ * Provides access to Burp's Cookie Jar functionality.
+ */
+public interface CookieJar
+{
+ /**
+ * Add a new HTTP cookie to the Cookie Jar.
+ *
+ * @param name The name of the cookie.
+ * @param value The value of the cookie.
+ * @param path The path for which the cookie is in scope or {@code null} if none is set.
+ * @param domain The domain for which the cookie is in scope.
+ * @param expiration The expiration time for the cookie, or {@code null} if none is set (i.e., for non-persistent session cookies).
+ */
+ void setCookie(String name, String value, String path, String domain, ZonedDateTime expiration);
+
+ /**
+ * @return A list of stored cookies.
+ */
+ List cookies();
+}
diff --git a/src/burp/api/montoya/http/sessions/SessionHandlingAction.java b/src/burp/api/montoya/http/sessions/SessionHandlingAction.java
new file mode 100644
index 0000000..fa1767c
--- /dev/null
+++ b/src/burp/api/montoya/http/sessions/SessionHandlingAction.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.sessions;
+
+import burp.api.montoya.http.Http;
+
+/**
+ * Extensions can implement this interface and then call {@link Http#registerSessionHandlingAction} to register a custom session handling action. Each registered action will be
+ * available within the session handling rule UI for the user to select as a rule action. Users can choose to invoke an action directly in its own right, or following execution of
+ * a macro.
+ */
+public interface SessionHandlingAction
+{
+ /**
+ * @return Action name
+ */
+ String name();
+
+ /**
+ * Invoked when the session handling action should be executed.
+ * This may happen as an action in its own right, or as a sub-action following execution of a macro.
+ * It can issue additional requests of its own if necessary, and can return a modified base request in the {@link ActionResult}
+ *
+ * @param actionData {@link SessionHandlingActionData} The action can query this object to obtain details about the base request.
+ *
+ * @return A new {@link ActionResult} instance.
+ */
+ ActionResult performAction(SessionHandlingActionData actionData);
+}
diff --git a/src/burp/api/montoya/http/sessions/SessionHandlingActionData.java b/src/burp/api/montoya/http/sessions/SessionHandlingActionData.java
new file mode 100644
index 0000000..d5c2c3f
--- /dev/null
+++ b/src/burp/api/montoya/http/sessions/SessionHandlingActionData.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.http.sessions;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+import java.util.List;
+
+/**
+ * Information required for session handling.
+ */
+public interface SessionHandlingActionData
+{
+ /**
+ * @return The base request that is currently being processed.
+ */
+ HttpRequest request();
+
+ /**
+ * If the action is invoked following execution of a macro, this method contains the result of executing the macro. Otherwise, it is an empty list. Actions can use the details
+ * of the macro items to perform custom analysis of the macro to derive values of non-standard session handling tokens, etc.
+ *
+ * @return List of {@link HttpRequestResponse} generated during the execution of the macro.
+ */
+ List macroRequestResponses();
+
+ /**
+ * @return The message annotation on the request.
+ */
+ Annotations annotations();
+}
diff --git a/src/burp/api/montoya/internal/MontoyaObjectFactory.java b/src/burp/api/montoya/internal/MontoyaObjectFactory.java
new file mode 100644
index 0000000..2729457
--- /dev/null
+++ b/src/burp/api/montoya/internal/MontoyaObjectFactory.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.internal;
+
+import burp.api.montoya.collaborator.InteractionFilter;
+import burp.api.montoya.collaborator.SecretKey;
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.HighlightColor;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.core.Range;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.RequestOptions;
+import burp.api.montoya.http.handler.RequestToBeSentAction;
+import burp.api.montoya.http.handler.ResponseReceivedAction;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.params.HttpParameter;
+import burp.api.montoya.http.message.params.HttpParameterType;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.http.sessions.ActionResult;
+import burp.api.montoya.intruder.GeneratedPayload;
+import burp.api.montoya.intruder.HttpRequestTemplate;
+import burp.api.montoya.intruder.HttpRequestTemplateGenerationOptions;
+import burp.api.montoya.intruder.PayloadProcessingAction;
+import burp.api.montoya.intruder.PayloadProcessingResult;
+import burp.api.montoya.persistence.PersistedList;
+import burp.api.montoya.persistence.PersistedObject;
+import burp.api.montoya.proxy.MessageReceivedAction;
+import burp.api.montoya.proxy.MessageToBeSentAction;
+import burp.api.montoya.proxy.http.ProxyRequestReceivedAction;
+import burp.api.montoya.proxy.http.ProxyRequestToBeSentAction;
+import burp.api.montoya.proxy.http.ProxyResponseReceivedAction;
+import burp.api.montoya.proxy.http.ProxyResponseToBeSentAction;
+import burp.api.montoya.proxy.websocket.BinaryMessageReceivedAction;
+import burp.api.montoya.proxy.websocket.BinaryMessageToBeSentAction;
+import burp.api.montoya.proxy.websocket.TextMessageReceivedAction;
+import burp.api.montoya.proxy.websocket.TextMessageToBeSentAction;
+import burp.api.montoya.scanner.AuditConfiguration;
+import burp.api.montoya.scanner.AuditResult;
+import burp.api.montoya.scanner.BuiltInAuditConfiguration;
+import burp.api.montoya.scanner.CrawlConfiguration;
+import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+import burp.api.montoya.scanner.audit.issues.AuditIssueConfidence;
+import burp.api.montoya.scanner.audit.issues.AuditIssueDefinition;
+import burp.api.montoya.scanner.audit.issues.AuditIssueSeverity;
+import burp.api.montoya.sitemap.SiteMapFilter;
+import burp.api.montoya.ui.Selection;
+import burp.api.montoya.ui.menu.BasicMenuItem;
+import burp.api.montoya.ui.menu.Menu;
+import burp.api.montoya.websocket.BinaryMessageAction;
+import burp.api.montoya.websocket.MessageAction;
+import burp.api.montoya.websocket.TextMessageAction;
+
+import java.util.List;
+
+public interface MontoyaObjectFactory
+{
+ HttpService httpService(String baseUrl);
+
+ HttpService httpService(String host, boolean secure);
+
+ HttpService httpService(String host, int port, boolean secure);
+
+ HttpHeader httpHeader(String name, String value);
+
+ HttpHeader httpHeader(String header);
+
+ HttpParameter parameter(String name, String value, HttpParameterType type);
+
+ HttpRequest httpRequest();
+
+ HttpRequest httpRequest(ByteArray request);
+
+ HttpRequest httpRequest(String request);
+
+ HttpRequest httpRequest(HttpService service, ByteArray request);
+
+ HttpRequest httpRequest(HttpService service, String request);
+
+ HttpRequest http2Request(HttpService service, List headers, String body);
+
+ HttpRequest http2Request(HttpService service, List headers, ByteArray body);
+
+ HttpRequest httpRequestFromUrl(String url);
+
+ HttpResponse httpResponse();
+
+ HttpResponse httpResponse(String response);
+
+ HttpResponse httpResponse(ByteArray response);
+
+ HttpRequestResponse httpRequestResponse(HttpRequest request, HttpResponse response, Annotations annotations);
+
+ HttpRequestResponse httpRequestResponse(HttpRequest request, HttpResponse response);
+
+ Range range(int startIndexInclusive, int endIndexExclusive);
+
+ Annotations annotations();
+
+ Annotations annotations(String notes);
+
+ Annotations annotations(HighlightColor highlightColor);
+
+ Annotations annotations(String notes, HighlightColor highlightColor);
+
+ AuditInsertionPoint auditInsertionPoint(String name, HttpRequest baseRequest, int startIndexInclusive, int endIndexExclusive);
+
+ AuditIssueDefinition auditIssueDefinition(String name, String background, String remediation, AuditIssueSeverity typicalSeverity);
+
+ AuditIssue auditIssue(
+ String name,
+ String detail,
+ String remediation,
+ String baseUrl,
+ AuditIssueSeverity severity,
+ AuditIssueConfidence confidence,
+ String background,
+ String remediationBackground,
+ AuditIssueSeverity typicalSeverity,
+ List requestResponses);
+
+ AuditIssue auditIssue(
+ String name,
+ String detail,
+ String remediation,
+ String baseUrl,
+ AuditIssueSeverity severity,
+ AuditIssueConfidence confidence,
+ String background,
+ String remediationBackground,
+ AuditIssueSeverity typicalSeverity,
+ HttpRequestResponse... requestResponses);
+
+ Selection selection(ByteArray selectionContents);
+
+ Selection selection(int startIndexInclusive, int endIndexExclusive);
+
+ Selection selection(ByteArray selectionContents, int startIndexInclusive, int endIndexExclusive);
+
+ SecretKey secretKey(String encodedKey);
+
+ ProxyRequestReceivedAction proxyRequestReceivedAction(HttpRequest request, Annotations annotations, MessageReceivedAction action);
+
+ ProxyRequestToBeSentAction proxyRequestToBeSentAction(HttpRequest request, Annotations annotations, MessageToBeSentAction action);
+
+ ProxyResponseToBeSentAction proxyResponseToReturnAction(HttpResponse response, Annotations annotations, MessageToBeSentAction action);
+
+ ProxyResponseReceivedAction proxyResponseReceivedAction(HttpResponse response, Annotations annotations, MessageReceivedAction action);
+
+ RequestToBeSentAction requestResult(HttpRequest request, Annotations annotations);
+
+ ResponseReceivedAction responseResult(HttpResponse response, Annotations annotations);
+
+ HttpRequestTemplate httpRequestTemplate(ByteArray content, List insertionPointOffsets);
+
+ HttpRequestTemplate httpRequestTemplate(HttpRequest request, List insertionPointOffsets);
+
+ HttpRequestTemplate httpRequestTemplate(ByteArray content, HttpRequestTemplateGenerationOptions options);
+
+ HttpRequestTemplate httpRequestTemplate(HttpRequest request, HttpRequestTemplateGenerationOptions options);
+
+ PayloadProcessingResult payloadProcessingResult(ByteArray processedPayload, PayloadProcessingAction action);
+
+ InteractionFilter interactionIdFilter(String id);
+
+ InteractionFilter interactionPayloadFilter(String payload);
+
+ SiteMapFilter prefixFilter(String prefix);
+
+ Marker marker(Range range);
+
+ Marker marker(int startIndexInclusive, int endIndexExclusive);
+
+ ByteArray byteArrayOfLength(int length);
+
+ ByteArray byteArray(byte[] bytes);
+
+ ByteArray byteArray(int[] ints);
+
+ ByteArray byteArray(String text);
+
+ TextMessageAction continueWithTextMessage(String payload);
+
+ TextMessageAction dropTextMessage();
+
+ TextMessageAction textMessageAction(String payload, MessageAction action);
+
+ BinaryMessageAction continueWithBinaryMessage(ByteArray payload);
+
+ BinaryMessageAction dropBinaryMessage();
+
+ BinaryMessageAction binaryMessageAction(ByteArray payload, MessageAction action);
+
+ BinaryMessageReceivedAction followUserRulesInitialProxyBinaryMessage(ByteArray payload);
+
+ TextMessageReceivedAction followUserRulesInitialProxyTextMessage(String payload);
+
+ BinaryMessageReceivedAction interceptInitialProxyBinaryMessage(ByteArray payload);
+
+ TextMessageReceivedAction interceptInitialProxyTextMessage(String payload);
+
+ BinaryMessageReceivedAction dropInitialProxyBinaryMessage();
+
+ TextMessageReceivedAction dropInitialProxyTextMessage();
+
+ BinaryMessageReceivedAction doNotInterceptInitialProxyBinaryMessage(ByteArray payload);
+
+ TextMessageReceivedAction doNotInterceptInitialProxyTextMessage(String payload);
+
+ BinaryMessageToBeSentAction continueWithFinalProxyBinaryMessage(ByteArray payload);
+
+ TextMessageToBeSentAction continueWithFinalProxyTextMessage(String payload);
+
+ BinaryMessageToBeSentAction dropFinalProxyBinaryMessage();
+
+ TextMessageToBeSentAction dropFinalProxyTextMessage();
+
+ PersistedObject persistedObject();
+
+ PersistedList persistedBooleanList();
+
+ PersistedList persistedShortList();
+
+ PersistedList persistedIntegerList();
+
+ PersistedList persistedLongList();
+
+ PersistedList persistedStringList();
+
+ PersistedList persistedByteArrayList();
+
+ PersistedList persistedHttpRequestList();
+
+ PersistedList persistedHttpResponseList();
+
+ PersistedList persistedHttpRequestResponseList();
+
+ AuditResult auditResult(List auditIssues);
+
+ AuditResult auditResult(AuditIssue... auditIssues);
+
+ AuditConfiguration auditConfiguration(BuiltInAuditConfiguration builtInAuditConfiguration);
+
+ CrawlConfiguration crawlConfiguration(String... seedUrls);
+
+ HttpParameter urlParameter(String name, String value);
+
+ HttpParameter bodyParameter(String name, String value);
+
+ HttpParameter cookieParameter(String name, String value);
+
+ GeneratedPayload payload(String payload);
+
+ GeneratedPayload payload(ByteArray payload);
+
+ GeneratedPayload payloadEnd();
+
+ PayloadProcessingResult usePayload(ByteArray processedPayload);
+
+ PayloadProcessingResult skipPayload();
+
+ ProxyRequestToBeSentAction requestFinalInterceptResultContinueWith(HttpRequest request);
+
+ ProxyRequestToBeSentAction requestFinalInterceptResultContinueWith(HttpRequest request, Annotations annotations);
+
+ ProxyRequestToBeSentAction requestFinalInterceptResultDrop();
+
+ ProxyResponseToBeSentAction responseFinalInterceptResultDrop();
+
+ ProxyResponseToBeSentAction responseFinalInterceptResultContinueWith(HttpResponse response, Annotations annotations);
+
+ ProxyResponseToBeSentAction responseFinalInterceptResultContinueWith(HttpResponse response);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultIntercept(HttpResponse response);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultIntercept(HttpResponse response, Annotations annotations);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultDoNotIntercept(HttpResponse response);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultDoNotIntercept(HttpResponse response, Annotations annotations);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultFollowUserRules(HttpResponse response);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultFollowUserRules(HttpResponse response, Annotations annotations);
+
+ ProxyResponseReceivedAction responseInitialInterceptResultDrop();
+
+ ProxyRequestReceivedAction requestInitialInterceptResultIntercept(HttpRequest request);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultIntercept(HttpRequest request, Annotations annotations);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultDoNotIntercept(HttpRequest request);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultDoNotIntercept(HttpRequest request, Annotations annotations);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultFollowUserRules(HttpRequest request);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultFollowUserRules(HttpRequest request, Annotations annotations);
+
+ ProxyRequestReceivedAction requestInitialInterceptResultDrop();
+
+ ResponseReceivedAction responseResult(HttpResponse response);
+
+ RequestToBeSentAction requestResult(HttpRequest request);
+
+ HighlightColor highlightColor(String color);
+
+ ActionResult actionResult(HttpRequest request);
+
+ ActionResult actionResult(HttpRequest request, Annotations annotations);
+
+ Menu menu(String caption);
+
+ BasicMenuItem basicMenuItem(String caption);
+
+ RequestOptions requestOptions();
+}
diff --git a/src/burp/api/montoya/internal/ObjectFactoryLocator.java b/src/burp/api/montoya/internal/ObjectFactoryLocator.java
new file mode 100644
index 0000000..972175e
--- /dev/null
+++ b/src/burp/api/montoya/internal/ObjectFactoryLocator.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.internal;
+
+public class ObjectFactoryLocator
+{
+ /**
+ * This is initialized when your extension is loaded.
+ */
+ public static MontoyaObjectFactory FACTORY = null;
+}
diff --git a/src/burp/api/montoya/intruder/AttackConfiguration.java b/src/burp/api/montoya/intruder/AttackConfiguration.java
new file mode 100644
index 0000000..42c257d
--- /dev/null
+++ b/src/burp/api/montoya/intruder/AttackConfiguration.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.http.HttpService;
+
+import java.util.Optional;
+
+/**
+ * Intruder attack configuration.
+ */
+public interface AttackConfiguration
+{
+ /**
+ * {@link HttpService} for the attack.
+ *
+ * @return An {@link Optional} of {@link HttpService} instance derived from this attack configuration or {@link Optional#empty} if the target template contains payload markers.
+ */
+ Optional httpService();
+
+ /**
+ * HTTP request template and insertion point offsets in a
+ * form of an {@link HttpRequestTemplate} instance.
+ *
+ * @return An instance of {@link HttpRequestTemplate}.
+ */
+ HttpRequestTemplate requestTemplate();
+}
diff --git a/src/burp/api/montoya/intruder/GeneratedPayload.java b/src/burp/api/montoya/intruder/GeneratedPayload.java
new file mode 100644
index 0000000..3b4c52b
--- /dev/null
+++ b/src/burp/api/montoya/intruder/GeneratedPayload.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.ByteArray;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Intruder payload.
+ */
+public interface GeneratedPayload
+{
+ /**
+ * @return Payload value.
+ */
+ ByteArray value();
+
+ /**
+ * Create a new {@link GeneratedPayload} instance from a String payload value.
+ *
+ * @param payload String payload value.
+ *
+ * @return A new {@link GeneratedPayload} instance.
+ */
+ static GeneratedPayload payload(String payload)
+ {
+ return FACTORY.payload(payload);
+ }
+
+ /**
+ * Create a new {@link GeneratedPayload} instance from a byte array payload value.
+ *
+ * @param payload Byte array payload value.
+ *
+ * @return A new {@link GeneratedPayload} instance.
+ */
+ static GeneratedPayload payload(ByteArray payload)
+ {
+ return FACTORY.payload(payload);
+ }
+
+ /**
+ * Create a new {@link GeneratedPayload} instance to signify there are no more payloads.
+ *
+ * @return A new {@link GeneratedPayload} instance.
+ */
+ static GeneratedPayload end()
+ {
+ return FACTORY.payloadEnd();
+ }
+}
diff --git a/src/burp/api/montoya/intruder/HttpRequestTemplate.java b/src/burp/api/montoya/intruder/HttpRequestTemplate.java
new file mode 100644
index 0000000..70cb07a
--- /dev/null
+++ b/src/burp/api/montoya/intruder/HttpRequestTemplate.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Range;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Intruder request template, which contains the HTTP request and insertion point offsets.
+ */
+public interface HttpRequestTemplate
+{
+ /**
+ * @return Content of the request template.
+ */
+ ByteArray content();
+
+ /**
+ * Insertion point offsets for an Intruder attack.
+ *
+ * @return A list of {@link Range} objects representing insertion point offsets.
+ */
+ List insertionPointOffsets();
+
+ /**
+ * Create a new {@link HttpRequestTemplate} instance
+ * from an {@link HttpRequest} object and a list of insertion point offsets.
+ *
+ * @param request An instance of {@link HttpRequest}.
+ * @param insertionPointOffsets List of insertion point offsets.
+ *
+ * @return A new instance of {@link HttpRequestTemplate}.
+ */
+ static HttpRequestTemplate httpRequestTemplate(HttpRequest request, List insertionPointOffsets)
+ {
+ return FACTORY.httpRequestTemplate(request, insertionPointOffsets);
+ }
+
+ /**
+ * Create a new {@link HttpRequestTemplate} instance
+ * from an HTTP request in a byte array form and a list of insertion point offsets.
+ *
+ * @param content An HTTP request in a byte array form.
+ * @param insertionPointOffsets List of insertion point offsets.
+ *
+ * @return A new instance of {@link HttpRequestTemplate}.
+ */
+ static HttpRequestTemplate httpRequestTemplate(ByteArray content, List insertionPointOffsets)
+ {
+ return FACTORY.httpRequestTemplate(content, insertionPointOffsets);
+ }
+
+ /**
+ * Create a new {@link HttpRequestTemplate} instance
+ * from an {@link HttpRequest} object with insertion point offsets at each URL, cookie, and body parameter position.
+ *
+ * @param request An instance of {@link HttpRequest}.
+ * @param options Options to use when generating the template.
+ *
+ * @return A new instance of {@link HttpRequestTemplate}.
+ */
+ static HttpRequestTemplate httpRequestTemplate(HttpRequest request, HttpRequestTemplateGenerationOptions options)
+ {
+ return FACTORY.httpRequestTemplate(request, options);
+ }
+
+ /**
+ * Create a new {@link HttpRequestTemplate} instance
+ * from an HTTP request in a byte array form with insertion point offsets at each URL, cookie, and body parameter position.
+ *
+ * @param content An HTTP request in a byte array form.
+ * @param options Options to use when generating the template.
+ *
+ * @return A new instance of {@link HttpRequestTemplate}.
+ */
+ static HttpRequestTemplate httpRequestTemplate(ByteArray content, HttpRequestTemplateGenerationOptions options)
+ {
+ return FACTORY.httpRequestTemplate(content, options);
+ }
+}
diff --git a/src/burp/api/montoya/intruder/HttpRequestTemplateGenerationOptions.java b/src/burp/api/montoya/intruder/HttpRequestTemplateGenerationOptions.java
new file mode 100644
index 0000000..ca842b0
--- /dev/null
+++ b/src/burp/api/montoya/intruder/HttpRequestTemplateGenerationOptions.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+/**
+ * Options that can be used to generate a new HttpRequestTemplate.
+ */
+public enum HttpRequestTemplateGenerationOptions
+{
+ /**
+ * Replace base parameter value with offsets.
+ */
+ REPLACE_BASE_PARAMETER_VALUE_WITH_OFFSETS,
+
+ /**
+ * Append offsets to base parameter value.
+ */
+ APPEND_OFFSETS_TO_BASE_PARAMETER_VALUE
+}
diff --git a/src/burp/api/montoya/intruder/Intruder.java b/src/burp/api/montoya/intruder/Intruder.java
new file mode 100644
index 0000000..c3426aa
--- /dev/null
+++ b/src/burp/api/montoya/intruder/Intruder.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+/**
+ * Provides access to the functionality of the Burp Intruder tool.
+ */
+public interface Intruder
+{
+ /**
+ * Register a custom Intruder payload processor. Each registered
+ * processor will be available within the Intruder UI for the user to select as the
+ * action for a payload processing rule.
+ *
+ * @param payloadProcessor An object created by the extension that implements the
+ * {@link PayloadProcessor} interface.
+ *
+ * @return The {@link Registration} for the payload processor.
+ */
+ Registration registerPayloadProcessor(PayloadProcessor payloadProcessor);
+
+ /**
+ * Register a provider for Intruder payloads. Each registered
+ * provider will be available within the Intruder UI for the user to select as the payload
+ * source for an attack. When this is selected, the provider will be asked to provide a
+ * new instance of an {@link PayloadGenerator} object, which will be used to generate
+ * payloads for the attack.
+ *
+ * @param payloadGeneratorProvider An object created by the extension that implements the
+ * PayloadGeneratorProvider interface.
+ *
+ * @return The {@link Registration} for the payload generator provider.
+ */
+ Registration registerPayloadGeneratorProvider(PayloadGeneratorProvider payloadGeneratorProvider);
+
+ /**
+ * Send an HTTP request to the Burp Intruder tool. The request
+ * will be displayed in the user interface, and markers for attack payloads will be placed
+ * into the locations specified in the provided {@link HttpRequestTemplate} object.
+ *
+ * @param service An {@link HttpService} object that specifies the hostname, port and protocol
+ * of a remote server.
+ * @param requestTemplate An HTTP request template containing insertion point offsets.
+ */
+ void sendToIntruder(HttpService service, HttpRequestTemplate requestTemplate);
+
+ /**
+ * Send an HTTP request to the Burp Intruder tool. The request
+ * will be displayed in the user interface.
+ *
+ * @param request The full HTTP request.
+ */
+ void sendToIntruder(HttpRequest request);
+}
diff --git a/src/burp/api/montoya/intruder/IntruderInsertionPoint.java b/src/burp/api/montoya/intruder/IntruderInsertionPoint.java
new file mode 100644
index 0000000..19cef6f
--- /dev/null
+++ b/src/burp/api/montoya/intruder/IntruderInsertionPoint.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.ByteArray;
+
+/**
+ * Intruder insertion point for attack payloads.
+ */
+public interface IntruderInsertionPoint
+{
+ /**
+ * @return The base value of the insertion point.
+ */
+ ByteArray baseValue();
+}
diff --git a/src/burp/api/montoya/intruder/PayloadData.java b/src/burp/api/montoya/intruder/PayloadData.java
new file mode 100644
index 0000000..6babe17
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadData.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.ByteArray;
+
+/**
+ * Contains information about the payload
+ */
+public interface PayloadData
+{
+ /**
+ * @return The value of the payload to be processed.
+ */
+ ByteArray currentPayload();
+
+ /**
+ * @return The value of the original payload prior to processing by any already-applied processing rules
+ */
+ ByteArray originalPayload();
+
+ /**
+ * @return The insertion point data.
+ */
+ IntruderInsertionPoint insertionPoint();
+}
diff --git a/src/burp/api/montoya/intruder/PayloadGenerator.java b/src/burp/api/montoya/intruder/PayloadGenerator.java
new file mode 100644
index 0000000..26783da
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadGenerator.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+/**
+ * Intruder payload generator. Extensions that have registered
+ * a {@link PayloadGeneratorProvider} must return a new instance of this interface when required as part
+ * of a new Intruder attack.
+ */
+public interface PayloadGenerator
+{
+ /**
+ * Invoked by Burp to obtain the value of the next payload.
+ * Should return {@link GeneratedPayload#end()} instance to signal to Burp that the generator has finished.
+ *
+ * @param insertionPoint Insertion point for the payload.
+ *
+ * @return A generated Intruder payload.
+ */
+ GeneratedPayload generatePayloadFor(IntruderInsertionPoint insertionPoint);
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/intruder/PayloadGeneratorProvider.java b/src/burp/api/montoya/intruder/PayloadGeneratorProvider.java
new file mode 100644
index 0000000..ed6976d
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadGeneratorProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+/**
+ * Extensions can implement this interface and then call {@link Intruder#registerPayloadGeneratorProvider}
+ * to register a provider for custom Intruder payload generators.
+ */
+public interface PayloadGeneratorProvider
+{
+ /**
+ * Name Burp will use when displaying the payload generator
+ * in a dropdown list in the UI.
+ *
+ * @return Name of the payload generator.
+ */
+ String displayName();
+
+ /**
+ * Invoked by Burp to obtain an instance of {@link PayloadGenerator}
+ * to add to Intruder.
+ *
+ * @param attackConfiguration An object containing information about the currently
+ * selected attack configuration tab.
+ *
+ * @return An instance of an object that implements the {@link PayloadGenerator} interface.
+ */
+ PayloadGenerator providePayloadGenerator(AttackConfiguration attackConfiguration);
+}
diff --git a/src/burp/api/montoya/intruder/PayloadProcessingAction.java b/src/burp/api/montoya/intruder/PayloadProcessingAction.java
new file mode 100644
index 0000000..ba9255e
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadProcessingAction.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+/**
+ * Instructions that the payload processor can give Intruder for the current payload.
+ */
+public enum PayloadProcessingAction
+{
+ /**
+ * Skip the current payload
+ */
+ SKIP_PAYLOAD,
+ /**
+ * Use the current payload
+ */
+ USE_PAYLOAD
+}
diff --git a/src/burp/api/montoya/intruder/PayloadProcessingResult.java b/src/burp/api/montoya/intruder/PayloadProcessingResult.java
new file mode 100644
index 0000000..228ec41
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadProcessingResult.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+import burp.api.montoya.core.ByteArray;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * An instance of this interface should be returned by {@link PayloadProcessor#processPayload} if a custom
+ * {@link PayloadProcessor} was registered with Intruder.
+ */
+public interface PayloadProcessingResult
+{
+ /**
+ * @return The current value of the processed payload.
+ */
+ ByteArray processedPayload();
+
+ /**
+ * Invoked by Burp to see what action it should perform with the payload. If the value
+ * is {@link PayloadProcessingAction#USE_PAYLOAD}, Burp will use the payload in the attack or skip it
+ * if the value is {@link PayloadProcessingAction#SKIP_PAYLOAD}.
+ *
+ * @return Action to perform with the payload.
+ */
+ PayloadProcessingAction action();
+
+ /**
+ * Create a new instance of {@link PayloadProcessingResult} with a
+ * {@link PayloadProcessingAction#USE_PAYLOAD} action.
+ *
+ * @param processedPayload Processed payload value
+ *
+ * @return A new {@link PayloadProcessingResult} instance.
+ */
+ static PayloadProcessingResult usePayload(ByteArray processedPayload)
+ {
+ return FACTORY.usePayload(processedPayload);
+ }
+
+ /**
+ * Create a new instance of {@link PayloadProcessingResult} with a
+ * {@link PayloadProcessingAction#SKIP_PAYLOAD} action.
+ *
+ * @return A new {@link PayloadProcessingResult} instance.
+ */
+ static PayloadProcessingResult skipPayload()
+ {
+ return FACTORY.skipPayload();
+ }
+
+ static PayloadProcessingResult payloadProcessingResult(ByteArray processedPayload, PayloadProcessingAction action)
+ {
+ return FACTORY.payloadProcessingResult(processedPayload, action);
+ }
+}
diff --git a/src/burp/api/montoya/intruder/PayloadProcessor.java b/src/burp/api/montoya/intruder/PayloadProcessor.java
new file mode 100644
index 0000000..512f6a2
--- /dev/null
+++ b/src/burp/api/montoya/intruder/PayloadProcessor.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.intruder;
+
+/**
+ * Extensions can implement this interface and then call {@link Intruder#registerPayloadProcessor} to register a
+ * custom Intruder payload processor.
+ */
+public interface PayloadProcessor
+{
+ /**
+ * Name Burp will use when displaying the payload processor
+ * in a dropdown list in the UI.
+ *
+ * @return Name of the payload processor
+ */
+ String displayName();
+
+ /**
+ * Invoked by Burp each time the processor should be applied to an Intruder payload.
+ *
+ * @param payloadData Information about the current payload to be processed
+ *
+ * @return The value of the processed payload.
+ */
+ PayloadProcessingResult processPayload(PayloadData payloadData);
+}
diff --git a/src/burp/api/montoya/logger/LoggerHttpRequestResponse.java b/src/burp/api/montoya/logger/LoggerHttpRequestResponse.java
new file mode 100644
index 0000000..00ed114
--- /dev/null
+++ b/src/burp/api/montoya/logger/LoggerHttpRequestResponse.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.logger;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ToolSource;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.handler.TimingData;
+import burp.api.montoya.http.message.MimeType;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.time.ZonedDateTime;
+import java.util.regex.Pattern;
+
+/**
+ * This interface is used to define a coupling between {@link HttpRequest} and {@link HttpResponse} for the Logger.
+ */
+public interface LoggerHttpRequestResponse
+{
+ /**
+ * @return The HTTP request message.
+ */
+ HttpRequest request();
+
+ /**
+ * @return The HTTP response message.
+ */
+ HttpResponse response();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ HttpService httpService();
+
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * Returns the date and time at which Burp Logger received the request.
+ *
+ * @return The time at which Burp Logger received the request.
+ */
+ ZonedDateTime time();
+
+ /**
+ * Obtain the MIME type of the response or request, as determined by Burp Suite.
+ * If there is no response the mime type will be determined from the request url.
+ *
+ * @return The MIME type.
+ */
+ MimeType mimeType();
+
+ /**
+ * @return True if there is a response.
+ */
+ boolean hasResponse();
+
+ /**
+ * Retrieve the timing data associated with this request.
+ *
+ * @return The timing data.
+ */
+ TimingData timingData();
+
+ /**
+ * The page title for the response.
+ *
+ * @return The page title, or an empty string if none exists.
+ */
+ String pageTitle();
+
+ /**
+ * The tool that issued the request.
+ *
+ * @return ToolSource which indicates which Burp tool sent the request.
+ */
+ ToolSource toolSource();
+
+ /**
+ * Searches the data in the HTTP request, response and notes for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP request, response and notes for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ boolean contains(Pattern pattern);
+}
diff --git a/src/burp/api/montoya/logging/Logging.java b/src/burp/api/montoya/logging/Logging.java
new file mode 100644
index 0000000..a372545
--- /dev/null
+++ b/src/burp/api/montoya/logging/Logging.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.logging;
+
+import java.io.PrintStream;
+
+/**
+ * Provides access to the functionality related to logging and events.
+ */
+public interface Logging
+{
+ /**
+ * Obtain the current extension's standard output
+ * stream. Extensions should write all output to this stream, allowing the
+ * Burp user to configure how that output is handled from within the UI.
+ *
+ * @return The extension's standard output stream.
+ *
+ * @deprecated Use {@link burp.api.montoya.logging.Logging#logToOutput} instead.
+ */
+ @Deprecated
+ PrintStream output();
+
+ /**
+ * Obtain the current extension's standard error
+ * stream. Extensions should write all error messages to this stream,
+ * allowing the Burp user to configure how that output is handled from
+ * within the UI.
+ *
+ * @return The extension's standard error stream.
+ *
+ * @deprecated Use {@link burp.api.montoya.logging.Logging#logToError} instead.
+ */
+ @Deprecated
+ PrintStream error();
+
+ /**
+ * This method prints a line of output to the current extension's standard
+ * output stream.
+ *
+ * @param message The message to print.
+ */
+ void logToOutput(String message);
+
+ /**
+ * This method prints a line of output to the current extension's standard
+ * error stream.
+ *
+ * @param message The message to print.
+ */
+ void logToError(String message);
+
+ /**
+ * This method prints a message and a stack trace to the current extension's standard
+ * error stream.
+ *
+ * @param message The message to print.
+ * @param cause The cause of the error being logged.
+ */
+ void logToError(String message, Throwable cause);
+
+ /**
+ * This method prints a stack trace to the current extension's standard
+ * error stream.
+ *
+ * @param cause The cause of the error being logged.
+ */
+ void logToError(Throwable cause);
+
+ /**
+ * This method can be used to display a debug event in the Burp Suite
+ * event log.
+ *
+ * @param message The debug message to display.
+ */
+ void raiseDebugEvent(String message);
+
+ /**
+ * This method can be used to display an informational event in the Burp
+ * Suite event log.
+ *
+ * @param message The informational message to display.
+ */
+ void raiseInfoEvent(String message);
+
+ /**
+ * This method can be used to display an error event in the Burp Suite
+ * event log.
+ *
+ * @param message The error message to display.
+ */
+ void raiseErrorEvent(String message);
+
+ /**
+ * This method can be used to display a critical event in the Burp Suite
+ * event log.
+ *
+ * @param message The critical message to display.
+ */
+ void raiseCriticalEvent(String message);
+}
diff --git a/src/burp/api/montoya/organizer/Organizer.java b/src/burp/api/montoya/organizer/Organizer.java
new file mode 100644
index 0000000..e9f9764
--- /dev/null
+++ b/src/burp/api/montoya/organizer/Organizer.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.organizer;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+/**
+ * Provides access to the functionality of the Organizer tool.
+ */
+public interface Organizer
+{
+ /**
+ * This method can be used to send an HTTP request to the Burp Organizer
+ * tool.
+ *
+ * @param request The full HTTP request.
+ */
+ void sendToOrganizer(HttpRequest request);
+
+ /**
+ * This method can be used to send an HTTP request and response to the Burp
+ * Organizer tool.
+ *
+ * @param requestResponse The full HTTP request and response.
+ */
+ void sendToOrganizer(HttpRequestResponse requestResponse);
+}
diff --git a/src/burp/api/montoya/persistence/PersistedList.java b/src/burp/api/montoya/persistence/PersistedList.java
new file mode 100644
index 0000000..c8044be
--- /dev/null
+++ b/src/burp/api/montoya/persistence/PersistedList.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.persistence;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * List that has been persisted in the project.
+ * The methods of this list operate on the underlying persisted data.
+ */
+public interface PersistedList extends List
+{
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link Boolean}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedBooleanList()
+ {
+ return FACTORY.persistedBooleanList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link Short}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedShortList()
+ {
+ return FACTORY.persistedShortList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link Integer}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedIntegerList()
+ {
+ return FACTORY.persistedIntegerList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link Long}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedLongList()
+ {
+ return FACTORY.persistedLongList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link String}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedStringList()
+ {
+ return FACTORY.persistedStringList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link ByteArray}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedByteArrayList()
+ {
+ return FACTORY.persistedByteArrayList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link HttpRequest}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedHttpRequestList()
+ {
+ return FACTORY.persistedHttpRequestList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link HttpResponse}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedHttpResponseList()
+ {
+ return FACTORY.persistedHttpResponseList();
+ }
+
+ /**
+ * Create a new instance of {@link PersistedList} that contains instances of {@link HttpRequestResponse}.
+ *
+ * @return A new {@link PersistedList} instance.
+ */
+ static PersistedList persistedHttpRequestResponseList()
+ {
+ return FACTORY.persistedHttpRequestResponseList();
+ }
+}
diff --git a/src/burp/api/montoya/persistence/PersistedObject.java b/src/burp/api/montoya/persistence/PersistedObject.java
new file mode 100644
index 0000000..9c9a3fc
--- /dev/null
+++ b/src/burp/api/montoya/persistence/PersistedObject.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.persistence;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.Set;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * [Professional only] Enables data to be stored and accessed from the Burp project.
+ * Supports HTTP requests, HTTP responses, byte arrays, primitives, lists of all these, and object hierarchies.
+ */
+public interface PersistedObject
+{
+ /**
+ * {@link PersistedObject} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedObject getChildObject(String key);
+
+ /**
+ * Associates the specified {@link PersistedObject} with the specified key in this map.
+ * If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified child object is to be associated.
+ * @param childObject The {@link PersistedObject} to be associated with the specified key.
+ */
+ void setChildObject(String key, PersistedObject childObject);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedObject}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteChildObject(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link PersistedObject} objects.
+ *
+ * @return Set of keys.
+ */
+ Set childObjectKeys();
+
+ /**
+ * {@link String} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ String getString(String key);
+
+ /**
+ * Associates the specified {@link String} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setString(String key, String value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link String}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteString(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link String} values.
+ *
+ * @return Set of keys.
+ */
+ Set stringKeys();
+
+ /**
+ * {@link Boolean} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Boolean getBoolean(String key);
+
+ /**
+ * Associates the specified {@code boolean} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setBoolean(String key, boolean value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link Boolean}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteBoolean(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Boolean} values.
+ *
+ * @return Set of keys.
+ */
+ Set booleanKeys();
+
+ /**
+ * {@link Byte} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Byte getByte(String key);
+
+ /**
+ * Associates the specified {@code byte} with the specified key in this map
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setByte(String key, byte value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link Byte}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteByte(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Byte} values.
+ *
+ * @return Set of keys.
+ */
+ Set byteKeys();
+
+ /**
+ * {@link Short} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Short getShort(String key);
+
+ /**
+ * Associates the specified short with the specified key in this map
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value currently mapped to the specified key is removed.
+ */
+ void setShort(String key, short value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Short}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteShort(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Short} values.
+ *
+ * @return Set of keys.
+ */
+ Set shortKeys();
+
+ /**
+ * {@link Integer} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Integer getInteger(String key);
+
+ /**
+ * Associates the specified {@code int} with the specified key in this map
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setInteger(String key, int value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Integer}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteInteger(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Integer} values.
+ *
+ * @return Set of keys.
+ */
+ Set integerKeys();
+
+ /**
+ * {@link Long} associated with the specified key,
+ * or {@code null}} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Long getLong(String key);
+
+ /**
+ * Associates the specified {@code long} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setLong(String key, long value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Long}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteLong(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Long} values.
+ *
+ * @return Set of keys.
+ */
+ Set longKeys();
+
+ /**
+ * {@link ByteArray} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ ByteArray getByteArray(String key);
+
+ /**
+ * Associates the specified {@code ByteArray} with the specified key in this map.
+ * If the map previously contained a mapping for the key, the old value is replaced
+ * by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setByteArray(String key, ByteArray value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link ByteArray}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteByteArray(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link ByteArray} values.
+ *
+ * @return Set of keys.
+ */
+ Set byteArrayKeys();
+
+ /**
+ * {@link HttpRequest} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ HttpRequest getHttpRequest(String key);
+
+ /**
+ * Associates the specified {@link HttpRequest} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setHttpRequest(String key, HttpRequest value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link HttpRequest}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpRequest(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpRequest} values.
+ *
+ * @return Set of keys.
+ */
+ Set httpRequestKeys();
+
+ /**
+ * {@link PersistedList} of {@link HttpRequest} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getHttpRequestList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link HttpRequest} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * The methods of this list operate on the underlying persisted data.
+ */
+ void setHttpRequestList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link HttpRequest}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpRequestList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpRequest} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set httpRequestListKeys();
+
+ /**
+ * {@link HttpResponse} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ HttpResponse getHttpResponse(String key);
+
+ /**
+ * Associates the specified {@link HttpResponse} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setHttpResponse(String key, HttpResponse value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link HttpResponse}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpResponse(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpResponse} values.
+ *
+ * @return Set of keys.
+ */
+ Set httpResponseKeys();
+
+ /**
+ * {@link PersistedList} of {@link HttpResponse} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getHttpResponseList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link HttpResponse} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * The methods of this list operate on the underlying persisted data.
+ */
+ void setHttpResponseList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link HttpResponse}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpResponseList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpResponse} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set httpResponseListKeys();
+
+ /**
+ * {@link HttpRequestResponse} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ HttpRequestResponse getHttpRequestResponse(String key);
+
+ /**
+ * Associates the specified {@link HttpRequestResponse} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setHttpRequestResponse(String key, HttpRequestResponse value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link HttpRequestResponse}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpRequestResponse(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpRequestResponse} values.
+ *
+ * @return Set of keys.
+ */
+ Set httpRequestResponseKeys();
+
+ /**
+ * {@link PersistedList} of {@link HttpRequestResponse} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getHttpRequestResponseList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link HttpRequestResponse} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * The methods of this list operate on the underlying persisted data.
+ */
+ void setHttpRequestResponseList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link HttpRequestResponse}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteHttpRequestResponseList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link HttpRequestResponse} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set httpRequestResponseListKeys();
+
+ /**
+ * {@link PersistedList} of {@link Boolean} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getBooleanList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link Boolean} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setBooleanList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link Boolean}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteBooleanList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Boolean} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set booleanListKeys();
+
+ /**
+ * {@link PersistedList} of {@link Short} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getShortList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link Short} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setShortList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link Short}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteShortList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Short} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set shortListKeys();
+
+ /**
+ * {@link PersistedList} of {@link Integer} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getIntegerList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link Integer} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setIntegerList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link Integer}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteIntegerList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Integer} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set integerListKeys();
+
+ /**
+ * {@link PersistedList} of {@link Long} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getLongList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link Long} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setLongList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link Long}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteLongList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Long} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set longListKeys();
+
+ /**
+ * {@link PersistedList} of {@link String} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value to which the specified key is mapped, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getStringList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@link String} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setStringList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link String}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteStringList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link String} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set stringListKeys();
+
+ /**
+ * {@link PersistedList} of {@link ByteArray} associated with the specified key,
+ * or {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ PersistedList getByteArrayList(String key);
+
+ /**
+ * Associates the specified {@link PersistedList} of {@code ByteArray} with the specified key in this map.
+ * If the map previously contained a mapping for the key,
+ * the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * The methods of this list operate on the underlying persisted data.
+ */
+ void setByteArrayList(String key, PersistedList value);
+
+ /**
+ * Removes the mapping of the specified key to the {@link PersistedList} of {@link ByteArray}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteByteArrayList(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link ByteArray} Lists.
+ *
+ * @return Set of keys.
+ */
+ Set byteArrayListKeys();
+
+ /**
+ * Create a new instance of {@link PersistedObject}.
+ *
+ * @return A new {@link PersistedObject} instance.
+ */
+ static PersistedObject persistedObject()
+ {
+ return FACTORY.persistedObject();
+ }
+}
diff --git a/src/burp/api/montoya/persistence/Persistence.java b/src/burp/api/montoya/persistence/Persistence.java
new file mode 100644
index 0000000..558522e
--- /dev/null
+++ b/src/burp/api/montoya/persistence/Persistence.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.persistence;
+
+/**
+ * Provides access to the persistence functionality.
+ */
+public interface Persistence
+{
+ /**
+ * Access data storage functionality in the Burp project. When Burp is started without
+ * a project file, the data is stored in memory.
+ *
+ * @return An implementation of the {@link PersistedObject} interface
+ * that stores data in either the project file or memory.
+ */
+ PersistedObject extensionData();
+
+ /**
+ * Access Java preference store functionality
+ * in a way that survives reloads of the extension and of Burp Suite.
+ *
+ * @return An implementation of the {@link Preferences} interface
+ * that stores data in a persistent way.
+ */
+ Preferences preferences();
+}
diff --git a/src/burp/api/montoya/persistence/Preferences.java b/src/burp/api/montoya/persistence/Preferences.java
new file mode 100644
index 0000000..2dcd4c4
--- /dev/null
+++ b/src/burp/api/montoya/persistence/Preferences.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.persistence;
+
+import java.util.Set;
+
+/**
+ * Enables data to be stored and accessed from the Java preference store. Supports primitives.
+ */
+public interface Preferences
+{
+ /**
+ * {@link String} associated with the specified key.
+ * Returns {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ String getString(String key);
+
+ /**
+ * Associates the specified {@link String} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ */
+ void setString(String key, String value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link String}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteString(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link String} values.
+ *
+ * @return Set of keys.
+ */
+ Set stringKeys();
+
+ /**
+ * {@link Boolean} associated with the specified key.
+ * Returns {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Boolean getBoolean(String key);
+
+ /**
+ * Associates the specified {@code boolean} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setBoolean(String key, boolean value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Boolean}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteBoolean(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Boolean} values.
+ *
+ * @return Set of keys.
+ */
+ Set booleanKeys();
+
+ /**
+ * {@link Byte} associated with the specified key.
+ * Returns {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Byte getByte(String key);
+
+ /**
+ * Associates the specified {@code byte} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setByte(String key, byte value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Byte}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteByte(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Byte} values.
+ *
+ * @return Set of keys.
+ */
+ Set byteKeys();
+
+ /**
+ * {@link Short} associated with the specified key.
+ * Returns {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Short getShort(String key);
+
+ /**
+ * Associates the specified short with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setShort(String key, short value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Short}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteShort(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Short} values.
+ *
+ * @return Set of keys.
+ */
+ Set shortKeys();
+
+ /**
+ * {@link Integer} associated with the specified key.
+ * Returns {@code null} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Integer getInteger(String key);
+
+ /**
+ * Associates the specified {@code int} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value that is currently mapped to the specified key is removed.
+ */
+ void setInteger(String key, int value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Integer}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteInteger(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Integer} values.
+ *
+ * @return Set of keys.
+ */
+ Set integerKeys();
+
+ /**
+ * {@link Long} associated with the specified key,
+ * or {@code null}} if this map contains no mapping for the key.
+ *
+ * @param key The key whose associated value is to be returned.
+ *
+ * @return The value associated with the specified key, or
+ * {@code null} if this map contains no mapping for the key.
+ */
+ Long getLong(String key);
+
+ /**
+ * Associates the specified {@code long} with the specified key in this map.
+ * This is an optional operation. If the map previously contained a mapping for
+ * the key, the old value is replaced by the specified value.
+ *
+ * @param key The key with which the specified value is to be associated.
+ * @param value The value to be associated with the specified key.
+ * If this value is {@code null} then any value currently mapped to the specified key is removed.
+ */
+ void setLong(String key, long value);
+
+ /**
+ * Removes the mapping from the specified key to the {@link Long}.
+ *
+ * @param key The key whose mapping is to be deleted.
+ */
+ void deleteLong(String key);
+
+ /**
+ * Retrieve all keys currently mapped for {@link Long} values.
+ *
+ * @return Set of keys.
+ */
+ Set longKeys();
+}
diff --git a/src/burp/api/montoya/proxy/MessageReceivedAction.java b/src/burp/api/montoya/proxy/MessageReceivedAction.java
new file mode 100644
index 0000000..6930fb9
--- /dev/null
+++ b/src/burp/api/montoya/proxy/MessageReceivedAction.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+/**
+ * This enum represents the initial action to be taken when intercepting HTTP and WebSocket
+ * messages in the Proxy.
+ */
+public enum MessageReceivedAction
+{
+ /**
+ * Causes Burp Proxy to follow the current interception rules to determine
+ * the appropriate action to take for the message.
+ */
+ CONTINUE,
+
+ /**
+ * Causes Burp Proxy to present the message to the user for manual review
+ * or modification.
+ */
+ INTERCEPT,
+
+ /**
+ * Causes Burp Proxy to forward the message without presenting it to the
+ * user.
+ */
+ DO_NOT_INTERCEPT,
+
+ /**
+ * Causes Burp Proxy to drop the message.
+ */
+ DROP
+}
diff --git a/src/burp/api/montoya/proxy/MessageToBeSentAction.java b/src/burp/api/montoya/proxy/MessageToBeSentAction.java
new file mode 100644
index 0000000..16a8609
--- /dev/null
+++ b/src/burp/api/montoya/proxy/MessageToBeSentAction.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+/**
+ * This enum represents the final action to be taken when intercepting HTTP and WebSocket
+ * messages in the Proxy.
+ */
+public enum MessageToBeSentAction
+{
+ /**
+ * Causes Burp Proxy to forward the message.
+ */
+ CONTINUE,
+
+ /**
+ * Causes Burp Proxy to drop the message.
+ */
+ DROP
+}
diff --git a/src/burp/api/montoya/proxy/Proxy.java b/src/burp/api/montoya/proxy/Proxy.java
new file mode 100644
index 0000000..6823fc3
--- /dev/null
+++ b/src/burp/api/montoya/proxy/Proxy.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.proxy.http.ProxyRequestHandler;
+import burp.api.montoya.proxy.http.ProxyResponseHandler;
+import burp.api.montoya.proxy.websocket.ProxyWebSocketCreationHandler;
+
+import java.util.List;
+
+/**
+ * Provides access to the functionality of the Proxy tool.
+ */
+public interface Proxy
+{
+ /**
+ * This method enables the master interception for Burp Proxy.
+ */
+ void enableIntercept();
+
+ /**
+ * This method disables the master interception for Burp Proxy.
+ */
+ void disableIntercept();
+
+ /**
+ * This method returns details of all items in the Proxy HTTP history.
+ *
+ * @return The list of all the {@link ProxyHttpRequestResponse} items in the
+ * Proxy HTTP history.
+ */
+ List history();
+
+ /**
+ * This method returns details of items in the Proxy HTTP history based on
+ * the filter.
+ *
+ * @param filter An instance of {@link ProxyHistoryFilter} that can be used
+ * to filter the items in the Proxy history.
+ *
+ * @return The list of {@link ProxyHttpRequestResponse} items in the Proxy
+ * HTTP history that matched the filter.
+ */
+ List history(ProxyHistoryFilter filter);
+
+ /**
+ * This method returns details of all items in the Proxy WebSockets history.
+ *
+ * @return The list of all the {@link ProxyWebSocketMessage} items in the
+ * Proxy WebSockets history.
+ */
+ List webSocketHistory();
+
+ /**
+ * This method returns details of items in the Proxy WebSockets history based
+ * on the filter.
+ *
+ * @param filter An instance of {@link ProxyWebSocketHistoryFilter} that can be used
+ * to filter the items in the Proxy WebSockets history.
+ *
+ * @return The list of {@link ProxyWebSocketMessage} items in the Proxy WebSockets
+ * history that matched the filter.
+ */
+ List webSocketHistory(ProxyWebSocketHistoryFilter filter);
+
+ /**
+ * Register a handler which will be notified of
+ * requests being processed by the Proxy tool. Extensions can perform
+ * custom analysis or modification of these messages, and control in-UI
+ * message interception.
+ *
+ * @param handler An object created by the extension that implements the
+ * {@link ProxyRequestHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerRequestHandler(ProxyRequestHandler handler);
+
+ /**
+ * Register a handler which will be notified of
+ * responses being processed by the Proxy tool. Extensions can perform
+ * custom analysis or modification of these messages, and control in-UI
+ * message interception.
+ *
+ * @param handler An object created by the extension that implements the
+ * {@link ProxyResponseHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerResponseHandler(ProxyResponseHandler handler);
+
+ /**
+ * Register a handler which will be invoked whenever a WebSocket is being created by the Proxy tool.
+ *
+ * @param handler An object created by the extension that implements {@link ProxyWebSocketCreationHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerWebSocketCreationHandler(ProxyWebSocketCreationHandler handler);
+}
diff --git a/src/burp/api/montoya/proxy/ProxyHistoryFilter.java b/src/burp/api/montoya/proxy/ProxyHistoryFilter.java
new file mode 100644
index 0000000..28dcde3
--- /dev/null
+++ b/src/burp/api/montoya/proxy/ProxyHistoryFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Proxy#history(ProxyHistoryFilter)} to get a filtered list of items in
+ * the Proxy history.
+ */
+public interface ProxyHistoryFilter
+{
+ /**
+ * This method is invoked for every item in the Proxy history to determine
+ * whether it should be included in the filtered list of items.
+ *
+ * @param requestResponse A {@link ProxyHttpRequestResponse} object that
+ * extensions can use to determine whether the item should be included in
+ * the filtered list of items.
+ *
+ * @return Return {@code true} if the item should be included in the
+ * filtered list of items.
+ */
+ boolean matches(ProxyHttpRequestResponse requestResponse);
+}
diff --git a/src/burp/api/montoya/proxy/ProxyHttpRequestResponse.java b/src/burp/api/montoya/proxy/ProxyHttpRequestResponse.java
new file mode 100644
index 0000000..fd77ca0
--- /dev/null
+++ b/src/burp/api/montoya/proxy/ProxyHttpRequestResponse.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.handler.TimingData;
+import burp.api.montoya.http.message.MimeType;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.requests.MalformedRequestException;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.time.ZonedDateTime;
+import java.util.regex.Pattern;
+
+/**
+ * HTTP request and response intercepted by the Proxy.
+ */
+public interface ProxyHttpRequestResponse
+{
+ /**
+ * This method retrieves the HTTP request that was sent by Burp Proxy.
+ *
+ * @return The {@link HttpRequest} that was sent by Burp Proxy.
+ * @see ProxyHttpRequestResponse#finalRequest()
+ */
+ HttpRequest request();
+
+ /**
+ * This method retrieves the HTTP request that was sent by Burp Proxy.
+ *
+ * @return The {@link HttpRequest} that was sent by Burp Proxy.
+ */
+ HttpRequest finalRequest();
+
+ /**
+ * This method retrieves the HTTP response that was received by Burp Proxy.
+ *
+ * @return The {@link HttpResponse} that was received by Burp Proxy.
+ * @see ProxyHttpRequestResponse#originalResponse()
+ */
+ HttpResponse response();
+
+ /**
+ * This method retrieves the HTTP response that was received by Burp Proxy.
+ *
+ * @return The {@link HttpResponse} that was received by Burp Proxy.
+ */
+ HttpResponse originalResponse();
+
+ /**
+ * This method retrieves the annotations for the request/response pair.
+ *
+ * @return The {@link Annotations} for the request/response pair.
+ */
+ Annotations annotations();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ HttpService httpService();
+
+ /**
+ * URL for the issued final request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The URL in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Deprecated(forRemoval = true)
+ String url();
+
+ /**
+ * HTTP method for the issued final request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The HTTP method used in the request.
+ * @throws MalformedRequestException if request is malformed.
+ * @deprecated use {@link #finalRequest()} method instead.
+ */
+ @Deprecated(forRemoval = true)
+ String method();
+
+ /**
+ * Path and File for the issued final request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path and file in the request
+ * @throws MalformedRequestException if request is malformed.
+ * @deprecated use {@link #finalRequest()} path instead.
+ */
+ @Deprecated(forRemoval = true)
+ String path();
+
+ /**
+ * @return The hostname or IP address for the service.
+ * @deprecated use {@link #finalRequest()} httpService instead.
+ */
+ @Deprecated(forRemoval = true)
+ String host();
+
+ /**
+ * @return The port number for the service.
+ * @deprecated use {@link #finalRequest()} httpService instead.
+ */
+ @Deprecated(forRemoval = true)
+ int port();
+
+ /**
+ * @return True is a secure protocol is used for the connection, false otherwise.
+ * @deprecated use {@link #finalRequest()} httpService instead.
+ */
+ @Deprecated(forRemoval = true)
+ boolean secure();
+
+ /**
+ * @return The {@code String} representation of the service.
+ * @deprecated use {@link #finalRequest()} httpService instead.
+ */
+ @Deprecated(forRemoval = true)
+ String httpServiceString();
+
+ /**
+ * HTTP Version text parsed from the request line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ * @deprecated use {@link #finalRequest()} httpVersion instead.
+ */
+ @Deprecated(forRemoval = true)
+ String requestHttpVersion();
+
+ /**
+ * Body of the issued final request
+ *
+ * @return The body of a message as a {@code String}.
+ * @deprecated use {@link #finalRequest()} body instead.
+ */
+ @Deprecated(forRemoval = true)
+ String requestBody();
+
+ /**
+ * @return True if the request or response was edited
+ */
+ boolean edited();
+
+ /**
+ * Returns the date and time at which Burp Proxy received the request.
+ *
+ * @return The time at which Burp Proxy received the request.
+ */
+ ZonedDateTime time();
+
+ /**
+ * Returns the proxy listener port used for the request/response.
+ *
+ * @return the port number used by the proxy listener
+ */
+ int listenerPort();
+
+ /**
+ * Obtain the MIME type of the response or request, as determined by Burp Suite.
+ * If there is no response the mime type will be determined from the request url.
+ *
+ * @return The MIME type.
+ */
+ MimeType mimeType();
+
+ /**
+ * @return True if there is a response.
+ */
+ boolean hasResponse();
+
+ /**
+ * Searches the data in the HTTP request and response for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP request and response for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ boolean contains(Pattern pattern);
+
+ /**
+ * Retrieve the timing data associated with this request and response.
+ *
+ * @return The timing data.
+ */
+ TimingData timingData();
+}
diff --git a/src/burp/api/montoya/proxy/ProxyWebSocketHistoryFilter.java b/src/burp/api/montoya/proxy/ProxyWebSocketHistoryFilter.java
new file mode 100644
index 0000000..ab41943
--- /dev/null
+++ b/src/burp/api/montoya/proxy/ProxyWebSocketHistoryFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Proxy#webSocketHistory(ProxyWebSocketHistoryFilter)} to get a filtered list of items in
+ * the Proxy WebSockets history.
+ */
+public interface ProxyWebSocketHistoryFilter
+{
+ /**
+ * This method is invoked for every item in the Proxy WebSockets history to determine
+ * whether it should be included in the filtered list of items.
+ *
+ * @param message A {@link ProxyWebSocketMessage} object that
+ * extensions can use to determine whether the item should be included in
+ * the filtered list of items.
+ *
+ * @return Return {@code true} if the item should be included in the
+ * filtered list of items.
+ */
+ boolean matches(ProxyWebSocketMessage message);
+}
diff --git a/src/burp/api/montoya/proxy/ProxyWebSocketMessage.java b/src/burp/api/montoya/proxy/ProxyWebSocketMessage.java
new file mode 100644
index 0000000..b71d4d6
--- /dev/null
+++ b/src/burp/api/montoya/proxy/ProxyWebSocketMessage.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.ui.contextmenu.WebSocketMessage;
+import burp.api.montoya.websocket.Direction;
+
+import java.time.ZonedDateTime;
+import java.util.regex.Pattern;
+
+/**
+ * WebSocket message intercepted by the Proxy.
+ */
+public interface ProxyWebSocketMessage extends WebSocketMessage
+{
+ /**
+ * This method retrieves the annotations for the message.
+ *
+ * @return The {@link Annotations} for the message.
+ */
+ @Override
+ Annotations annotations();
+
+ /**
+ * @return The direction of the message.
+ */
+ @Override
+ Direction direction();
+
+ /**
+ * @return WebSocket payload.
+ */
+ @Override
+ ByteArray payload();
+
+ /**
+ * @return The {@link HttpRequest} used to create the WebSocket.
+ */
+ @Override
+ HttpRequest upgradeRequest();
+
+ /**
+ * @return The ID for the web socket connection that this message is linked to.
+ */
+ int webSocketId();
+
+ /**
+ * @return An instance of {@link ZonedDateTime} indicating when the message was sent.
+ */
+ ZonedDateTime time();
+
+ /**
+ * @return The payload after modification from tools and extensions. {@code null} if the message has not been edited.
+ */
+ ByteArray editedPayload();
+
+ /**
+ * Returns the proxy listener port used for the web socket message.
+ *
+ * @return the port number used by the proxy listener
+ */
+ int listenerPort();
+
+ /**
+ * Searches the data in the web socket message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the web socket message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ boolean contains(Pattern pattern);
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/proxy/http/InterceptedHttpMessage.java b/src/burp/api/montoya/proxy/http/InterceptedHttpMessage.java
new file mode 100644
index 0000000..57384ff
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/InterceptedHttpMessage.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import java.net.InetAddress;
+
+/**
+ * HTTP message intercepted by Burp Proxy.
+ */
+public interface InterceptedHttpMessage
+{
+ /**
+ * This method retrieves a unique ID for this request/response.
+ *
+ * @return An identifier that is unique to a single request/response pair.
+ * Extensions can use this to correlate details of requests and responses
+ * and perform processing on the response message accordingly.
+ */
+ int messageId();
+
+ /**
+ * This method retrieves the name of the Burp Proxy listener that is
+ * processing the intercepted message.
+ *
+ * @return The name of the Burp Proxy listener that is processing the
+ * intercepted message. The format is the same as that shown in the Proxy
+ * Listeners UI - for example, "127.0.0.1:8080".
+ */
+ String listenerInterface();
+
+ /**
+ * This method retrieves the IP address for the source of the intercepted
+ * message.
+ *
+ * @return The IP address for the source of the intercepted message.
+ */
+ InetAddress sourceIpAddress();
+
+ /**
+ * This method retrieves the IP address for the destination of the
+ * intercepted message.
+ *
+ * @return The IP address for the destination of the intercepted message.
+ */
+ InetAddress destinationIpAddress();
+}
diff --git a/src/burp/api/montoya/proxy/http/InterceptedRequest.java b/src/burp/api/montoya/proxy/http/InterceptedRequest.java
new file mode 100644
index 0000000..e842ecb
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/InterceptedRequest.java
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.message.ContentType;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.params.HttpParameter;
+import burp.api.montoya.http.message.params.HttpParameterType;
+import burp.api.montoya.http.message.params.ParsedHttpParameter;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.requests.HttpTransformation;
+import burp.api.montoya.http.message.requests.MalformedRequestException;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * HTTP request intercepted by Burp Proxy.
+ */
+public interface InterceptedRequest extends InterceptedHttpMessage, HttpRequest
+{
+ /**
+ * @return Annotations for request/response.
+ */
+ Annotations annotations();
+
+ /**
+ * @return True if the request is in-scope.
+ */
+ @Override
+ boolean isInScope();
+
+ /**
+ * HTTP service for the request.
+ *
+ * @return An {@link HttpService} object containing details of the HTTP service.
+ */
+ @Override
+ HttpService httpService();
+
+ /**
+ * URL for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The URL in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String url();
+
+ /**
+ * HTTP method for the request.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return The HTTP method used in the request.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String method();
+
+ /**
+ * Request path including the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path and query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String path();
+
+ /**
+ * Request path excluding the query parameters.
+ * If the request is malformed, then a {@link MalformedRequestException} is thrown.
+ *
+ * @return the path excluding query parameters.
+ * @throws MalformedRequestException if request is malformed.
+ */
+ @Override
+ String pathWithoutQuery();
+
+ /**
+ * HTTP Version text parsed from the request line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * @param header The header to check if it exists in the request.
+ *
+ * @return True if the header exists in the request.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * @return True if the request has parameters.
+ */
+ @Override
+ boolean hasParameters();
+
+ /**
+ * @return True if the request has parameters of type {@link HttpParameterType}
+ */
+ @Override
+ boolean hasParameters(HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return An instance of {@link ParsedHttpParameter} that matches the type and name specified. {@code null} if not found.
+ */
+ @Override
+ ParsedHttpParameter parameter(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to get the value from.
+ * @param type The type of the parameter to get the value from.
+ *
+ * @return The value of the parameter that matches the name and type specified. {@code null} if not found.
+ */
+ @Override
+ String parameterValue(String name, HttpParameterType type);
+
+ /**
+ * @param name The name of the parameter to find.
+ * @param type The type of the parameter to find.
+ *
+ * @return {@code true} if a parameter exists that matches the name and type specified. {@code false} if not found.
+ */
+ @Override
+ boolean hasParameter(String name, HttpParameterType type);
+
+ /**
+ * @param parameter An instance of {@link HttpParameter} to match to an existing parameter.
+ *
+ * @return {@code true} if a parameter exists that matches the data within the provided {@link HttpParameter}. {@code false} if not found.
+ */
+ @Override
+ boolean hasParameter(HttpParameter parameter);
+
+ /**
+ * @return The detected content type of the request.
+ */
+ @Override
+ ContentType contentType();
+
+ /**
+ * @return The parameters contained in the request.
+ */
+ @Override
+ List parameters();
+
+ /**
+ * @param type The type of parameter that will be returned in the filtered list.
+ *
+ * @return A filtered list of {@link ParsedHttpParameter} containing only the provided type.
+ */
+ @Override
+ List parameters(HttpParameterType type);
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpRequest} in temporary file.
+ * This method is used to save the {@code HttpRequest} object to a temporary file,
+ * so that it is no longer held in memory. Extensions can use this method to convert
+ * {@code HttpRequest} objects into a form suitable for long-term usage.
+ *
+ * @return A new {@code HttpRequest} instance stored in temporary file.
+ */
+ HttpRequest copyToTempFile();
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new service.
+ *
+ * @param service An {@link HttpService} reference to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withService(HttpService service);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new path.
+ *
+ * @param path The path to use.
+ *
+ * @return A new {@code HttpRequest} instance with updated path.
+ */
+ @Override
+ HttpRequest withPath(String path);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the new method.
+ *
+ * @param method the method to use
+ *
+ * @return a new {@code HttpRequest} instance with updated method.
+ */
+ @Override
+ HttpRequest withMethod(String method);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param header HTTP header to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ @Override
+ HttpRequest withHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added or updated header.
+ * If the header exists in the request, it is updated.
+ * If the header doesn't exist in the request, it is added.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return A new {@code HttpRequest} with the added or updated header.
+ */
+ @Override
+ HttpRequest withHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the HTTP parameter.
+ * If the parameter exists in the request, it is updated.
+ * If the parameter doesn't exist in the request, it is added.
+ *
+ * @param parameters HTTP parameter to add or update.
+ *
+ * @return A new {@code HttpRequest} with the added or updated parameter.
+ */
+ @Override
+ HttpRequest withParameter(HttpParameter parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withAddedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added HTTP parameters.
+ *
+ * @param parameters HTTP parameters to add.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withAddedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withRemovedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the removed HTTP parameters.
+ *
+ * @param parameters HTTP parameters to remove.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withRemovedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withUpdatedParameters(List extends HttpParameter> parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated HTTP parameters.
+ *
+ * @param parameters HTTP parameters to update.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withUpdatedParameters(HttpParameter... parameters);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the transformation applied.
+ *
+ * @param transformation Transformation to apply.
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withTransformationApplied(HttpTransformation transformation);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the request
+ *
+ * @return A new {@code HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ @Override
+ HttpRequest withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the HTTP request.
+ *
+ * @return The updated HTTP request with the added header.
+ */
+ @Override
+ HttpRequest withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated request containing the updated header.
+ */
+ @Override
+ HttpRequest withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated request containing the updated header.
+ */
+ @Override
+ HttpRequest withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param name The name of the HTTP header to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ @Override
+ HttpRequest withRemovedHeader(String name);
+
+ /**
+ * Removes an existing HTTP header from the current request.
+ *
+ * @param header The {@link HttpHeader} to remove from the request.
+ *
+ * @return The updated request containing the removed header.
+ */
+ @Override
+ HttpRequest withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@link HttpRequest} instance.
+ */
+ @Override
+ HttpRequest withMarkers(Marker... markers);
+
+ /**
+ * Create a copy of the {@code HttpRequest} with added default headers.
+ *
+ * @return a new {@link HttpRequest} with added default headers
+ */
+ @Override
+ HttpRequest withDefaultHeaders();
+
+ /**
+ * This method retrieves a unique ID for this request/response.
+ *
+ * @return An identifier that is unique to a single request/response pair.
+ * Extensions can use this to correlate details of requests and responses
+ * and perform processing on the response message accordingly.
+ */
+ @Override
+ int messageId();
+
+ /**
+ * This method retrieves the name of the Burp Proxy listener that is
+ * processing the intercepted message.
+ *
+ * @return The name of the Burp Proxy listener that is processing the
+ * intercepted message. The format is the same as that shown in the Proxy
+ * Listeners UI - for example, "127.0.0.1:8080".
+ */
+ @Override
+ String listenerInterface();
+
+ /**
+ * This method retrieves the IP address for the source of the intercepted
+ * message.
+ *
+ * @return The IP address for the source of the intercepted message.
+ */
+ @Override
+ InetAddress sourceIpAddress();
+
+ /**
+ * This method retrieves the IP address for the destination of the
+ * intercepted message.
+ *
+ * @return The IP address for the destination of the intercepted message.
+ */
+ @Override
+ InetAddress destinationIpAddress();
+}
diff --git a/src/burp/api/montoya/proxy/http/InterceptedResponse.java b/src/burp/api/montoya/proxy/http/InterceptedResponse.java
new file mode 100644
index 0000000..d1d80d2
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/InterceptedResponse.java
@@ -0,0 +1,459 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Marker;
+import burp.api.montoya.http.message.Cookie;
+import burp.api.montoya.http.message.HttpHeader;
+import burp.api.montoya.http.message.MimeType;
+import burp.api.montoya.http.message.StatusCodeClass;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.http.message.responses.analysis.Attribute;
+import burp.api.montoya.http.message.responses.analysis.AttributeType;
+import burp.api.montoya.http.message.responses.analysis.KeywordCount;
+
+import java.net.InetAddress;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * HTTP response intercepted by Burp Proxy.
+ */
+public interface InterceptedResponse extends InterceptedHttpMessage, HttpResponse
+{
+ /**
+ * @return initiatingRequest The HTTP request that was sent.
+ * @see InterceptedResponse#initiatingRequest()
+ */
+ HttpRequest request();
+
+ /**
+ * @return initiatingRequest The HTTP request that was sent.
+ */
+ HttpRequest initiatingRequest();
+
+ /**
+ * @return Annotations for request/response.
+ */
+ Annotations annotations();
+
+ /**
+ * Obtain the HTTP status code contained in the response.
+ *
+ * @return HTTP status code.
+ */
+ @Override
+ short statusCode();
+
+ /**
+ * Obtain the HTTP reason phrase contained in the response for HTTP 1 messages.
+ * HTTP 2 messages will return a mapped phrase based on the status code.
+ *
+ * @return HTTP Reason phrase.
+ */
+ @Override
+ String reasonPhrase();
+
+ /**
+ * Test whether the status code is in the specified class.
+ *
+ * @param statusCodeClass The class of status code to test.
+ *
+ * @return True if the status code is in the class.
+ */
+ @Override
+ boolean isStatusCodeClass(StatusCodeClass statusCodeClass);
+
+ /**
+ * Return the HTTP Version text parsed from the response line for HTTP 1 messages.
+ * HTTP 2 messages will return "HTTP/2"
+ *
+ * @return Version string
+ */
+ @Override
+ String httpVersion();
+
+ /**
+ * HTTP headers contained in the message.
+ *
+ * @return A list of HTTP headers.
+ */
+ @Override
+ List headers();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ boolean hasHeader(HttpHeader header);
+
+ /**
+ * @param name The name of the header to query within the request.
+ *
+ * @return True if a header exists in the request with the supplied name.
+ */
+ @Override
+ boolean hasHeader(String name);
+
+ /**
+ * @param name The name of the header to check.
+ * @param value The value of the header to check.
+ *
+ * @return True if a header exists in the request that matches the name and value supplied.
+ */
+ @Override
+ boolean hasHeader(String name, String value);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return An instance of {@link HttpHeader} that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ HttpHeader header(String name);
+
+ /**
+ * @param name The name of the header to retrieve.
+ *
+ * @return The {@code String} value of the header that matches the name supplied, {@code null} if no match found.
+ */
+ @Override
+ String headerValue(String name);
+
+ /**
+ * Body of a message as a byte array.
+ *
+ * @return The body of a message as a byte array.
+ */
+ @Override
+ ByteArray body();
+
+ /**
+ * Body of a message as a {@code String}.
+ *
+ * @return The body of a message as a {@code String}.
+ */
+ @Override
+ String bodyToString();
+
+ /**
+ * Offset within the message where the message body begins.
+ *
+ * @return The message body offset.
+ */
+ @Override
+ int bodyOffset();
+
+ /**
+ * Markers for the message.
+ *
+ * @return A list of markers.
+ */
+ @Override
+ List markers();
+
+ /**
+ * Obtain details of the HTTP cookies set in the response.
+ *
+ * @return A list of {@link Cookie} objects representing the cookies set in the response, if any.
+ */
+ @Override
+ List cookies();
+
+ /**
+ * @param name The name of the cookie to find.
+ *
+ * @return An instance of {@link Cookie} that matches the name provided. {@code null} if not found.
+ */
+ @Override
+ Cookie cookie(String name);
+
+ /**
+ * @param name The name of the cookie to retrieve the value from.
+ *
+ * @return The value of the cookie that matches the name provided. {@code null} if not found.
+ */
+ @Override
+ String cookieValue(String name);
+
+ /**
+ * @param name The name of the cookie to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the name provided. {@code false} if not.
+ */
+ @Override
+ boolean hasCookie(String name);
+
+ /**
+ * @param cookie An instance of {@link Cookie} to check if it exists in the response.
+ *
+ * @return {@code true} If a cookie exists within the response that matches the {@link Cookie} provided. {@code false} if not.
+ */
+ @Override
+ boolean hasCookie(Cookie cookie);
+
+ /**
+ * Obtain the MIME type of the response, as determined by Burp Suite.
+ *
+ * @return The MIME type.
+ */
+ @Override
+ MimeType mimeType();
+
+ /**
+ * Obtain the MIME type of the response, as stated in the HTTP headers.
+ *
+ * @return The stated MIME type.
+ */
+ @Override
+ MimeType statedMimeType();
+
+ /**
+ * Obtain the MIME type of the response, as inferred from the contents of the HTTP message body.
+ *
+ * @return The inferred MIME type.
+ */
+ @Override
+ MimeType inferredMimeType();
+
+ /**
+ * Retrieve the number of types given keywords appear in the response.
+ *
+ * @param keywords Keywords to count.
+ *
+ * @return List of keyword counts in the order they were provided.
+ */
+ @Override
+ List keywordCounts(String... keywords);
+
+ /**
+ * Retrieve the values of response attributes.
+ *
+ * @param types Response attributes to retrieve values for.
+ *
+ * @return List of {@link Attribute} objects.
+ */
+ @Override
+ List attributes(AttributeType... types);
+
+ /**
+ * Searches the data in the HTTP message for the specified search term.
+ *
+ * @param searchTerm The value to be searched for.
+ * @param caseSensitive Flags whether the search is case-sensitive.
+ *
+ * @return True if the search term is found.
+ */
+ @Override
+ boolean contains(String searchTerm, boolean caseSensitive);
+
+ /**
+ * Searches the data in the HTTP message for the specified regular expression.
+ *
+ * @param pattern The regular expression to be searched for.
+ *
+ * @return True if the pattern is matched.
+ */
+ @Override
+ boolean contains(Pattern pattern);
+
+ /**
+ * Message as a byte array.
+ *
+ * @return The message as a byte array.
+ */
+ @Override
+ ByteArray toByteArray();
+
+ /**
+ * Message as a {@code String}.
+ *
+ * @return The message as a {@code String}.
+ */
+ @Override
+ String toString();
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the provided status code.
+ *
+ * @param statusCode the new status code for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withStatusCode(short statusCode);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new reason phrase.
+ *
+ * @param reasonPhrase the new reason phrase for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withReasonPhrase(String reasonPhrase);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the new http version.
+ *
+ * @param httpVersion the new http version for response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withHttpVersion(String httpVersion);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withBody(String body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated body.
+ * Updates Content-Length header.
+ *
+ * @param body the new body for the response
+ *
+ * @return A new {@code HttpResponse} instance.
+ */
+ @Override
+ HttpResponse withBody(ByteArray body);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param header The {@link HttpHeader} to add to the response.
+ *
+ * @return The updated response containing the added header.
+ */
+ @Override
+ HttpResponse withAddedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added header.
+ *
+ * @param name The name of the header.
+ * @param value The value of the header.
+ *
+ * @return The updated response containing the added header.
+ */
+ @Override
+ HttpResponse withAddedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param header The {@link HttpHeader} to update containing the new value.
+ *
+ * @return The updated response containing the updated header.
+ */
+ @Override
+ HttpResponse withUpdatedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the updated header.
+ *
+ * @param name The name of the header to update the value of.
+ * @param value The new value of the specified HTTP header.
+ *
+ * @return The updated response containing the updated header.
+ */
+ @Override
+ HttpResponse withUpdatedHeader(String name, String value);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param header The {@link HttpHeader} to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ @Override
+ HttpResponse withRemovedHeader(HttpHeader header);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the removed header.
+ *
+ * @param name The name of the HTTP header to remove from the response.
+ *
+ * @return The updated response containing the removed header.
+ */
+ @Override
+ HttpResponse withRemovedHeader(String name);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ @Override
+ HttpResponse withMarkers(List markers);
+
+ /**
+ * Create a copy of the {@code HttpResponse} with the added markers.
+ *
+ * @param markers Request markers to add.
+ *
+ * @return A new {@code MarkedHttpRequestResponse} instance.
+ */
+ @Override
+ HttpResponse withMarkers(Marker... markers);
+
+ /**
+ * This method retrieves a unique ID for this request/response.
+ *
+ * @return An identifier that is unique to a single request/response pair.
+ * Extensions can use this to correlate details of requests and responses
+ * and perform processing on the response message accordingly.
+ */
+ @Override
+ int messageId();
+
+ /**
+ * This method retrieves the name of the Burp Proxy listener that is
+ * processing the intercepted message.
+ *
+ * @return The name of the Burp Proxy listener that is processing the
+ * intercepted message. The format is the same as that shown in the Proxy
+ * Listeners UI - for example, "127.0.0.1:8080".
+ */
+ @Override
+ String listenerInterface();
+
+ /**
+ * This method retrieves the IP address for the source of the intercepted
+ * message.
+ *
+ * @return The IP address for the source of the intercepted message.
+ */
+ @Override
+ InetAddress sourceIpAddress();
+
+ /**
+ * This method retrieves the IP address for the destination of the
+ * intercepted message.
+ *
+ * @return The IP address for the destination of the intercepted message.
+ */
+ @Override
+ InetAddress destinationIpAddress();
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyRequestHandler.java b/src/burp/api/montoya/proxy/http/ProxyRequestHandler.java
new file mode 100644
index 0000000..84b4eb6
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyRequestHandler.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.proxy.Proxy;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Proxy#registerRequestHandler(ProxyRequestHandler)} to register a
+ * Proxy request handler. The handler will be notified of requests being
+ * processed by the Proxy tool. Extensions can perform custom analysis or
+ * modification of these messages, and control in-UI message interception.
+ */
+public interface ProxyRequestHandler
+{
+ /**
+ * This method is invoked before an HTTP request is received by the Proxy.
+ * Can modify the request.
+ * Can modify the annotations.
+ * Can control whether the request should be intercepted and displayed to the user for manual review or modification.
+ * Can drop the request.
+ *
+ * @param interceptedRequest An {@link InterceptedRequest} object that extensions can use to query and update details of the request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} containing the required action, annotations and HTTP request to be passed through the proxy.
+ */
+ ProxyRequestReceivedAction handleRequestReceived(InterceptedRequest interceptedRequest);
+
+ /**
+ * This method is invoked after an HTTP request has been processed by the Proxy before it is sent.
+ * Can modify the request.
+ * Can modify the annotations.
+ * Can control whether the request is sent or dropped.
+ *
+ * @param interceptedRequest An {@link InterceptedRequest} object that extensions can use to query and update details of the intercepted request.
+ *
+ * @return The {@link ProxyRequestToBeSentAction} containing the required action, annotations and HTTP request to be sent from the proxy.
+ */
+ ProxyRequestToBeSentAction handleRequestToBeSent(InterceptedRequest interceptedRequest);
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyRequestReceivedAction.java b/src/burp/api/montoya/proxy/http/ProxyRequestReceivedAction.java
new file mode 100644
index 0000000..66f4f8c
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyRequestReceivedAction.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.proxy.MessageReceivedAction;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a result from
+ * {@link ProxyRequestHandler#handleRequestReceived(InterceptedRequest)}.
+ */
+public interface ProxyRequestReceivedAction
+{
+ /**
+ * This method retrieves the current initial intercept action.
+ *
+ * @return The {@link MessageReceivedAction}.
+ */
+ MessageReceivedAction action();
+
+ /**
+ * This method retrieves the current HTTP request to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link HttpRequest} to forward after any modifications by
+ * the extension.
+ */
+ HttpRequest request();
+
+ /**
+ * This method retrieves the annotations for the current request after any
+ * modifications by the extension.
+ *
+ * @return The {@link Annotations} for the intercepted HTTP request.
+ */
+ Annotations annotations();
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the request.
+ * Annotations are not modified.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that allows user rules to be
+ * followed.
+ */
+ static ProxyRequestReceivedAction continueWith(HttpRequest request)
+ {
+ return FACTORY.requestInitialInterceptResultFollowUserRules(request);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the request.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to follow the current interception rules to determine the appropriate
+ * action to take for the request.
+ */
+ static ProxyRequestReceivedAction continueWith(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.requestInitialInterceptResultFollowUserRules(request, annotations);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * present the request to the user for manual review or modification.
+ * Annotations are not modified.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to present the request to the user for manual review or modification.
+ */
+ static ProxyRequestReceivedAction intercept(HttpRequest request)
+ {
+ return FACTORY.requestInitialInterceptResultIntercept(request);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * present the request to the user for manual review or modification.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to present the request to the user for manual review or modification.
+ */
+ static ProxyRequestReceivedAction intercept(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.requestInitialInterceptResultIntercept(request, annotations);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the request without presenting it to the user.
+ * Annotations are not modified.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to forward the request without presenting it to the user.
+ */
+ static ProxyRequestReceivedAction doNotIntercept(HttpRequest request)
+ {
+ return FACTORY.requestInitialInterceptResultDoNotIntercept(request);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the request without presenting it to the user.
+ *
+ * @param request The {@link HttpRequest} received after any modifications
+ * by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to forward the request without presenting it to the user.
+ */
+ static ProxyRequestReceivedAction doNotIntercept(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.requestInitialInterceptResultDoNotIntercept(request, annotations);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * drop the request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} that causes Burp Proxy
+ * to drop the request.
+ */
+ static ProxyRequestReceivedAction drop()
+ {
+ return FACTORY.requestInitialInterceptResultDrop();
+ }
+
+ /**
+ * This method can be used to create a default implementation of an initial
+ * intercept result for an HTTP request.
+ *
+ * @param request The {@link HttpRequest} received after any modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted HTTP request. {@code null} value will leave the annotations unmodified.
+ * @param action The {@link MessageReceivedAction} for the HTTP request.
+ *
+ * @return The {@link ProxyRequestReceivedAction} including the HTTP
+ * request, annotations and initial intercept action.
+ */
+ static ProxyRequestReceivedAction proxyRequestReceivedAction(HttpRequest request, Annotations annotations, MessageReceivedAction action)
+ {
+ return FACTORY.proxyRequestReceivedAction(request, annotations, action);
+ }
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyRequestToBeSentAction.java b/src/burp/api/montoya/proxy/http/ProxyRequestToBeSentAction.java
new file mode 100644
index 0000000..682e272
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyRequestToBeSentAction.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.proxy.MessageToBeSentAction;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a result from
+ * {@link ProxyRequestHandler#handleRequestToBeSent(InterceptedRequest)}.
+ */
+public interface ProxyRequestToBeSentAction
+{
+ /**
+ * This method retrieves the current final intercept action.
+ *
+ * @return The {@link MessageToBeSentAction}.
+ */
+ MessageToBeSentAction action();
+
+ /**
+ * This method retrieves the current HTTP request to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link HttpRequest} to forward after any modifications by
+ * the extension.
+ */
+ HttpRequest request();
+
+ /**
+ * This method retrieves the annotations for the current request after any
+ * modifications by the extension.
+ *
+ * @return The {@link Annotations} for the intercepted HTTP request.
+ */
+ Annotations annotations();
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the request.
+ * Annotations are not modified.
+ *
+ * @param request The {@link HttpRequest} to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link ProxyRequestToBeSentAction} that causes Burp Proxy
+ * to forward the request.
+ */
+ static ProxyRequestToBeSentAction continueWith(HttpRequest request)
+ {
+ return FACTORY.requestFinalInterceptResultContinueWith(request);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the request.
+ *
+ * @param request The {@link HttpRequest} to forward after any
+ * modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP request.
+ *
+ * @return The {@link ProxyRequestToBeSentAction} that causes Burp Proxy
+ * to forward the request.
+ */
+ static ProxyRequestToBeSentAction continueWith(HttpRequest request, Annotations annotations)
+ {
+ return FACTORY.requestFinalInterceptResultContinueWith(request, annotations);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * drop the request.
+ *
+ * @return The {@link ProxyRequestToBeSentAction} that causes Burp Proxy
+ * to drop the request.
+ */
+ static ProxyRequestToBeSentAction drop()
+ {
+ return FACTORY.requestFinalInterceptResultDrop();
+ }
+
+ /**
+ * This method can be used to create a default implementation of a final
+ * intercept result for an HTTP request.
+ *
+ * @param request The {@link HttpRequest} to forward after any modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted HTTP request. {@code null} value will leave the annotations unmodified.
+ * @param action The {@link MessageToBeSentAction} for the HTTP request.
+ *
+ * @return The {@link ProxyRequestToBeSentAction} including the HTTP
+ * request, annotations and final intercept action.
+ */
+ static ProxyRequestToBeSentAction proxyRequestToBeSentAction(HttpRequest request, Annotations annotations, MessageToBeSentAction action)
+ {
+ return FACTORY.proxyRequestToBeSentAction(request, annotations, action);
+ }
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyResponseHandler.java b/src/burp/api/montoya/proxy/http/ProxyResponseHandler.java
new file mode 100644
index 0000000..be26d9d
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyResponseHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.proxy.Proxy;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Proxy#registerResponseHandler(ProxyResponseHandler)} to register a
+ * Proxy response handler. The handler will be notified of responses being
+ * processed by the Proxy tool. Extensions can perform custom analysis or
+ * modification of these responses, and control in-UI message interception.
+ */
+public interface ProxyResponseHandler
+{
+ /**
+ * This method is invoked when an HTTP response is received in the Proxy.
+ *
+ * @param interceptedResponse An {@link InterceptedResponse} object
+ * that extensions can use to query and update details of the response, and
+ * control whether the response should be intercepted and displayed to the
+ * user for manual review or modification.
+ *
+ * @return The {@link ProxyResponseReceivedAction} containing the required action, HTTP response and annotations to be passed through.
+ */
+ ProxyResponseReceivedAction handleResponseReceived(InterceptedResponse interceptedResponse);
+
+ /**
+ * This method is invoked when an HTTP response has been processed by the
+ * Proxy before it is returned to the client.
+ *
+ * @param interceptedResponse An {@link InterceptedResponse} object
+ * that extensions can use to query and update details of the response.
+ *
+ * @return The {@link ProxyResponseToBeSentAction} containing the required action, HTTP response and annotations to be passed through.
+ */
+ ProxyResponseToBeSentAction handleResponseToBeSent(InterceptedResponse interceptedResponse);
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyResponseReceivedAction.java b/src/burp/api/montoya/proxy/http/ProxyResponseReceivedAction.java
new file mode 100644
index 0000000..e0c9bac
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyResponseReceivedAction.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.proxy.MessageReceivedAction;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a result from
+ * {@link ProxyResponseHandler#handleResponseReceived(InterceptedResponse)}.
+ */
+public interface ProxyResponseReceivedAction
+{
+ /**
+ * This method retrieves the current initial intercept action.
+ *
+ * @return The {@link MessageReceivedAction}.
+ */
+ MessageReceivedAction action();
+
+ /**
+ * This method retrieves the current HTTP response to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link HttpResponse} to forward after any modifications by
+ * the extension.
+ */
+ HttpResponse response();
+
+ /**
+ * This method retrieves the annotations for the current response after any
+ * modifications by the extension.
+ *
+ * @return The {@link Annotations} for the intercepted HTTP response.
+ */
+ Annotations annotations();
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the response.
+ * Annotations are not modified.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to follow the current interception rules to determine the
+ * appropriate action to take for the response.
+ */
+ static ProxyResponseReceivedAction continueWith(HttpResponse response)
+ {
+ return FACTORY.responseInitialInterceptResultFollowUserRules(response);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the response.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP response.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to follow the current interception rules to determine the
+ * appropriate action to take for the response.
+ */
+ static ProxyResponseReceivedAction continueWith(HttpResponse response, Annotations annotations)
+ {
+ return FACTORY.responseInitialInterceptResultFollowUserRules(response, annotations);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * present the response to the user for manual review or modification.
+ * Annotations are not modified.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to present the response to the user for manual review or
+ * modification.
+ */
+ static ProxyResponseReceivedAction intercept(HttpResponse response)
+ {
+ return FACTORY.responseInitialInterceptResultIntercept(response);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * present the response to the user for manual review or modification.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP response.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to present the response to the user for manual review or
+ * modification.
+ */
+ static ProxyResponseReceivedAction intercept(HttpResponse response, Annotations annotations)
+ {
+ return FACTORY.responseInitialInterceptResultIntercept(response, annotations);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * forward the response without presenting it to the user.
+ * Annotations are not modified.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to forward the response without presenting it to the user.
+ */
+ static ProxyResponseReceivedAction doNotIntercept(HttpResponse response)
+ {
+ return FACTORY.responseInitialInterceptResultDoNotIntercept(response);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * forward the response without presenting it to the user.
+ *
+ * @param response The {@link HttpResponse} received after any
+ * modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted
+ * HTTP response.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to forward the response without presenting it to the user.
+ */
+ static ProxyResponseReceivedAction doNotIntercept(HttpResponse response, Annotations annotations)
+ {
+ return FACTORY.responseInitialInterceptResultDoNotIntercept(response, annotations);
+ }
+
+ /**
+ * This method can be used to create an action that causes Burp Proxy to
+ * drop the response.
+ *
+ * @return The {@link ProxyResponseReceivedAction} that causes Burp
+ * Proxy to drop the response.
+ */
+ static ProxyResponseReceivedAction drop()
+ {
+ return FACTORY.responseInitialInterceptResultDrop();
+ }
+
+ /**
+ * This method can be used to create a default implementation of a {@link ProxyResponseReceivedAction}
+ * for an HTTP response.
+ *
+ * @param response The {@link HttpResponse} received after any modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted HTTP response. {@code null} value will leave the annotations unmodified.
+ * @param action The {@link MessageReceivedAction} for the HTTP response.
+ *
+ * @return The {@link ProxyResponseReceivedAction} including the HTTP response, annotations and intercept action.
+ */
+ static ProxyResponseReceivedAction proxyResponseReceivedAction(HttpResponse response, Annotations annotations, MessageReceivedAction action)
+ {
+ return FACTORY.proxyResponseReceivedAction(response, annotations, action);
+ }
+}
diff --git a/src/burp/api/montoya/proxy/http/ProxyResponseToBeSentAction.java b/src/burp/api/montoya/proxy/http/ProxyResponseToBeSentAction.java
new file mode 100644
index 0000000..593102b
--- /dev/null
+++ b/src/burp/api/montoya/proxy/http/ProxyResponseToBeSentAction.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.http;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.proxy.MessageToBeSentAction;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a result from
+ * {@link ProxyResponseHandler#handleResponseToBeSent(InterceptedResponse)}.
+ */
+public interface ProxyResponseToBeSentAction
+{
+ /**
+ * This method retrieves the current final intercept action.
+ *
+ * @return The {@link MessageToBeSentAction}.
+ */
+ MessageToBeSentAction action();
+
+ /**
+ * This method retrieves the current HTTP response to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link HttpResponse} to forward after any modifications by
+ * the extension.
+ */
+ HttpResponse response();
+
+ /**
+ * This method retrieves the annotations for the current response after any
+ * modifications by the extension.
+ *
+ * @return The {@link Annotations} for the intercepted HTTP response.
+ */
+ Annotations annotations();
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the response.
+ * Annotations are not modified.
+ *
+ * @param response The {@link HttpResponse} to forward after any
+ * modifications by the extension.
+ *
+ * @return The {@link ProxyResponseToBeSentAction} that causes Burp Proxy
+ * to forward the response.
+ */
+ static ProxyResponseToBeSentAction continueWith(HttpResponse response)
+ {
+ return FACTORY.responseFinalInterceptResultContinueWith(response);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * forward the response.
+ *
+ * @param response The {@link HttpResponse} to forward after any modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted HTTP response.
+ *
+ * @return The {@link ProxyResponseToBeSentAction} that causes Burp Proxy
+ * to forward the response.
+ */
+ static ProxyResponseToBeSentAction continueWith(HttpResponse response, Annotations annotations)
+ {
+ return FACTORY.responseFinalInterceptResultContinueWith(response, annotations);
+ }
+
+ /**
+ * This method can be used to create a result that causes Burp Proxy to
+ * drop the response.
+ *
+ * @return The {@link ProxyResponseToBeSentAction} that causes Burp Proxy
+ * to drop the response.
+ */
+ static ProxyResponseToBeSentAction drop()
+ {
+ return FACTORY.responseFinalInterceptResultDrop();
+ }
+
+ /**
+ * This method can be used to create a default implementation of a final
+ * intercept result for an HTTP response.
+ *
+ * @param response The {@link HttpResponse} to forward after any modifications by the extension.
+ * @param annotations The {@link Annotations} for the intercepted HTTP response. {@code null} value will leave the annotations unmodified.
+ * @param action The {@link MessageToBeSentAction} for the HTTP response.
+ *
+ * @return The {@link ProxyResponseToBeSentAction} including the HTTP
+ * response, annotations and final intercept action.
+ */
+ static ProxyResponseToBeSentAction proxyResponseToReturnAction(HttpResponse response, Annotations annotations, MessageToBeSentAction action)
+ {
+ return FACTORY.proxyResponseToReturnAction(response, annotations, action);
+ }
+}
diff --git a/src/burp/api/montoya/proxy/websocket/BinaryMessageReceivedAction.java b/src/burp/api/montoya/proxy/websocket/BinaryMessageReceivedAction.java
new file mode 100644
index 0000000..0b49cf1
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/BinaryMessageReceivedAction.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.proxy.MessageReceivedAction;
+import burp.api.montoya.websocket.BinaryMessage;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a binary message from
+ * {@link ProxyMessageHandler#handleBinaryMessageReceived(InterceptedBinaryMessage)}.
+ */
+public interface BinaryMessageReceivedAction
+{
+ /**
+ * @return The action associated with this message.
+ */
+ MessageReceivedAction action();
+
+ /**
+ * @return The payload of this message.
+ */
+ ByteArray payload();
+
+ /**
+ * Build a binary WebSocket message to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the message.
+ *
+ * @param payload The binary message payload.
+ *
+ * @return The {@link BinaryMessageReceivedAction} that allows user rules to be
+ * followed.
+ */
+ static BinaryMessageReceivedAction continueWith(ByteArray payload)
+ {
+ return FACTORY.followUserRulesInitialProxyBinaryMessage(payload);
+ }
+
+ /**
+ * Build a binary WebSocket message to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the message.
+ *
+ * @param message The binary message.
+ *
+ * @return The {@link BinaryMessageReceivedAction} that allows user rules to be
+ * followed.
+ */
+ static BinaryMessageReceivedAction continueWith(BinaryMessage message)
+ {
+ return FACTORY.followUserRulesInitialProxyBinaryMessage(message.payload());
+ }
+
+ /**
+ * Build a binary WebSocket message to be intercepted within the Proxy.
+ *
+ * @param payload The binary message payload.
+ *
+ * @return The message.
+ */
+ static BinaryMessageReceivedAction intercept(ByteArray payload)
+ {
+ return FACTORY.interceptInitialProxyBinaryMessage(payload);
+ }
+
+ /**
+ * Build a binary WebSocket message to be intercepted within the Proxy.
+ *
+ * @param message The binary message.
+ *
+ * @return The message.
+ */
+ static BinaryMessageReceivedAction intercept(BinaryMessage message)
+ {
+ return FACTORY.interceptInitialProxyBinaryMessage(message.payload());
+ }
+
+ /**
+ * Build a binary WebSocket message to continue within the Proxy without interception.
+ *
+ * @param payload The binary message payload.
+ *
+ * @return The message.
+ */
+ static BinaryMessageReceivedAction doNotIntercept(ByteArray payload)
+ {
+ return FACTORY.doNotInterceptInitialProxyBinaryMessage(payload);
+ }
+
+ /**
+ * Build a binary WebSocket message to continue within the Proxy without interception.
+ *
+ * @param message The binary message.
+ *
+ * @return The message.
+ */
+ static BinaryMessageReceivedAction doNotIntercept(BinaryMessage message)
+ {
+ return FACTORY.doNotInterceptInitialProxyBinaryMessage(message.payload());
+ }
+
+ /**
+ * Build a binary WebSocket message to be dropped.
+ *
+ * @return The message to be dropped.
+ */
+ static BinaryMessageReceivedAction drop()
+ {
+ return FACTORY.dropInitialProxyBinaryMessage();
+ }
+}
diff --git a/src/burp/api/montoya/proxy/websocket/BinaryMessageToBeSentAction.java b/src/burp/api/montoya/proxy/websocket/BinaryMessageToBeSentAction.java
new file mode 100644
index 0000000..386130a
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/BinaryMessageToBeSentAction.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.proxy.MessageToBeSentAction;
+import burp.api.montoya.websocket.BinaryMessage;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Extensions can implement this interface when returning a binary message from
+ * {@link ProxyMessageHandler#handleBinaryMessageToBeSent(InterceptedBinaryMessage)}.
+ */
+public interface BinaryMessageToBeSentAction
+{
+ /**
+ * @return The action associated with this message.
+ */
+ MessageToBeSentAction action();
+
+ /**
+ * @return The payload of this message.
+ */
+ ByteArray payload();
+
+ /**
+ * Build a binary WebSocket message to continue through Burp.
+ *
+ * @param payload The binary message payload.
+ *
+ * @return The message.
+ */
+ static BinaryMessageToBeSentAction continueWith(ByteArray payload)
+ {
+ return FACTORY.continueWithFinalProxyBinaryMessage(payload);
+ }
+
+ /**
+ * Build a binary WebSocket message to continue through Burp.
+ *
+ * @param message The binary message.
+ *
+ * @return The message.
+ */
+ static BinaryMessageToBeSentAction continueWith(BinaryMessage message)
+ {
+ return FACTORY.continueWithFinalProxyBinaryMessage(message.payload());
+ }
+
+ /**
+ * Build a binary WebSocket message to be dropped.
+ *
+ * @return The message to be dropped.
+ */
+ static BinaryMessageToBeSentAction drop()
+ {
+ return FACTORY.dropFinalProxyBinaryMessage();
+ }
+}
diff --git a/src/burp/api/montoya/proxy/websocket/InterceptedBinaryMessage.java b/src/burp/api/montoya/proxy/websocket/InterceptedBinaryMessage.java
new file mode 100644
index 0000000..1b27e2c
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/InterceptedBinaryMessage.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.websocket.BinaryMessage;
+import burp.api.montoya.websocket.Direction;
+
+public interface InterceptedBinaryMessage extends BinaryMessage
+{
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * @return Binary based WebSocket payload.
+ */
+ @Override
+ ByteArray payload();
+
+ /**
+ * @return The direction of the message.
+ */
+ @Override
+ Direction direction();
+}
diff --git a/src/burp/api/montoya/proxy/websocket/InterceptedTextMessage.java b/src/burp/api/montoya/proxy/websocket/InterceptedTextMessage.java
new file mode 100644
index 0000000..ed8b0ef
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/InterceptedTextMessage.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.websocket.Direction;
+import burp.api.montoya.websocket.TextMessage;
+
+public interface InterceptedTextMessage extends TextMessage
+{
+ /**
+ * @return The annotations.
+ */
+ Annotations annotations();
+
+ /**
+ * @return Text based WebSocket payload.
+ */
+ @Override
+ String payload();
+
+ /**
+ * @return The direction of the message.
+ */
+ @Override
+ Direction direction();
+}
diff --git a/src/burp/api/montoya/proxy/websocket/ProxyMessageHandler.java b/src/burp/api/montoya/proxy/websocket/ProxyMessageHandler.java
new file mode 100644
index 0000000..2528115
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/ProxyMessageHandler.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+/**
+ * This interface allows an extension to be notified when messages are sent or received via the proxy WebSocket, or it has been closed.
+ */
+public interface ProxyMessageHandler
+{
+ /**
+ * Invoked when a text message is received from either the client or server.
+ * This gives the extension the ability to modify the message before it is
+ * processed by Burp.
+ *
+ * @param interceptedTextMessage Intercepted text WebSocket message.
+ *
+ * @return The {@link TextMessageReceivedAction} containing the required action and text message to be passed through.
+ */
+ TextMessageReceivedAction handleTextMessageReceived(InterceptedTextMessage interceptedTextMessage);
+
+ /**
+ * Invoked when a text message is about to be sent to either the client or server.
+ * This gives the extension the ability to modify the message before it is
+ * sent.
+ *
+ * @param interceptedTextMessage Intercepted text WebSocket message.
+ *
+ * @return The {@link TextMessageReceivedAction} containing the required action and text message to be passed through.
+ */
+ TextMessageToBeSentAction handleTextMessageToBeSent(InterceptedTextMessage interceptedTextMessage);
+
+ /**
+ * Invoked when a binary message is received from either the client or server.
+ * This gives the extension the ability to modify the message before it is
+ * processed by Burp.
+ *
+ * @param interceptedBinaryMessage Intercepted binary WebSocket message.
+ *
+ * @return The {@link BinaryMessageReceivedAction} containing the required action and binary message to be passed through.
+ */
+ BinaryMessageReceivedAction handleBinaryMessageReceived(InterceptedBinaryMessage interceptedBinaryMessage);
+
+ /**
+ * Invoked when a binary message is about to be sent to either the client or server.
+ * This gives the extension the ability to modify the message before it is
+ * sent.
+ *
+ * @param interceptedBinaryMessage Intercepted binary WebSocket message.
+ *
+ * @return The {@link BinaryMessageReceivedAction} containing the required action and binary message to be passed through.
+ */
+ BinaryMessageToBeSentAction handleBinaryMessageToBeSent(InterceptedBinaryMessage interceptedBinaryMessage);
+
+ /**
+ * Invoked when the WebSocket is closed.
+ */
+ default void onClose()
+ {
+ }
+}
diff --git a/src/burp/api/montoya/proxy/websocket/ProxyWebSocket.java b/src/burp/api/montoya/proxy/websocket/ProxyWebSocket.java
new file mode 100644
index 0000000..5a0bc73
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/ProxyWebSocket.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.websocket.Direction;
+
+/**
+ * ProxyWebSocket within Burp.
+ */
+public interface ProxyWebSocket
+{
+ /**
+ * This method allows an extension to send a text message via the WebSocket to either the client or the server.
+ *
+ * @param textMessage The message to be sent.
+ * @param direction The direction of the message.
+ */
+ void sendTextMessage(String textMessage, Direction direction);
+
+ /**
+ * This method allows an extension to send a binary message via the WebSocket to either the client or the server.
+ *
+ * @param binaryMessage The message to be sent.
+ * @param direction The direction of the message.
+ */
+ void sendBinaryMessage(ByteArray binaryMessage, Direction direction);
+
+ /**
+ * This method will close the WebSocket.
+ */
+ void close();
+
+ /**
+ * Register a handler which will perform actions when messages are sent or received by the WebSocket.
+ *
+ * @param handler An object created by the extension that implements {@link ProxyMessageHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerProxyMessageHandler(ProxyMessageHandler handler);
+}
diff --git a/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreation.java b/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreation.java
new file mode 100644
index 0000000..68a8f8b
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreation.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+/**
+ * Information about the proxy web socket that is being created.
+ */
+public interface ProxyWebSocketCreation
+{
+ /**
+ * @return The ProxyWebSocket that is being created.
+ */
+ ProxyWebSocket proxyWebSocket();
+
+ /**
+ * @return The HTTP upgrade request that initiated the WebSocket creation.
+ */
+ HttpRequest upgradeRequest();
+}
diff --git a/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreationHandler.java b/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreationHandler.java
new file mode 100644
index 0000000..5801600
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/ProxyWebSocketCreationHandler.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.proxy.Proxy;
+
+/**
+ * Extensions can implement this interface and then call {@link Proxy#registerWebSocketCreationHandler} to register a WebSocket handler.
+ * The handler will be notified of new WebSockets being created by the Proxy tool.
+ */
+public interface ProxyWebSocketCreationHandler
+{
+ /**
+ * Invoked by Burp when a WebSocket is being created by the Proxy tool.
+ * Note that the client side of the connection will not be upgraded until after this method completes.
+ *
+ * @param webSocketCreation {@link ProxyWebSocketCreation} containing information about the proxy websocket that is being created
+ */
+ void handleWebSocketCreation(ProxyWebSocketCreation webSocketCreation);
+}
diff --git a/src/burp/api/montoya/proxy/websocket/TextMessageReceivedAction.java b/src/burp/api/montoya/proxy/websocket/TextMessageReceivedAction.java
new file mode 100644
index 0000000..9c6f110
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/TextMessageReceivedAction.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.proxy.MessageReceivedAction;
+import burp.api.montoya.websocket.TextMessage;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+
+/**
+ * Extensions can implement this interface when returning a text message from
+ * {@link ProxyMessageHandler#handleTextMessageReceived(InterceptedTextMessage)}.
+ */
+public interface TextMessageReceivedAction
+{
+ /**
+ * @return The action associated with this message.
+ */
+ MessageReceivedAction action();
+
+ /**
+ * @return The payload of this message.
+ */
+ String payload();
+
+ /**
+ * Build a text WebSocket message to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the message.
+ *
+ * @param payload The text message payload.
+ *
+ * @return The {@link TextMessageReceivedAction} that allows user rules to be
+ * followed.
+ */
+ static TextMessageReceivedAction continueWith(String payload)
+ {
+ return FACTORY.followUserRulesInitialProxyTextMessage(payload);
+ }
+
+ /**
+ * Build a text WebSocket message to
+ * follow the current interception rules to determine the appropriate
+ * action to take for the message.
+ *
+ * @param message The text message.
+ *
+ * @return The {@link TextMessageReceivedAction} that allows user rules to be
+ * followed.
+ */
+ static TextMessageReceivedAction continueWith(TextMessage message)
+ {
+ return FACTORY.followUserRulesInitialProxyTextMessage(message.payload());
+ }
+
+ /**
+ * Build a text WebSocket message to be intercepted within the Proxy.
+ *
+ * @param payload The text message payload.
+ *
+ * @return The message.
+ */
+ static TextMessageReceivedAction intercept(String payload)
+ {
+ return FACTORY.interceptInitialProxyTextMessage(payload);
+ }
+
+ /**
+ * Build a text WebSocket message to be intercepted within the Proxy.
+ *
+ * @param message The text message.
+ *
+ * @return The message.
+ */
+ static TextMessageReceivedAction intercept(TextMessage message)
+ {
+ return FACTORY.interceptInitialProxyTextMessage(message.payload());
+ }
+
+ /**
+ * Build a text WebSocket message to continue within the Proxy without interception.
+ *
+ * @param payload The text message payload.
+ *
+ * @return The message.
+ */
+ static TextMessageReceivedAction doNotIntercept(String payload)
+ {
+ return FACTORY.doNotInterceptInitialProxyTextMessage(payload);
+ }
+
+ /**
+ * Build a text WebSocket message to continue within the Proxy without interception.
+ *
+ * @param message The text message payload.
+ *
+ * @return The message.
+ */
+ static TextMessageReceivedAction doNotIntercept(TextMessage message)
+ {
+ return FACTORY.doNotInterceptInitialProxyTextMessage(message.payload());
+ }
+
+ /**
+ * Build a text WebSocket message to be dropped.
+ *
+ * @return The message to be dropped.
+ */
+ static TextMessageReceivedAction drop()
+ {
+ return FACTORY.dropInitialProxyTextMessage();
+ }
+}
diff --git a/src/burp/api/montoya/proxy/websocket/TextMessageToBeSentAction.java b/src/burp/api/montoya/proxy/websocket/TextMessageToBeSentAction.java
new file mode 100644
index 0000000..12f5cd6
--- /dev/null
+++ b/src/burp/api/montoya/proxy/websocket/TextMessageToBeSentAction.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.proxy.websocket;
+
+import burp.api.montoya.proxy.MessageToBeSentAction;
+import burp.api.montoya.websocket.TextMessage;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+
+/**
+ * Extensions can implement this interface when returning a text message from
+ * {@link ProxyMessageHandler#handleTextMessageToBeSent(InterceptedTextMessage)}.
+ */
+public interface TextMessageToBeSentAction
+{
+ /**
+ * @return The action associated with this message.
+ */
+ MessageToBeSentAction action();
+
+ /**
+ * @return The payload of this message.
+ */
+ String payload();
+
+ /**
+ * Build a text WebSocket message to continue through Burp.
+ *
+ * @param payload The text message payload.
+ *
+ * @return The message.
+ */
+ static TextMessageToBeSentAction continueWith(String payload)
+ {
+ return FACTORY.continueWithFinalProxyTextMessage(payload);
+ }
+
+ /**
+ * Build a text WebSocket message to continue through Burp.
+ *
+ * @param message The text message.
+ *
+ * @return The message.
+ */
+ static TextMessageToBeSentAction continueWith(TextMessage message)
+ {
+ return FACTORY.continueWithFinalProxyTextMessage(message.payload());
+ }
+
+ /**
+ * Build a text WebSocket message to be dropped.
+ *
+ * @return The message to be dropped.
+ */
+ static TextMessageToBeSentAction drop()
+ {
+ return FACTORY.dropFinalProxyTextMessage();
+ }
+}
diff --git a/src/burp/api/montoya/repeater/Repeater.java b/src/burp/api/montoya/repeater/Repeater.java
new file mode 100644
index 0000000..aaaf1c2
--- /dev/null
+++ b/src/burp/api/montoya/repeater/Repeater.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.repeater;
+
+import burp.api.montoya.http.message.requests.HttpRequest;
+
+/**
+ * Provides access to the functionality of the Repeater tool.
+ */
+public interface Repeater
+{
+ /**
+ * This method can be used to send an HTTP request to the Burp Repeater
+ * tool. The request will be displayed in the user interface using a
+ * default tab index, but will not be sent until the user initiates
+ * this action.
+ *
+ * @param request The full HTTP request.
+ */
+ void sendToRepeater(HttpRequest request);
+
+ /**
+ * This method can be used to send an HTTP request to the Burp Repeater
+ * tool. The request will be displayed in the user interface, but will not
+ * be issued until the user initiates this action.
+ *
+ * @param request The full HTTP request.
+ * @param name An optional caption which will appear on the Repeater
+ * tab containing the request. If this value is {@code null} then a default
+ * tab index will be displayed.
+ */
+ void sendToRepeater(HttpRequest request, String name);
+}
diff --git a/src/burp/api/montoya/scanner/AuditConfiguration.java b/src/burp/api/montoya/scanner/AuditConfiguration.java
new file mode 100644
index 0000000..32cdd90
--- /dev/null
+++ b/src/burp/api/montoya/scanner/AuditConfiguration.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This class represents the configuration required for an audit in the Burp Scanner Tool.
+ */
+public interface AuditConfiguration
+{
+ /**
+ * This method can be used to create a built-in audit configuration.
+ *
+ * @param configuration The {@link BuiltInAuditConfiguration} to use for the audit.
+ *
+ * @return a {@code AuditConfiguration} based on a built-in configuration
+ */
+ static AuditConfiguration auditConfiguration(BuiltInAuditConfiguration configuration)
+ {
+ return FACTORY.auditConfiguration(configuration);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/AuditResult.java b/src/burp/api/montoya/scanner/AuditResult.java
new file mode 100644
index 0000000..89487e3
--- /dev/null
+++ b/src/burp/api/montoya/scanner/AuditResult.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+public interface AuditResult
+{
+ List auditIssues();
+
+ static AuditResult auditResult(List auditIssues)
+ {
+ return FACTORY.auditResult(auditIssues);
+ }
+
+ static AuditResult auditResult(AuditIssue... auditIssues)
+ {
+ return FACTORY.auditResult(auditIssues);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/BuiltInAuditConfiguration.java b/src/burp/api/montoya/scanner/BuiltInAuditConfiguration.java
new file mode 100644
index 0000000..cf401e4
--- /dev/null
+++ b/src/burp/api/montoya/scanner/BuiltInAuditConfiguration.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * This enum represents built in configurations for the Burp Scanner tool.
+ */
+public enum BuiltInAuditConfiguration
+{
+ LEGACY_PASSIVE_AUDIT_CHECKS,
+ LEGACY_ACTIVE_AUDIT_CHECKS
+}
diff --git a/src/burp/api/montoya/scanner/ConsolidationAction.java b/src/burp/api/montoya/scanner/ConsolidationAction.java
new file mode 100644
index 0000000..ac4b492
--- /dev/null
+++ b/src/burp/api/montoya/scanner/ConsolidationAction.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * This enum represents the action to be taken when duplicate audit issues are
+ * found.
+ */
+public enum ConsolidationAction
+{
+ KEEP_EXISTING,
+ KEEP_BOTH,
+ KEEP_NEW
+}
diff --git a/src/burp/api/montoya/scanner/Crawl.java b/src/burp/api/montoya/scanner/Crawl.java
new file mode 100644
index 0000000..072b5bf
--- /dev/null
+++ b/src/burp/api/montoya/scanner/Crawl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * Crawl in the Burp Scanner tool.
+ */
+public interface Crawl extends ScanTask
+{
+ /**
+ * Number of requests that have been made for the
+ * scan task.
+ *
+ * @return The number of requests that have been made for the scan task.
+ */
+ @Override
+ int requestCount();
+
+ /**
+ * Number of network errors that have occurred for
+ * the scan task.
+ *
+ * @return The number of network errors that have occurred for the scan
+ * task.
+ */
+ @Override
+ int errorCount();
+
+ /**
+ * Delete the task.
+ */
+ @Override
+ void delete();
+
+ /**
+ * This functionality is not yet implemented.
+ *
+ * @return the current status message of the task
+ */
+ @Override
+ String statusMessage();
+}
diff --git a/src/burp/api/montoya/scanner/CrawlAndAudit.java b/src/burp/api/montoya/scanner/CrawlAndAudit.java
new file mode 100644
index 0000000..8675186
--- /dev/null
+++ b/src/burp/api/montoya/scanner/CrawlAndAudit.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * Crawl and audit in the Burp Scanner tool.
+ */
+public interface CrawlAndAudit extends ScanTask
+{
+ /**
+ * Number of requests that have been made for the
+ * scan task.
+ *
+ * @return The number of requests that have been made for the scan task.
+ */
+ @Override
+ int requestCount();
+
+ /**
+ * Number of network errors that have occurred for
+ * the scan task.
+ *
+ * @return The number of network errors that have occurred for the scan
+ * task.
+ */
+ @Override
+ int errorCount();
+
+ /**
+ * Delete the task.
+ */
+ @Override
+ void delete();
+
+ /**
+ * @return the current status message of the task
+ */
+ @Override
+ String statusMessage();
+}
diff --git a/src/burp/api/montoya/scanner/CrawlConfiguration.java b/src/burp/api/montoya/scanner/CrawlConfiguration.java
new file mode 100644
index 0000000..8b721b9
--- /dev/null
+++ b/src/burp/api/montoya/scanner/CrawlConfiguration.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This class represents the configuration required for an crawl in the Burp Scanner Tool.
+ */
+public interface CrawlConfiguration
+{
+ /**
+ * @return the seed urls for the crawl
+ */
+ List seedUrls();
+
+ /**
+ * Build a crawl configuration with seed urls
+ *
+ * @param seedUrls used by the crawler
+ *
+ * @return crawl configuration required by the crawler.
+ */
+ static CrawlConfiguration crawlConfiguration(String... seedUrls)
+ {
+ return FACTORY.crawlConfiguration(seedUrls);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/ReportFormat.java b/src/burp/api/montoya/scanner/ReportFormat.java
new file mode 100644
index 0000000..5e8053b
--- /dev/null
+++ b/src/burp/api/montoya/scanner/ReportFormat.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * This enum represents the formats for scan reports.
+ */
+public enum ReportFormat
+{
+ HTML,
+ XML
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/scanner/ScanCheck.java b/src/burp/api/montoya/scanner/ScanCheck.java
new file mode 100644
index 0000000..adb5a9a
--- /dev/null
+++ b/src/burp/api/montoya/scanner/ScanCheck.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPoint;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Scanner#registerScanCheck(ScanCheck)} to register a custom Scanner
+ * check. When performing an audit, Burp will ask the check to perform an
+ * active or passive audit on the base request, and report any audit issues
+ * that are identified.
+ */
+public interface ScanCheck
+{
+ /**
+ * The Scanner invokes this method for each insertion point that is
+ * actively audited. Extensions may issue HTTP requests as required to
+ * carry out an active audit, and should use the
+ * {@link AuditInsertionPoint} object provided to build requests for
+ * particular payloads.
+ * Note:
+ * Scan checks should submit raw non-encoded payloads to insertion points,
+ * and the insertion point has responsibility for performing any data
+ * encoding that is necessary given the nature and location of the insertion
+ * point.
+ *
+ * @param baseRequestResponse The base {@link HttpRequestResponse} that
+ * should be actively audited.
+ * @param auditInsertionPoint An {@link AuditInsertionPoint} object that
+ * can be queried to obtain details of the insertion point being tested, and
+ * can be used to build requests for particular payloads.
+ *
+ * @return An {@link AuditResult} object with a list of {@link AuditIssue}
+ * objects, or an empty {@link AuditResult} object if no issues are identified.
+ */
+ AuditResult activeAudit(HttpRequestResponse baseRequestResponse, AuditInsertionPoint auditInsertionPoint);
+
+ /**
+ * The Scanner invokes this method for each base request / response that is
+ * passively audited. Note: Extensions should only analyze the
+ * HTTP messages provided during a passive audit, and should not make any
+ * new HTTP requests of their own.
+ *
+ * @param baseRequestResponse The base {@link HttpRequestResponse} that
+ * should be passively audited.
+ *
+ * @return An {@link AuditResult} object with a list of {@link AuditIssue}
+ * objects, or an empty {@link AuditResult} object if no issues are identified.
+ */
+ AuditResult passiveAudit(HttpRequestResponse baseRequestResponse);
+
+ /**
+ * The Scanner invokes this method when the custom Scan check has
+ * reported multiple issues for the same URL path. This can arise either
+ * because there are multiple distinct vulnerabilities, or because the same
+ * (or a similar) request has been scanned more than once. The custom check
+ * should determine whether the issues are duplicates. In most cases, where
+ * a check uses distinct issue names or descriptions for distinct issues,
+ * the consolidation process will simply be a matter of comparing these
+ * features for the two issues.
+ *
+ * @param newIssue An {@link AuditIssue} at the same URL path that has been
+ * newly reported by this Scan check.
+ * @param existingIssue An {@link AuditIssue} that was previously reported
+ * by this Scan check.
+ *
+ * @return A {@link ConsolidationAction} to determine which issue(s) should
+ * be reported in the main Scanner results.
+ */
+ ConsolidationAction consolidateIssues(AuditIssue newIssue, AuditIssue existingIssue);
+}
diff --git a/src/burp/api/montoya/scanner/ScanConfiguration.java b/src/burp/api/montoya/scanner/ScanConfiguration.java
new file mode 100644
index 0000000..1f35044
--- /dev/null
+++ b/src/burp/api/montoya/scanner/ScanConfiguration.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+/**
+ * Configurations for the Burp Scanner tool.
+ */
+public interface ScanConfiguration
+{
+}
diff --git a/src/burp/api/montoya/scanner/ScanTask.java b/src/burp/api/montoya/scanner/ScanTask.java
new file mode 100644
index 0000000..8d05be9
--- /dev/null
+++ b/src/burp/api/montoya/scanner/ScanTask.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import burp.api.montoya.core.Task;
+
+/**
+ * This interface is used to retrieve details of tasks in the Burp Scanner.
+ */
+public interface ScanTask extends Task
+{
+ /**
+ * Number of requests that have been made for the
+ * scan task.
+ *
+ * @return The number of requests that have been made for the scan task.
+ */
+ int requestCount();
+
+ /**
+ * Number of network errors that have occurred for
+ * the scan task.
+ *
+ * @return The number of network errors that have occurred for the scan
+ * task.
+ */
+ int errorCount();
+
+ /**
+ * Delete the task.
+ */
+ @Override
+ void delete();
+
+ /**
+ * @return the current status message of the task
+ */
+ @Override
+ String statusMessage();
+}
diff --git a/src/burp/api/montoya/scanner/Scanner.java b/src/burp/api/montoya/scanner/Scanner.java
new file mode 100644
index 0000000..878bc77
--- /dev/null
+++ b/src/burp/api/montoya/scanner/Scanner.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner;
+
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.scanner.audit.Audit;
+import burp.api.montoya.scanner.audit.AuditIssueHandler;
+import burp.api.montoya.scanner.audit.insertionpoint.AuditInsertionPointProvider;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+import burp.api.montoya.scanner.bchecks.BChecks;
+
+import java.nio.file.Path;
+import java.util.List;
+
+/**
+ * [Professional only] Provides access to the functionality of the Scanner tool.
+ */
+public interface Scanner
+{
+ /**
+ * Register a handler which will be notified of new
+ * audit issues that are reported by the Scanner tool. Extensions can
+ * perform custom analysis or logging of audit issues by registering an
+ * audit issue handler.
+ *
+ * @param auditIssueHandler An object created by the extension that
+ * implements the {@link AuditIssueHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerAuditIssueHandler(AuditIssueHandler auditIssueHandler);
+
+ /**
+ * Register a custom Scanner check. When performing
+ * scanning, Burp will ask the check to perform active or passive scanning
+ * on the base request, and report any Scanner issues that are identified.
+ *
+ * @param scanCheck An object created by the extension that implements the
+ * {@link ScanCheck} interface.
+ *
+ * @return The {@link Registration} for the check.
+ */
+ Registration registerScanCheck(ScanCheck scanCheck);
+
+ /**
+ * Register a provider of Scanner insertion points.
+ * For each base request that is actively scanned, Burp will ask the
+ * provider to provide any custom Scanner insertion points that are
+ * appropriate for the request.
+ *
+ * @param insertionPointProvider An object created by the extension that
+ * implements the {@link AuditInsertionPointProvider} interface.
+ *
+ * @return The {@link Registration} for the provider.
+ */
+ Registration registerInsertionPointProvider(AuditInsertionPointProvider insertionPointProvider);
+
+ /**
+ * This method can be used to start a crawl in the Burp Scanner tool.
+ *
+ * @return The {@link Crawl} started in the Burp Scanner tool.
+ */
+ Crawl startCrawl(CrawlConfiguration crawlConfiguration);
+
+ /**
+ * This method can be used to start an audit in the Burp Scanner tool.
+ *
+ * @return The {@link Audit} started in the Burp Scanner tool.
+ */
+ Audit startAudit(AuditConfiguration auditConfiguration);
+
+ /**
+ * Generate a report for the specified Scanner
+ * issues. The report format can be specified. For all other reporting
+ * options, the default settings that appear in the reporting UI wizard are
+ * used.
+ *
+ * @param issues The {@link AuditIssue}s issues to be reported.
+ * @param format The {@link ReportFormat} to be used in the report.
+ * @param path The {@link Path} to the file that will be saved.
+ */
+ void generateReport(List issues, ReportFormat format, Path path);
+
+ /**
+ * Access functionality related to BChecks.
+ *
+ * @return An implementation of the {@link BChecks} interface which exposes BChecks functionality.
+ */
+ BChecks bChecks();
+}
diff --git a/src/burp/api/montoya/scanner/audit/Audit.java b/src/burp/api/montoya/scanner/audit/Audit.java
new file mode 100644
index 0000000..e2cedb4
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/Audit.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit;
+
+import burp.api.montoya.core.Range;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.scanner.ScanTask;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+import java.util.List;
+
+/**
+ * Audit in the Burp Scanner tool.
+ */
+public interface Audit extends ScanTask
+{
+ /**
+ * This method retrieves the number of insertion points.
+ *
+ * @return The number of insertion points.
+ */
+ int insertionPointCount();
+
+ /**
+ * This method retrieves the audit issues found by this audit.
+ *
+ * @return The list of {@link AuditIssue}s found by this audit.
+ */
+ List issues();
+
+ /**
+ * This method can be used to add an HTTP request to this audit.
+ *
+ * @param request The {@link HttpRequest} to add to this audit.
+ */
+ void addRequest(HttpRequest request);
+
+ /**
+ * This method can be used to add an HTTP request to this audit.
+ *
+ * @param request The {@link HttpRequest} to add to this audit.
+ * @param insertionPointOffsets The list of {@link Range}s representing the
+ * insertion point offsets.
+ */
+ void addRequest(HttpRequest request, List insertionPointOffsets);
+
+ /**
+ * This method can be used to add an HTTP request and response to this
+ * audit.
+ *
+ * @param requestResponse The {@link HttpRequestResponse} to add to this
+ * audit.
+ */
+ void addRequestResponse(HttpRequestResponse requestResponse);
+
+ /**
+ * Number of requests that have been made for the
+ * scan task.
+ *
+ * @return The number of requests that have been made for the scan task.
+ */
+ @Override
+ int requestCount();
+
+ /**
+ * Number of network errors that have occurred for
+ * the scan task.
+ *
+ * @return The number of network errors that have occurred for the scan
+ * task.
+ */
+ @Override
+ int errorCount();
+
+ /**
+ * Delete the task.
+ */
+ @Override
+ void delete();
+
+ /**
+ * @return the current status message of the task
+ */
+ @Override
+ String statusMessage();
+}
diff --git a/src/burp/api/montoya/scanner/audit/AuditIssueHandler.java b/src/burp/api/montoya/scanner/audit/AuditIssueHandler.java
new file mode 100644
index 0000000..7a01fc3
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/AuditIssueHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit;
+
+import burp.api.montoya.scanner.Scanner;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Scanner#registerAuditIssueHandler(AuditIssueHandler)} to register an
+ * audit issue handler. The handler will be notified of new issues that are
+ * reported by the Scanner tool. Extensions can perform custom analysis or
+ * logging of audit issues by registering an audit issue handler.
+ */
+public interface AuditIssueHandler
+{
+ /**
+ * This method is invoked when a new issue is added to Burp Scanner's
+ * results.
+ *
+ * @param auditIssue An {@link AuditIssue} object that the extension can
+ * query to obtain details about the new issue.
+ */
+ void handleNewAuditIssue(AuditIssue auditIssue);
+}
diff --git a/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPoint.java b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPoint.java
new file mode 100644
index 0000000..96b31d9
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPoint.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.insertionpoint;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Range;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.scanner.ScanCheck;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This interface is used to define an insertion point for use by active Scan
+ * checks. Extensions can obtain instances of this interface by registering an
+ * {@link ScanCheck}, or can create instances for use by Burp's own scan checks
+ * by registering an {@link AuditInsertionPointProvider}.
+ */
+public interface AuditInsertionPoint
+{
+ /**
+ * Name of this insertion point.
+ *
+ * @return The name of this insertion point (for example, a description of
+ * a particular request parameter).
+ */
+ String name();
+
+ /**
+ * Base value for this insertion point.
+ *
+ * @return the base value that appears in this insertion point in the base
+ * request being audited, or {@code null} if there is no value in the base
+ * request that corresponds to this insertion point.
+ */
+ String baseValue();
+
+ /**
+ * Build a request with the specified payload placed
+ * into the insertion point. There is no requirement for extension-provided
+ * insertion points to adjust the Content-Length header in requests if the
+ * body length has changed, although Burp-provided insertion points will
+ * always do this and will return a request with a valid Content-Length
+ * header.
+ * Note:
+ * Scan checks should submit raw non-encoded payloads to insertion points,
+ * and the insertion point has responsibility for performing any data
+ * encoding that is necessary given the nature and location of the insertion
+ * point.
+ *
+ * @param payload The payload that should be placed into the insertion
+ * point.
+ *
+ * @return The resulting request.
+ */
+ HttpRequest buildHttpRequestWithPayload(ByteArray payload);
+
+ /**
+ * Determine the offsets of the payload value within
+ * the request, when it is placed into the insertion point. Scan checks may
+ * invoke this method when reporting issues, so as to highlight the
+ * relevant part of the request within the UI.
+ *
+ * @param payload The payload that should be placed into the insertion
+ * point.
+ *
+ * @return A list of {@link Range} objects containing the start and end
+ * offsets of the payload within the request, or an empty list if this is
+ * not applicable (for example, where the insertion point places a payload
+ * into a serialized data structure, the raw payload may not literally
+ * appear anywhere within the resulting request).
+ */
+ List issueHighlights(ByteArray payload);
+
+ /**
+ * Type of this insertion point.
+ *
+ * @return The {@link AuditInsertionPointType} for this insertion point.
+ */
+ default AuditInsertionPointType type()
+ {
+ return AuditInsertionPointType.EXTENSION_PROVIDED;
+ }
+
+ /**
+ * This method can be used to create an audit insertion point based on offsets.
+ *
+ * @param name The name of the audit insertion point.
+ * @param baseRequest The base {@link HttpRequest}.
+ * @param startIndexInclusive The start index inclusive.
+ * @param endIndexExclusive The end index exclusive.
+ *
+ * @return The {@link AuditInsertionPoint} based on offsets.
+ */
+ static AuditInsertionPoint auditInsertionPoint(String name, HttpRequest baseRequest, int startIndexInclusive, int endIndexExclusive)
+ {
+ return FACTORY.auditInsertionPoint(name, baseRequest, startIndexInclusive, endIndexExclusive);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointProvider.java b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointProvider.java
new file mode 100644
index 0000000..439cdce
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.insertionpoint;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.scanner.Scanner;
+
+import java.util.List;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Scanner#registerInsertionPointProvider(AuditInsertionPointProvider)}
+ * to register a provider for custom audit insertion points.
+ */
+public interface AuditInsertionPointProvider
+{
+ /**
+ * The Scanner invokes this method when a request is actively audited. The
+ * provider should provide a list of custom insertion points that
+ * will be used in the audit. Note: these insertion points are used
+ * in addition to those that are derived from Burp Scanner's configuration,
+ * and those provided by any other Burp extensions.
+ *
+ * @param baseHttpRequestResponse The base {@link HttpRequestResponse} that
+ * will be actively audited.
+ *
+ * @return A list of {@link AuditInsertionPoint} objects
+ * that should be used in the audit, or {@code null} if no custom insertion
+ * points are applicable for this request.
+ */
+ List provideInsertionPoints(HttpRequestResponse baseHttpRequestResponse);
+}
diff --git a/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointType.java b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointType.java
new file mode 100644
index 0000000..2db2c3c
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/insertionpoint/AuditInsertionPointType.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.insertionpoint;
+
+/**
+ * This enum represents the audit insertion point type.
+ */
+public enum AuditInsertionPointType
+{
+ PARAM_URL,
+ PARAM_BODY,
+ PARAM_COOKIE,
+ PARAM_XML,
+ PARAM_XML_ATTR,
+ PARAM_MULTIPART_ATTR,
+ PARAM_JSON,
+ PARAM_AMF,
+ HEADER,
+ PARAM_NAME_URL,
+ PARAM_NAME_BODY,
+ ENTIRE_BODY,
+ URL_PATH_FILENAME,
+ URL_PATH_FOLDER,
+ USER_PROVIDED,
+ EXTENSION_PROVIDED,
+ UNKNOWN
+}
diff --git a/src/burp/api/montoya/scanner/audit/issues/AuditIssue.java b/src/burp/api/montoya/scanner/audit/issues/AuditIssue.java
new file mode 100644
index 0000000..2bf3958
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/issues/AuditIssue.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.issues;
+
+import burp.api.montoya.collaborator.Interaction;
+import burp.api.montoya.http.HttpService;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.scanner.ScanCheck;
+import burp.api.montoya.scanner.audit.AuditIssueHandler;
+import burp.api.montoya.sitemap.SiteMap;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This interface is used to retrieve details of audit issues. Extensions can
+ * obtain details of issues by registering an {@link AuditIssueHandler}.
+ * Extensions can also add custom audit issues by registering an
+ * {@link ScanCheck} or calling {@link SiteMap#add(AuditIssue)},
+ * and providing their own implementations of this interface. Note that issue
+ * descriptions and other text generated by extensions are subject to an HTML
+ * whitelist that allows only formatting tags and simple hyperlinks.
+ */
+public interface AuditIssue
+{
+ /**
+ * Name of this issue type.
+ *
+ * @return The name of this issue type (e.g. "SQL injection").
+ */
+ String name();
+
+ /**
+ * This method returns detailed information about this specific instance of
+ * the issue.
+ *
+ * @return Detailed information about this specific instance of the issue,
+ * or {@code null} if none applies. A limited set of HTML tags may be used.
+ */
+ String detail();
+
+ /**
+ * This method returns detailed information about the remediation for this
+ * specific instance of the issue.
+ *
+ * @return Detailed information about the remediation for this specific
+ * instance of the issue, or {@code null} if none applies. A limited set of
+ * HTML tags may be used.
+ */
+ String remediation();
+
+ /**
+ * HTTP service for which the issue was generated.
+ *
+ * @return The HTTP service for which the issue was generated.
+ */
+ HttpService httpService();
+
+ /**
+ * Base URL for which this issue was generated.
+ *
+ * @return The base URL for which this issue was generated.
+ */
+ String baseUrl();
+
+ /**
+ * Issue severity level.
+ *
+ * @return The {@link AuditIssueSeverity} level.
+ */
+ AuditIssueSeverity severity();
+
+ /**
+ * Issue confidence level.
+ *
+ * @return The {@link AuditIssueConfidence} level.
+ */
+ AuditIssueConfidence confidence();
+
+ /**
+ * HTTP request/response messages that caused the issue to be generated.
+ *
+ * @return The list of {@link HttpRequestResponse} objects on the basis of
+ * which the issue was generated.
+ */
+ List requestResponses();
+
+ /**
+ * Collaborator interactions that caused the issue to be generated.
+ *
+ * @return The list of Burp Collaborator {@link Interaction} objects that caused the issue to be generated.
+ * If there are no interactions, this will be empty.
+ */
+ List collaboratorInteractions();
+
+ /**
+ * Definition for this issue.
+ *
+ * @return The {@link AuditIssueDefinition} for this issue.
+ */
+ AuditIssueDefinition definition();
+
+ /**
+ * This method can be used to create a default implementation of an audit
+ * issue for a URL.
+ *
+ * @param name The name of the issue type.
+ * @param detail The detailed information about the issue.
+ * @param remediation The detailed information about the remediation for
+ * the issue.
+ * @param baseUrl The base URL for which the issue is generated.
+ * @param severity The {@link AuditIssueSeverity} level.
+ * @param confidence The {@link AuditIssueConfidence} level.
+ * @param background The background description for the type of issue.
+ * @param remediationBackground The background description of the
+ * remediation for this type of issue.
+ * @param typicalSeverity The typical {@link AuditIssueSeverity} level.
+ * @param requestResponses The {@link HttpRequestResponse} objects on the
+ * basis of which the issue is generated.
+ *
+ * @return The audit issue for the URL.
+ */
+ static AuditIssue auditIssue(
+ String name,
+ String detail,
+ String remediation,
+ String baseUrl,
+ AuditIssueSeverity severity,
+ AuditIssueConfidence confidence,
+ String background,
+ String remediationBackground,
+ AuditIssueSeverity typicalSeverity,
+ HttpRequestResponse... requestResponses)
+ {
+ return FACTORY.auditIssue(name, detail, remediation, baseUrl, severity, confidence, background, remediationBackground, typicalSeverity, requestResponses);
+ }
+
+ /**
+ * This method can be used to create a default implementation of an audit
+ * issue for a URL.
+ *
+ * @param name The name of the issue type.
+ * @param detail The detailed information about the issue.
+ * @param remediation The detailed information about the remediation for
+ * the issue.
+ * @param baseUrl The base URL for which the issue is generated.
+ * @param severity The {@link AuditIssueSeverity} level.
+ * @param confidence The {@link AuditIssueConfidence} level.
+ * @param background The background description for the type of issue.
+ * @param remediationBackground The background description of the
+ * remediation for this type of issue.
+ * @param typicalSeverity The typical {@link AuditIssueSeverity} level.
+ * @param requestResponses The list of {@link HttpRequestResponse} objects
+ * on the basis of which the issue is generated.
+ *
+ * @return The audit issue for the URL.
+ */
+ static AuditIssue auditIssue(
+ String name,
+ String detail,
+ String remediation,
+ String baseUrl,
+ AuditIssueSeverity severity,
+ AuditIssueConfidence confidence,
+ String background,
+ String remediationBackground,
+ AuditIssueSeverity typicalSeverity,
+ List requestResponses)
+ {
+ return FACTORY.auditIssue(name, detail, remediation, baseUrl, severity, confidence, background, remediationBackground, typicalSeverity, requestResponses);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/audit/issues/AuditIssueConfidence.java b/src/burp/api/montoya/scanner/audit/issues/AuditIssueConfidence.java
new file mode 100644
index 0000000..d1486c6
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/issues/AuditIssueConfidence.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.issues;
+
+/**
+ * This enum represents the confidence level of an audit issue.
+ */
+public enum AuditIssueConfidence
+{
+ CERTAIN,
+ FIRM,
+ TENTATIVE
+}
diff --git a/src/burp/api/montoya/scanner/audit/issues/AuditIssueDefinition.java b/src/burp/api/montoya/scanner/audit/issues/AuditIssueDefinition.java
new file mode 100644
index 0000000..d3e3c37
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/issues/AuditIssueDefinition.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.issues;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This interface is used to retrieve background information about audit
+ * issues. Note that text generated by extensions is subject to an HTML
+ * whitelist that allows only formatting tags and simple hyperlinks.
+ */
+public interface AuditIssueDefinition
+{
+
+ /**
+ * Name of this issue type.
+ *
+ * @return The name of this issue type (e.g. "SQL injection").
+ */
+ String name();
+
+ /**
+ * This method returns a background description for this issue type.
+ *
+ * @return A background description for this type of issue, or {@code null}
+ * if none applies. A limited set of HTML tags may be used.
+ */
+ String background();
+
+ /**
+ * This method returns a background description of the remediation for this
+ * type of issue.
+ *
+ * @return A background description of the remediation for this type of
+ * issue, or {@code null} if none applies. A limited set of HTML tags may
+ * be used.
+ */
+ String remediation();
+
+ /**
+ * Typical issue severity level.
+ *
+ * @return The typical {@link AuditIssueSeverity} level.
+ */
+ AuditIssueSeverity typicalSeverity();
+
+ /**
+ * This method returns an index of the issue type. See the Burp Scanner
+ * documentation for a listing of all the issue types.
+ *
+ * @return An index of the issue type.
+ */
+ int typeIndex();
+
+ /**
+ * This method can be used to create a default implementation of an audit
+ * issue definition.
+ *
+ * @param name The name of the issue type.
+ * @param background The background description for the type of issue.
+ * @param remediation The background description of the remediation for
+ * this type of issue.
+ * @param typicalSeverity The typical {@link AuditIssueSeverity} level.
+ *
+ * @return The audit issue definition.
+ */
+ static AuditIssueDefinition auditIssueDefinition(String name, String background, String remediation, AuditIssueSeverity typicalSeverity)
+ {
+ return FACTORY.auditIssueDefinition(name, background, remediation, typicalSeverity);
+ }
+}
diff --git a/src/burp/api/montoya/scanner/audit/issues/AuditIssueSeverity.java b/src/burp/api/montoya/scanner/audit/issues/AuditIssueSeverity.java
new file mode 100644
index 0000000..2940cd8
--- /dev/null
+++ b/src/burp/api/montoya/scanner/audit/issues/AuditIssueSeverity.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scanner.audit.issues;
+
+/**
+ * This enum represents the severity level of an audit issue.
+ */
+public enum AuditIssueSeverity
+{
+ HIGH,
+ MEDIUM,
+ LOW,
+ INFORMATION,
+ FALSE_POSITIVE
+}
diff --git a/src/burp/api/montoya/scanner/bchecks/BCheckImportResult.java b/src/burp/api/montoya/scanner/bchecks/BCheckImportResult.java
new file mode 100644
index 0000000..c65c364
--- /dev/null
+++ b/src/burp/api/montoya/scanner/bchecks/BCheckImportResult.java
@@ -0,0 +1,30 @@
+package burp.api.montoya.scanner.bchecks;
+
+import java.util.List;
+
+/**
+ * The result of importing a BCheck
+ */
+public interface BCheckImportResult
+{
+ /**
+ * The status of an imported BCheck
+ */
+ enum Status
+ {
+ LOADED_WITHOUT_ERRORS,
+ LOADED_WITH_ERRORS
+ }
+
+ /**
+ * The status of the BCheck after import
+ *
+ * @return the status
+ */
+ Status status();
+
+ /**
+ * @return a list of errors if the script was invalid or empty is the script was valid.
+ */
+ List importErrors();
+}
diff --git a/src/burp/api/montoya/scanner/bchecks/BChecks.java b/src/burp/api/montoya/scanner/bchecks/BChecks.java
new file mode 100644
index 0000000..e04b95f
--- /dev/null
+++ b/src/burp/api/montoya/scanner/bchecks/BChecks.java
@@ -0,0 +1,27 @@
+package burp.api.montoya.scanner.bchecks;
+
+/**
+ * Provides access to functionality related to BChecks.
+ */
+public interface BChecks
+{
+ /**
+ * This method can be used to import a BCheck. By default, these will be enabled if the
+ * script imports without errors.
+ *
+ * @param script the BCheck script to import
+ *
+ * @return The {@link BCheckImportResult} which contains the result of importing the BCheck.
+ */
+ BCheckImportResult importBCheck(String script);
+
+ /**
+ * This method can be used to import a BCheck.
+ *
+ * @param script the BCheck script to import
+ * @param enabled whether the script should be enabled after successful import
+ *
+ * @return The {@link BCheckImportResult} which contains the result of importing the BCheck.
+ */
+ BCheckImportResult importBCheck(String script, boolean enabled);
+}
diff --git a/src/burp/api/montoya/scope/Scope.java b/src/burp/api/montoya/scope/Scope.java
new file mode 100644
index 0000000..2615f8b
--- /dev/null
+++ b/src/burp/api/montoya/scope/Scope.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scope;
+
+import burp.api.montoya.core.Registration;
+
+/**
+ * Provides access to the functionality related to Burp's
+ * Suite-wide target scope.
+ */
+public interface Scope
+{
+ /**
+ * This method can be used to query whether a specified URL is within the
+ * current Suite-wide target scope.
+ *
+ * @param url The URL to query.
+ *
+ * @return Returns {@code true} if the URL is within the current Suite-wide
+ * target scope.
+ */
+ boolean isInScope(String url);
+
+ /**
+ * This method can be used to include the specified URL in the Suite-wide
+ * target scope.
+ *
+ * @param url The URL to include in the Suite-wide target scope.
+ */
+ void includeInScope(String url);
+
+ /**
+ * This method can be used to exclude the specified URL from the Suite-wide
+ * target scope.
+ *
+ * @param url The URL to exclude from the Suite-wide target scope.
+ */
+ void excludeFromScope(String url);
+
+ /**
+ * Register a handler which will be notified of
+ * changes to Burp's Suite-wide target scope.
+ *
+ * @param handler An object created by the extension that implements the
+ * {@link ScopeChangeHandler} interface.
+ *
+ * @return The {@link Registration} for the handler.
+ */
+ Registration registerScopeChangeHandler(ScopeChangeHandler handler);
+}
diff --git a/src/burp/api/montoya/scope/ScopeChange.java b/src/burp/api/montoya/scope/ScopeChange.java
new file mode 100644
index 0000000..97d10c4
--- /dev/null
+++ b/src/burp/api/montoya/scope/ScopeChange.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scope;
+
+/**
+ * Change to Burp's Suite-wide target scope.
+ */
+public interface ScopeChange
+{
+}
diff --git a/src/burp/api/montoya/scope/ScopeChangeHandler.java b/src/burp/api/montoya/scope/ScopeChangeHandler.java
new file mode 100644
index 0000000..ef21f34
--- /dev/null
+++ b/src/burp/api/montoya/scope/ScopeChangeHandler.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.scope;
+
+/**
+ * Extensions can implement this interface and then call
+ * {@link Scope#registerScopeChangeHandler(ScopeChangeHandler)} to register a scope change
+ * handler. The handler will be notified whenever a change occurs to Burp's
+ * Suite-wide target scope.
+ */
+public interface ScopeChangeHandler
+{
+ /**
+ * This method is invoked whenever a change occurs to Burp's Suite-wide
+ * target scope.
+ *
+ * @param scopeChange An object representing the change to Burp's
+ * Suite-wide target scope.
+ */
+ void scopeChanged(ScopeChange scopeChange);
+}
diff --git a/src/burp/api/montoya/sitemap/SiteMap.java b/src/burp/api/montoya/sitemap/SiteMap.java
new file mode 100644
index 0000000..6f81fc5
--- /dev/null
+++ b/src/burp/api/montoya/sitemap/SiteMap.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.sitemap;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.scanner.ScanCheck;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+import java.util.List;
+
+/**
+ * Provides methods for querying and modifying Burp's site map.
+ */
+public interface SiteMap
+{
+ /**
+ * This method filters out the site map according to the passed {@link SiteMapFilter}
+ * object and returns a list of matched {@link HttpRequestResponse} items.
+ *
+ * @param filter This parameter can be used to specify a filter, in order to extract a
+ * specific subset of the site map.
+ *
+ * @return A list of filtered items from the site map.
+ */
+ List requestResponses(SiteMapFilter filter);
+
+ /**
+ * This method returns details of all items in the site map.
+ *
+ * @return A list of all items from the site map.
+ */
+ List requestResponses();
+
+ /**
+ * This method returns current audit issues for URLs in the site map that are matched by the
+ * {@link SiteMapFilter} object.
+ *
+ * @param filter This parameter can be used to specify a filter, in order to extract issues
+ * for a specific subset of the site map.
+ *
+ * @return A filtered list of audit issues.
+ */
+ List issues(SiteMapFilter filter);
+
+ /**
+ * This method returns all the current audit issues for URLs in the site map.
+ *
+ * @return A list of audit issues.
+ */
+ List issues();
+
+ /**
+ * This method can be used to add an {@link HttpRequestResponse} item to Burp's site
+ * map with the specified request/response details. This will overwrite the details of any
+ * existing matching item in the site map.
+ *
+ * @param requestResponse Item to be added to the site map
+ */
+ void add(HttpRequestResponse requestResponse);
+
+ /**
+ * Register a new Audit issue. Note: Wherever possible, extensions
+ * should implement custom Scanner checks using {@link ScanCheck} and report issues
+ * via those checks, to integrate with Burp's user-driven workflow, and ensure proper
+ * consolidation of duplicate reported issues. This method is only designed for tasks
+ * outside the normal testing workflow, such as porting results from other scanning tools.
+ *
+ * @param auditIssue An object created by the extension that implements the
+ * {@link AuditIssue} interface.
+ */
+ void add(AuditIssue auditIssue);
+}
diff --git a/src/burp/api/montoya/sitemap/SiteMapFilter.java b/src/burp/api/montoya/sitemap/SiteMapFilter.java
new file mode 100644
index 0000000..b1f7d33
--- /dev/null
+++ b/src/burp/api/montoya/sitemap/SiteMapFilter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.sitemap;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * This interface is used to filter items when querying Burp's site map.
+ */
+public interface SiteMapFilter
+{
+ /**
+ * Invoked by Burp to check whether a given site map node matches the filter.
+ *
+ * @param node Site map node to match.
+ *
+ * @return Returns true if the site map node matches the filter.
+ */
+ boolean matches(SiteMapNode node);
+
+ /**
+ * This method returns a site map filter object that matches site map nodes with URLs
+ * starting with the specified prefix. Note that the prefix is case-sensitive.
+ *
+ * @param prefix Case-sensitive URL prefix used to match site tree nodes. If {@code null} is
+ * passed, the resulting filter will match all site map nodes.
+ *
+ * @return A site map filter object that matches nodes via a URL prefix
+ */
+ static SiteMapFilter prefixFilter(String prefix)
+ {
+ return FACTORY.prefixFilter(prefix);
+ }
+}
diff --git a/src/burp/api/montoya/sitemap/SiteMapNode.java b/src/burp/api/montoya/sitemap/SiteMapNode.java
new file mode 100644
index 0000000..a411c33
--- /dev/null
+++ b/src/burp/api/montoya/sitemap/SiteMapNode.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.sitemap;
+
+/**
+ * This interface is used to represent items in the Burp's site map.
+ */
+public interface SiteMapNode
+{
+ /**
+ * Retrieve the URL associated with the site map's node.
+ *
+ * @return The URL of the node.
+ */
+ String url();
+}
diff --git a/src/burp/api/montoya/ui/Selection.java b/src/burp/api/montoya/ui/Selection.java
new file mode 100644
index 0000000..576f95b
--- /dev/null
+++ b/src/burp/api/montoya/ui/Selection.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Range;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * Provides helpful information and functionality relating to a user's selection within the user interface.
+ */
+public interface Selection
+{
+ /**
+ * @return The contents that are derived from within the user's selection range.
+ */
+ ByteArray contents();
+
+ /**
+ * @return The positional data of where the user has selected.
+ */
+ Range offsets();
+
+ /**
+ * @param selectionContents The contents of the selection.
+ *
+ * @return A new instance of {@link Selection}
+ */
+ static Selection selection(ByteArray selectionContents)
+ {
+ return FACTORY.selection(selectionContents);
+ }
+
+ /**
+ * Create an instance of {@link Selection} without content data.
+ *
+ * @param startIndexInclusive The start position of the selection range.
+ * @param endIndexExclusive The end position of the selection range.
+ *
+ * @return A new instance of {@link Selection}
+ */
+ static Selection selection(int startIndexInclusive, int endIndexExclusive)
+ {
+ return FACTORY.selection(startIndexInclusive, endIndexExclusive);
+ }
+
+ /**
+ * Create an instance of {@link Selection}.
+ *
+ * @param selectionContents The contents of the selection.
+ * @param startIndexInclusive The start position of the selection range.
+ * @param endIndexExclusive The end position of the selection range.
+ *
+ * @return A new instance of {@link Selection}
+ */
+ static Selection selection(ByteArray selectionContents, int startIndexInclusive, int endIndexExclusive)
+ {
+ return FACTORY.selection(selectionContents, startIndexInclusive, endIndexExclusive);
+ }
+}
diff --git a/src/burp/api/montoya/ui/Theme.java b/src/burp/api/montoya/ui/Theme.java
new file mode 100644
index 0000000..7e40ccb
--- /dev/null
+++ b/src/burp/api/montoya/ui/Theme.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui;
+
+/**
+ * This enum contains the different themes available in Burp Suites user interface.
+ */
+public enum Theme
+{
+ DARK,
+ LIGHT
+}
diff --git a/src/burp/api/montoya/ui/UserInterface.java b/src/burp/api/montoya/ui/UserInterface.java
new file mode 100644
index 0000000..cfa8894
--- /dev/null
+++ b/src/burp/api/montoya/ui/UserInterface.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui;
+
+import burp.api.montoya.core.Registration;
+import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
+import burp.api.montoya.ui.editor.EditorOptions;
+import burp.api.montoya.ui.editor.HttpRequestEditor;
+import burp.api.montoya.ui.editor.HttpResponseEditor;
+import burp.api.montoya.ui.editor.RawEditor;
+import burp.api.montoya.ui.editor.WebSocketMessageEditor;
+import burp.api.montoya.ui.editor.extension.HttpRequestEditorProvider;
+import burp.api.montoya.ui.editor.extension.HttpResponseEditorProvider;
+import burp.api.montoya.ui.editor.extension.WebSocketMessageEditorProvider;
+import burp.api.montoya.ui.menu.MenuBar;
+import burp.api.montoya.ui.swing.SwingUtils;
+
+import java.awt.Component;
+import java.awt.Font;
+
+/**
+ * This interface gives you access to various user interface related features.
+ * Such as registering your own User Interface providers, creating instances of Burps various editors
+ * and applying themes to custom components.
+ */
+public interface UserInterface
+{
+ /**
+ * @return The Burp Suite {@link MenuBar}.
+ */
+ MenuBar menuBar();
+
+ /**
+ * Add a custom tab to the main Burp Suite window.
+ *
+ * @param title The text to be displayed in the tab heading.
+ * @param component The component that will be rendered within the custom tab.
+ *
+ * @return A {@link Registration} of the custom suite tab.
+ */
+ Registration registerSuiteTab(String title, Component component);
+
+ /**
+ * This method can be used to register a provider of custom context menu items.
+ *
+ * @param provider The provider to register.
+ *
+ * @return A {@link Registration} of the context menu item provider.
+ */
+ Registration registerContextMenuItemsProvider(ContextMenuItemsProvider provider);
+
+ /**
+ * This method can be used to register a provider of custom HTTP request editors.
+ *
+ * @param provider The provider to register.
+ *
+ * @return A {@link Registration} of the HTTP request editor provider.
+ */
+ Registration registerHttpRequestEditorProvider(HttpRequestEditorProvider provider);
+
+ /**
+ * This method can be used to register a provider of custom HTTP response editors.
+ *
+ * @param provider The provider to register.
+ *
+ * @return A {@link Registration} of the HTTP response editor provider.
+ */
+ Registration registerHttpResponseEditorProvider(HttpResponseEditorProvider provider);
+
+ /**
+ * This method can be used to register a provider of custom Web Socket message editors.
+ *
+ * @param provider The provider to register.
+ *
+ * @return A {@link Registration} of the Web Socket message editor provider.
+ */
+ Registration registerWebSocketMessageEditorProvider(WebSocketMessageEditorProvider provider);
+
+ /**
+ * Create a new instance of Burp's plain text editor, for the extension to use in its own UI.
+ *
+ * @param options Optional options to apply to the editor.
+ *
+ * @return An instance of the {@link RawEditor} interface.
+ */
+ RawEditor createRawEditor(EditorOptions... options);
+
+ /**
+ * Create a new instance of Burp's WebSocket message editor, for the extension to use in its own UI.
+ *
+ * @param options Optional options to apply to the editor.
+ *
+ * @return An instance of the {@link WebSocketMessageEditor} interface.
+ */
+ WebSocketMessageEditor createWebSocketMessageEditor(EditorOptions... options);
+
+ /**
+ * Create a new instance of Burp's HTTP request editor, for the extension to use in its own UI.
+ *
+ * @param options Optional options to apply to the editor.
+ *
+ * @return An instance of the {@link HttpRequestEditor} interface.
+ */
+ HttpRequestEditor createHttpRequestEditor(EditorOptions... options);
+
+ /**
+ * Create a new instance of Burp's HTTP response editor, for the extension to use in its own UI.
+ *
+ * @param options Optional options to apply to the editor.
+ *
+ * @return An instance of the {@link HttpResponseEditor} interface.
+ */
+ HttpResponseEditor createHttpResponseEditor(EditorOptions... options);
+
+ /**
+ * Customize UI components in line with Burp's UI style, including font size, colors, table line spacing, etc.
+ * The action is performed recursively on any child components of the passed-in component.
+ *
+ * @param component The component to be customized.
+ */
+ void applyThemeToComponent(Component component);
+
+ /**
+ * Identify the theme currently being used.
+ *
+ * @return The current {@link Theme}
+ */
+ Theme currentTheme();
+
+ /**
+ * Access the message editor's font type and size.
+ *
+ * @return The current {@link java.awt.Font}, as specified in the Settings dialog under the HTTP message display setting.
+ */
+ Font currentEditorFont();
+
+ /**
+ * Access Burp's font size.
+ *
+ * @return The current {@link java.awt.Font}, as specified in the Settings dialog under the Appearance setting.
+ */
+ Font currentDisplayFont();
+
+ /**
+ * @return An instance of {@link SwingUtils}
+ */
+ SwingUtils swingUtils();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/AuditIssueContextMenuEvent.java b/src/burp/api/montoya/ui/contextmenu/AuditIssueContextMenuEvent.java
new file mode 100644
index 0000000..eda9841
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/AuditIssueContextMenuEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.ToolSource;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+import java.util.List;
+
+public interface AuditIssueContextMenuEvent extends ComponentEvent, ToolSource, InvocationSource
+{
+ /**
+ * This method can be used to retrieve details of the Scanner audit issues that were selected by the user when the context menu was invoked.
+ * This will return an empty list if no issues are applicable to the invocation.
+ *
+ * @return a List of {@link AuditIssue} objects representing the items that were shown or selected by the user when the context menu was invoked.
+ */
+ List selectedIssues();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/ComponentEvent.java b/src/burp/api/montoya/ui/contextmenu/ComponentEvent.java
new file mode 100644
index 0000000..59cefd1
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/ComponentEvent.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import java.awt.event.InputEvent;
+
+/**
+ * This interface describes an action or event that has occurred with a user interface component.
+ */
+public interface ComponentEvent
+{
+ /**
+ * This method can be used to retrieve the native Java input event that was
+ * the trigger for the context menu invocation.
+ *
+ * @return The {@link InputEvent} that was the trigger for the context menu invocation.
+ */
+ InputEvent inputEvent();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/ContextMenuEvent.java b/src/burp/api/montoya/ui/contextmenu/ContextMenuEvent.java
new file mode 100644
index 0000000..10b448f
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/ContextMenuEvent.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.ToolSource;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.scanner.audit.issues.AuditIssue;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Provides useful information when generating context menu items from a {@link ContextMenuItemsProvider}.
+ */
+public interface ContextMenuEvent extends ComponentEvent, ToolSource, InvocationSource
+{
+ /**
+ * This method can be used to retrieve details of the currently selected HTTP request/response when the context menu was invoked.
+ *
+ * @return an {@link Optional} describing the currently selected request response with selection metadata.
+ */
+ Optional messageEditorRequestResponse();
+
+ /**
+ * This method can be used to retrieve details of the currently selected HTTP request/response pair that was
+ * selected by the user when the context menu was invoked. This will return an empty list if the user has not made a selection.
+ *
+ * @return A list of request responses that have been selected by the user.
+ */
+ List selectedRequestResponses();
+
+ /**
+ * This method can be used to retrieve details of the Scanner issues that were selected by the user when the context menu was invoked.
+ * This will return an empty list if no issues are applicable to the invocation.
+ *
+ * @return a List of {@link AuditIssue} objects representing the items that were shown or selected by the user when the context menu was invoked.
+ * @deprecated Use {@link ContextMenuItemsProvider#provideMenuItems(AuditIssueContextMenuEvent)} instead.
+ */
+ @Deprecated
+ List selectedIssues();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/ContextMenuItemsProvider.java b/src/burp/api/montoya/ui/contextmenu/ContextMenuItemsProvider.java
new file mode 100644
index 0000000..8842751
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/ContextMenuItemsProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import java.awt.Component;
+import java.util.List;
+
+import static java.util.Collections.emptyList;
+
+/**
+ * This interface allows extensions to implement and register a provider for custom context menu items.
+ */
+public interface ContextMenuItemsProvider
+{
+ /**
+ * Invoked by Burp Suite when the user requests a context menu with HTTP request/response information in the user interface.
+ * Extensions should return {@code null} or {@link java.util.Collections#emptyList()} from this method, to indicate that no menu items are required.
+ *
+ * @param event This object can be queried to find out about HTTP request/responses that are associated with the context menu invocation.
+ *
+ * @return A list of custom menu items (which may include sub-menus, checkbox menu items, etc.) that should be displayed.
+ */
+ default List provideMenuItems(ContextMenuEvent event)
+ {
+ return emptyList();
+ }
+
+ /**
+ * Invoked by Burp Suite when the user requests a context menu with WebSocket information in the user interface.
+ * Extensions should return {@code null} or {@link java.util.Collections#emptyList()} from this method, to indicate that no menu items are required.
+ *
+ * @param event This object can be queried to find out about WebSocket messages that are associated with the context menu invocation.
+ *
+ * @return A list of custom menu items (which may include sub-menus, checkbox menu items, etc.) that should be displayed.
+ */
+ default List provideMenuItems(WebSocketContextMenuEvent event)
+ {
+ return emptyList();
+ }
+
+ /**
+ * Invoked by Burp Suite when the user requests a context menu with audit issue information in the user interface.
+ * Extensions should return {@code null} or {@link java.util.Collections#emptyList()} from this method, to indicate that no menu items are required.
+ *
+ * @param event This object can be queried to find out about audit issues that are associated with the context menu invocation.
+ *
+ * @return A list of custom menu items (which may include sub-menus, checkbox menu items, etc.) that should be displayed.
+ */
+ default List provideMenuItems(AuditIssueContextMenuEvent event)
+ {
+ return emptyList();
+ }
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/InvocationSource.java b/src/burp/api/montoya/ui/contextmenu/InvocationSource.java
new file mode 100644
index 0000000..1e233ab
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/InvocationSource.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+/**
+ * Provides information about the source from which a context menu was invoked.
+ */
+public interface InvocationSource
+{
+ /**
+ * @return An instance of {@link InvocationType} which provides the current location of the context menu being invoked.
+ */
+ InvocationType invocationType();
+
+ /**
+ * A helper method to allow the extension to ask if the context is within a set of locations.
+ *
+ * @param invocationType One or more instances of {@link InvocationType} to check.
+ *
+ * @return True if the context menu is being invoked from one of the types that is being checked.
+ */
+ boolean isFrom(InvocationType... invocationType);
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/InvocationType.java b/src/burp/api/montoya/ui/contextmenu/InvocationType.java
new file mode 100644
index 0000000..8aaa19a
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/InvocationType.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+/**
+ * An enum containing different types of context menu invocations.
+ */
+public enum InvocationType
+{
+ MESSAGE_EDITOR_REQUEST,
+ MESSAGE_EDITOR_RESPONSE,
+ MESSAGE_VIEWER_REQUEST,
+ MESSAGE_VIEWER_RESPONSE,
+ SITE_MAP_TREE,
+ SITE_MAP_TABLE,
+ PROXY_HISTORY,
+ SCANNER_RESULTS,
+ INTRUDER_PAYLOAD_POSITIONS,
+ INTRUDER_ATTACK_RESULTS,
+ SEARCH_RESULTS;
+
+ /**
+ * @return A helper method to ask if this type contains HTTP messages.
+ */
+ public boolean containsHttpMessage()
+ {
+ switch (this)
+ {
+ case MESSAGE_EDITOR_REQUEST:
+ case MESSAGE_EDITOR_RESPONSE:
+ case MESSAGE_VIEWER_REQUEST:
+ case MESSAGE_VIEWER_RESPONSE:
+ case INTRUDER_PAYLOAD_POSITIONS:
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return A helper method to ask if this type contains HTTP request/responses.
+ */
+ public boolean containsHttpRequestResponses()
+ {
+ switch (this)
+ {
+ case SITE_MAP_TREE:
+ case SITE_MAP_TABLE:
+ case PROXY_HISTORY:
+ case INTRUDER_ATTACK_RESULTS:
+ case SEARCH_RESULTS:
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @return A helper method to ask if this type contains any scan issues.
+ */
+ public boolean containsScanIssues()
+ {
+ return this == SCANNER_RESULTS;
+ }
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/MessageEditorHttpRequestResponse.java b/src/burp/api/montoya/ui/contextmenu/MessageEditorHttpRequestResponse.java
new file mode 100644
index 0000000..a2abc35
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/MessageEditorHttpRequestResponse.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.Range;
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.http.message.responses.HttpResponse;
+
+import java.util.Optional;
+
+/**
+ * This class contains information about a user selection of a request or response within a Burp Suite message editor.
+ */
+public interface MessageEditorHttpRequestResponse
+{
+ /**
+ * @return An {@link SelectionContext} which indicates what data has been selected by the user and has focus.
+ */
+ SelectionContext selectionContext();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} range of indices that indicates the position of the users current selection.
+ */
+ Optional selectionOffsets();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ int caretPosition();
+
+ /**
+ * @return An instance of {@link HttpRequestResponse} which contains the information about the currently displayed or selected HTTP request/response.
+ */
+ HttpRequestResponse requestResponse();
+
+ /**
+ * Update the message editor with the HTTP request
+ *
+ * @param request the request to update the editor.
+ */
+ void setRequest(HttpRequest request);
+
+ /**
+ * Update the message editor with the HTTP response
+ *
+ * @param response the response to update the editor.
+ */
+ void setResponse(HttpResponse response);
+
+
+ enum SelectionContext
+ {
+ REQUEST,
+ RESPONSE
+ }
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/WebSocketContextMenuEvent.java b/src/burp/api/montoya/ui/contextmenu/WebSocketContextMenuEvent.java
new file mode 100644
index 0000000..15215d5
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/WebSocketContextMenuEvent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.ToolSource;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface WebSocketContextMenuEvent extends ComponentEvent, ToolSource
+{
+ /**
+ * This method can be used to retrieve details of the currently selected WebSocket message when the context menu was invoked from an editor.
+ *
+ * @return an {@link Optional} describing the currently selected WebSocket message with selection metadata.
+ */
+ Optional messageEditorWebSocket();
+
+ /**
+ * This method can be used to retrieve details of the currently selected WebSocket messages that are
+ * selected by the user when the context menu was invoked. This will return an empty list if the user has not made a selection.
+ *
+ * @return A list of WebSocket messages that have been selected by the user.
+ */
+ List selectedWebSocketMessages();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/WebSocketEditorEvent.java b/src/burp/api/montoya/ui/contextmenu/WebSocketEditorEvent.java
new file mode 100644
index 0000000..11eacab
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/WebSocketEditorEvent.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.core.Range;
+import burp.api.montoya.core.ToolSource;
+
+import java.util.Optional;
+
+public interface WebSocketEditorEvent extends ComponentEvent, ToolSource
+{
+ /**
+ * @return The contents of the message editor.
+ */
+ ByteArray getContents();
+
+ /**
+ * This method can be used to set the content within the message editor programmatically.
+ * If the editor is read only the contents will not be updated.
+ *
+ * @param contents The content to set in the message editor.
+ */
+ void setContents(ByteArray contents);
+
+ /**
+ * @return the WebSocket message used to populate the editor.
+ */
+ WebSocketMessage webSocketMessage();
+
+ /**
+ * @return if the editor is read only.
+ */
+ boolean isReadOnly();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} range of indices that indicates the position of the users current selection.
+ */
+ Optional selectionOffsets();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ int caretPosition();
+}
diff --git a/src/burp/api/montoya/ui/contextmenu/WebSocketMessage.java b/src/burp/api/montoya/ui/contextmenu/WebSocketMessage.java
new file mode 100644
index 0000000..b398ae9
--- /dev/null
+++ b/src/burp/api/montoya/ui/contextmenu/WebSocketMessage.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.contextmenu;
+
+import burp.api.montoya.core.Annotations;
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.websocket.Direction;
+
+public interface WebSocketMessage
+{
+ /**
+ * This method retrieves the annotations for the message.
+ *
+ * @return The {@link Annotations} for the message.
+ */
+ Annotations annotations();
+
+ /**
+ * @return The direction of the message.
+ */
+ Direction direction();
+
+ /**
+ * @return WebSocket payload.
+ */
+ ByteArray payload();
+
+ /**
+ * @return The {@link HttpRequest} used to create the WebSocket.
+ */
+ HttpRequest upgradeRequest();
+}
diff --git a/src/burp/api/montoya/ui/editor/Editor.java b/src/burp/api/montoya/ui/editor/Editor.java
new file mode 100644
index 0000000..8e68b58
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/Editor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+import java.util.Optional;
+
+/**
+ * Provides the shared behaviour between the different editor types.
+ */
+public interface Editor
+{
+ /**
+ * Update the search expression that is shown in the search bar below the editor.
+ *
+ * @param expression The search expression.
+ */
+ void setSearchExpression(String expression);
+
+ /**
+ * @return True if the user has modified the contents of the editor since the last time the content was set programmatically.
+ */
+ boolean isModified();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ int caretPosition();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} containing the users current selection in the editor.
+ */
+ Optional selection();
+
+ /**
+ * @return UI component of the editor, for extensions to add to their own UI.
+ */
+ Component uiComponent();
+}
diff --git a/src/burp/api/montoya/ui/editor/EditorOptions.java b/src/burp/api/montoya/ui/editor/EditorOptions.java
new file mode 100644
index 0000000..d104f34
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/EditorOptions.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+/**
+ * These options allow you to configure additional behaviour to {@link Editor} implementations.
+ */
+public enum EditorOptions
+{
+ READ_ONLY
+}
diff --git a/src/burp/api/montoya/ui/editor/HttpRequestEditor.java b/src/burp/api/montoya/ui/editor/HttpRequestEditor.java
new file mode 100644
index 0000000..0016efc
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/HttpRequestEditor.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+import java.util.Optional;
+
+/**
+ * Provides extensions with an instance of Burp Suites HTTP request editor to use in their own user interface.
+ */
+public interface HttpRequestEditor extends Editor
+{
+ /**
+ * @return an instance of {@link HttpRequest} derived from the contents of the editor.
+ */
+ HttpRequest getRequest();
+
+ /**
+ * Display the contents of an HTTP request in the editor.
+ *
+ * @param request The HTTP request to be set.
+ */
+ void setRequest(HttpRequest request);
+
+ /**
+ * Update the search expression that is shown in the search bar below the editor.
+ *
+ * @param expression The search expression.
+ */
+ @Override
+ void setSearchExpression(String expression);
+
+ /**
+ * @return True if the user has modified the contents of the editor since the last time the content was set programmatically.
+ */
+ @Override
+ boolean isModified();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ @Override
+ int caretPosition();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} containing the users current selection in the editor.
+ */
+ @Override
+ Optional selection();
+
+ /**
+ * @return UI component of the editor, for extensions to add to their own UI.
+ */
+ @Override
+ Component uiComponent();
+}
diff --git a/src/burp/api/montoya/ui/editor/HttpResponseEditor.java b/src/burp/api/montoya/ui/editor/HttpResponseEditor.java
new file mode 100644
index 0000000..5a98eac
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/HttpResponseEditor.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+import java.util.Optional;
+
+/**
+ * Provides extensions with an instance of Burp Suites HTTP response editor to use in their own user interface.
+ */
+public interface HttpResponseEditor extends Editor
+{
+ /**
+ * @return an instance of {@link HttpResponse} derived from the contents of the editor.
+ */
+ HttpResponse getResponse();
+
+ /**
+ * Display the contents of an HTTP response in the editor.
+ *
+ * @param response The HTTP response to be set.
+ */
+ void setResponse(HttpResponse response);
+
+ /**
+ * Update the search expression that is shown in the search bar below the editor.
+ *
+ * @param expression The search expression.
+ */
+ @Override
+ void setSearchExpression(String expression);
+
+ /**
+ * @return True if the user has modified the contents of the editor since the last time the content was set programmatically.
+ */
+ @Override
+ boolean isModified();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ @Override
+ int caretPosition();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} containing the users current selection in the editor.
+ */
+ @Override
+ Optional selection();
+
+ /**
+ * @return UI component of the editor, for extensions to add to their own UI.
+ */
+ @Override
+ Component uiComponent();
+}
diff --git a/src/burp/api/montoya/ui/editor/RawEditor.java b/src/burp/api/montoya/ui/editor/RawEditor.java
new file mode 100644
index 0000000..e79b7b7
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/RawEditor.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+import java.util.Optional;
+
+/**
+ * Provides extensions with an instance of Burp Suite's HTTP text editor to use in their own user interface.
+ */
+public interface RawEditor extends Editor
+{
+ /**
+ * @param editable Boolean flag to toggle if this text editor is editable or not.
+ */
+ void setEditable(boolean editable);
+
+ /**
+ * @return The contents of the text editor.
+ */
+ ByteArray getContents();
+
+ /**
+ * This method can be used to set content within the text editor programmatically
+ *
+ * @param contents The content to set in the text editor.
+ */
+ void setContents(ByteArray contents);
+
+ /**
+ * Update the search expression that is shown in the search bar below the editor.
+ *
+ * @param expression The search expression.
+ */
+ @Override
+ void setSearchExpression(String expression);
+
+ /**
+ * @return True if the user has modified the contents of the editor since the last time the content was set programmatically.
+ */
+ @Override
+ boolean isModified();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ @Override
+ int caretPosition();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} containing the users current selection in the editor.
+ */
+ @Override
+ Optional selection();
+
+ /**
+ * @return UI component of the editor, for extensions to add to their own UI.
+ */
+ @Override
+ Component uiComponent();
+}
diff --git a/src/burp/api/montoya/ui/editor/WebSocketMessageEditor.java b/src/burp/api/montoya/ui/editor/WebSocketMessageEditor.java
new file mode 100644
index 0000000..1013c40
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/WebSocketMessageEditor.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+import java.util.Optional;
+
+/**
+ * Provides extensions with an instance of Burp Suite's WebSocket message editor to use in their own user interface.
+ */
+public interface WebSocketMessageEditor extends Editor
+{
+ /**
+ * @return The contents of the message editor.
+ */
+ ByteArray getContents();
+
+ /**
+ * This method can be used to set content within the message editor programmatically
+ *
+ * @param contents The content to set in the message editor.
+ */
+ void setContents(ByteArray contents);
+
+ /**
+ * Update the search expression that is shown in the search bar below the editor.
+ *
+ * @param expression The search expression.
+ */
+ @Override
+ void setSearchExpression(String expression);
+
+ /**
+ * @return True if the user has modified the contents of the editor since the last time the content was set programmatically.
+ */
+ @Override
+ boolean isModified();
+
+ /**
+ * @return The index of the position for the carat within the current message editor.
+ */
+ @Override
+ int caretPosition();
+
+ /**
+ * This will return {@link Optional#empty()} if the user has not made a selection.
+ *
+ * @return An {@link Optional} containing the users current selection in the editor.
+ */
+ @Override
+ Optional selection();
+
+ /**
+ * @return UI component of the editor, for extensions to add to their own UI.
+ */
+ @Override
+ Component uiComponent();
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/EditorCreationContext.java b/src/burp/api/montoya/ui/editor/extension/EditorCreationContext.java
new file mode 100644
index 0000000..56c5498
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/EditorCreationContext.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+import burp.api.montoya.core.ToolSource;
+
+/**
+ * This interface is used by an
+ * ExtensionHttpRequestEditor
or ExtensionHttpResponseEditor
to obtain
+ * details about the currently displayed message.
+ * Extensions that create instances of Burp's HTTP message editor can
+ * optionally provide an implementation of
+ * IMessageEditorController
, which the editor will invoke when it
+ * requires further information about the current message (for example, to send
+ * it to another Burp tool). Extensions that provide custom editor tabs via an
+ * IMessageEditorTabFactory
will receive a reference to an
+ * IMessageEditorController
object for each tab instance they
+ * generate, which the tab can invoke if it requires further information about
+ * the current message.
+ */
+public interface EditorCreationContext
+{
+ /**
+ * Indicates which Burp tool is requesting the editor.
+ *
+ * @return The tool requesting an editor
+ */
+ ToolSource toolSource();
+
+ /**
+ * Indicates which modes the Burp tool requests of the editor.
+ * e.g. Proxy expects a read only editor, Repeater expects the default editor.
+ *
+ * @return The mode required by the editor.
+ */
+ EditorMode editorMode();
+}
\ No newline at end of file
diff --git a/src/burp/api/montoya/ui/editor/extension/EditorMode.java b/src/burp/api/montoya/ui/editor/extension/EditorMode.java
new file mode 100644
index 0000000..d84a31d
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/EditorMode.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+/**
+ * An enum to describe the different modes of Burp Suites message editor.
+ */
+public enum EditorMode
+{
+ DEFAULT,
+ READ_ONLY
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedEditor.java b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedEditor.java
new file mode 100644
index 0000000..82958d4
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedEditor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+
+/**
+ * Provides the shared behaviour between the different extension provided editor types.
+ */
+public interface ExtensionProvidedEditor
+{
+ /**
+ * Sets the provided {@link HttpRequestResponse} object within the editor component.
+ *
+ * @param requestResponse The request and response to set in the editor.
+ */
+ void setRequestResponse(HttpRequestResponse requestResponse);
+
+ /**
+ * A check to determine if the HTTP message editor is enabled for a specific {@link HttpRequestResponse}
+ *
+ * @param requestResponse The {@link HttpRequestResponse} to check.
+ *
+ * @return True if the HTTP message editor is enabled for the provided request and response.
+ */
+ boolean isEnabledFor(HttpRequestResponse requestResponse);
+
+ /**
+ * @return The caption located in the message editor tab header.
+ */
+ String caption();
+
+ /**
+ * @return The component that is rendered within the message editor tab.
+ */
+ Component uiComponent();
+
+ /**
+ * The method should return {@code null} if no data has been selected.
+ *
+ * @return The data that is currently selected by the user.
+ */
+ Selection selectedData();
+
+ /**
+ * @return True if the user has modified the current message within the editor.
+ */
+ boolean isModified();
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpRequestEditor.java b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpRequestEditor.java
new file mode 100644
index 0000000..7c4bff7
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpRequestEditor.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.requests.HttpRequest;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+
+/**
+ * Extensions that register an {@link HttpRequestEditorProvider} must return an instance of this interface.
+ * Burp will then use that instance to create custom tabs within its HTTP request editor.
+ */
+public interface ExtensionProvidedHttpRequestEditor extends ExtensionProvidedEditor
+{
+ /**
+ * @return An instance of {@link HttpRequest} derived from the content of the HTTP request editor.
+ */
+ HttpRequest getRequest();
+
+ /**
+ * Sets the provided {@link HttpRequestResponse} object within the editor component.
+ *
+ * @param requestResponse The request and response to set in the editor.
+ */
+ @Override
+ void setRequestResponse(HttpRequestResponse requestResponse);
+
+ /**
+ * A check to determine if the HTTP message editor is enabled for a specific {@link HttpRequestResponse}
+ *
+ * @param requestResponse The {@link HttpRequestResponse} to check.
+ *
+ * @return True if the HTTP message editor is enabled for the provided request and response.
+ */
+ @Override
+ boolean isEnabledFor(HttpRequestResponse requestResponse);
+
+ /**
+ * @return The caption located in the message editor tab header.
+ */
+ @Override
+ String caption();
+
+ /**
+ * @return The component that is rendered within the message editor tab.
+ */
+ @Override
+ Component uiComponent();
+
+ /**
+ * The method should return {@code null} if no data has been selected.
+ *
+ * @return The data that is currently selected by the user.
+ */
+ @Override
+ Selection selectedData();
+
+ /**
+ * @return True if the user has modified the current message within the editor.
+ */
+ @Override
+ boolean isModified();
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpResponseEditor.java b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpResponseEditor.java
new file mode 100644
index 0000000..56241bc
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedHttpResponseEditor.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+import burp.api.montoya.http.message.HttpRequestResponse;
+import burp.api.montoya.http.message.responses.HttpResponse;
+import burp.api.montoya.ui.Selection;
+
+import java.awt.Component;
+
+/**
+ * Extensions that register an {@link HttpResponseEditorProvider} must return an instance of this interface.
+ * Burp will then use that instance to create custom tabs within its HTTP response editor.
+ */
+public interface ExtensionProvidedHttpResponseEditor extends ExtensionProvidedEditor
+{
+ /**
+ * @return An instance of {@link HttpResponse} derived from the content of the HTTP response editor.
+ */
+ HttpResponse getResponse();
+
+ /**
+ * Sets the provided {@link HttpRequestResponse} object within the editor component.
+ *
+ * @param requestResponse The request and response to set in the editor.
+ */
+ @Override
+ void setRequestResponse(HttpRequestResponse requestResponse);
+
+ /**
+ * A check to determine if the HTTP message editor is enabled for a specific {@link HttpRequestResponse}
+ *
+ * @param requestResponse The {@link HttpRequestResponse} to check.
+ *
+ * @return True if the HTTP message editor is enabled for the provided request and response.
+ */
+ @Override
+ boolean isEnabledFor(HttpRequestResponse requestResponse);
+
+ /**
+ * @return The caption located in the message editor tab header.
+ */
+ @Override
+ String caption();
+
+ /**
+ * @return The component that is rendered within the message editor tab.
+ */
+ @Override
+ Component uiComponent();
+
+ /**
+ * The method should return {@code null} if no data has been selected.
+ *
+ * @return The data that is currently selected by the user.
+ */
+ @Override
+ Selection selectedData();
+
+ /**
+ * @return True if the user has modified the current message within the editor.
+ */
+ @Override
+ boolean isModified();
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedWebSocketMessageEditor.java b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedWebSocketMessageEditor.java
new file mode 100644
index 0000000..0198e1c
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/ExtensionProvidedWebSocketMessageEditor.java
@@ -0,0 +1,57 @@
+package burp.api.montoya.ui.editor.extension;
+
+import burp.api.montoya.core.ByteArray;
+import burp.api.montoya.ui.Selection;
+import burp.api.montoya.ui.contextmenu.WebSocketMessage;
+
+import java.awt.Component;
+
+/**
+ * Extensions that register an {@link WebSocketMessageEditorProvider} must return an instance of this interface.
+ * Burp will then use that instance to create custom tabs within its Web Socket message editor.
+ */
+public interface ExtensionProvidedWebSocketMessageEditor
+{
+ /**
+ * @return The current message set in the editor as an instance of {@link ByteArray}
+ */
+ ByteArray getMessage();
+
+ /**
+ * Sets the provided {@link WebSocketMessage} within the editor component.
+ *
+ * @param message The message to set in the editor.
+ */
+ void setMessage(WebSocketMessage message);
+
+ /**
+ * A check to determine if the Web Socket editor is enabled for a specific {@link WebSocketMessage} message
+ *
+ * @param message The {@link WebSocketMessage} to check.
+ *
+ * @return True if the Web Socket message editor is enabled for the provided message.
+ */
+ boolean isEnabledFor(WebSocketMessage message);
+
+ /**
+ * @return The caption located in the message editor tab header.
+ */
+ String caption();
+
+ /**
+ * @return The component that is rendered within the message editor tab.
+ */
+ Component uiComponent();
+
+ /**
+ * The method should return {@code null} if no data has been selected.
+ *
+ * @return The data that is currently selected by the user.
+ */
+ Selection selectedData();
+
+ /**
+ * @return True if the user has modified the current message within the editor.
+ */
+ boolean isModified();
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/HttpRequestEditorProvider.java b/src/burp/api/montoya/ui/editor/extension/HttpRequestEditorProvider.java
new file mode 100644
index 0000000..e9e0b53
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/HttpRequestEditorProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+/**
+ * Extensions can register an instance of this interface to provide custom HTTP request editors within Burp's user interface.
+ */
+public interface HttpRequestEditorProvider
+{
+ /**
+ * Invoked by Burp when a new HTTP request editor is required from the extension.
+ *
+ * @param creationContext details about the context that is requiring a request editor
+ *
+ * @return An instance of {@link ExtensionProvidedHttpRequestEditor}
+ */
+ ExtensionProvidedHttpRequestEditor provideHttpRequestEditor(EditorCreationContext creationContext);
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/HttpResponseEditorProvider.java b/src/burp/api/montoya/ui/editor/extension/HttpResponseEditorProvider.java
new file mode 100644
index 0000000..1ca887f
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/HttpResponseEditorProvider.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2022-2023. PortSwigger Ltd. All rights reserved.
+ *
+ * This code may be used to extend the functionality of Burp Suite Community Edition
+ * and Burp Suite Professional, provided that this usage does not violate the
+ * license terms for those products.
+ */
+
+package burp.api.montoya.ui.editor.extension;
+
+/**
+ * Extensions can register an instance of this interface to provide custom HTTP response editors within Burp's user interface.
+ */
+public interface HttpResponseEditorProvider
+{
+ /**
+ * Invoked by Burp when a new HTTP response editor is required from the extension.
+ *
+ * @param creationContext details about the context that is requiring a response editor
+ *
+ * @return An instance of {@link ExtensionProvidedHttpResponseEditor}
+ */
+ ExtensionProvidedHttpResponseEditor provideHttpResponseEditor(EditorCreationContext creationContext);
+}
diff --git a/src/burp/api/montoya/ui/editor/extension/WebSocketMessageEditorProvider.java b/src/burp/api/montoya/ui/editor/extension/WebSocketMessageEditorProvider.java
new file mode 100644
index 0000000..ca9a751
--- /dev/null
+++ b/src/burp/api/montoya/ui/editor/extension/WebSocketMessageEditorProvider.java
@@ -0,0 +1,16 @@
+package burp.api.montoya.ui.editor.extension;
+
+/**
+ * Extensions can register an instance of this interface to provide custom Web Socket message editors within Burp's user interface.
+ */
+public interface WebSocketMessageEditorProvider
+{
+ /**
+ * Invoked by Burp when a new Web Socket message editor is required from the extension.
+ *
+ * @param creationContext details about the context that is requiring a message editor
+ *
+ * @return An instance of {@link ExtensionProvidedWebSocketMessageEditor}
+ */
+ ExtensionProvidedWebSocketMessageEditor provideMessageEditor(EditorCreationContext creationContext);
+}
diff --git a/src/burp/api/montoya/ui/menu/BasicMenuItem.java b/src/burp/api/montoya/ui/menu/BasicMenuItem.java
new file mode 100644
index 0000000..29022ad
--- /dev/null
+++ b/src/burp/api/montoya/ui/menu/BasicMenuItem.java
@@ -0,0 +1,41 @@
+package burp.api.montoya.ui.menu;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+public interface BasicMenuItem extends MenuItem
+{
+ /**
+ * The action performed when the {@link BasicMenuItem} is clicked.
+ */
+ void action();
+
+ /**
+ * Create a copy of {@link BasicMenuItem} with a new {@link Runnable} action.
+ *
+ * @param action The new {@link Runnable} action.
+ *
+ * @return An updated copy of {@link BasicMenuItem}.
+ */
+ BasicMenuItem withAction(Runnable action);
+
+ /**
+ * Create a copy of {@link BasicMenuItem} with a new caption.
+ *
+ * @param caption The new caption.
+ *
+ * @return An updated copy of {@link BasicMenuItem}
+ */
+ BasicMenuItem withCaption(String caption);
+
+ /**
+ * Create a new instance of {@link BasicMenuItem} with a caption.
+ *
+ * @param caption The caption for the {@link BasicMenuItem}.
+ *
+ * @return A new instance of the {@link BasicMenuItem}.
+ */
+ static BasicMenuItem basicMenuItem(String caption)
+ {
+ return FACTORY.basicMenuItem(caption);
+ }
+}
diff --git a/src/burp/api/montoya/ui/menu/Menu.java b/src/burp/api/montoya/ui/menu/Menu.java
new file mode 100644
index 0000000..ae4e9aa
--- /dev/null
+++ b/src/burp/api/montoya/ui/menu/Menu.java
@@ -0,0 +1,64 @@
+package burp.api.montoya.ui.menu;
+
+import java.util.List;
+
+import static burp.api.montoya.internal.ObjectFactoryLocator.FACTORY;
+
+/**
+ * A menu to be displayed in the {@link MenuBar}.
+ */
+public interface Menu
+{
+ /**
+ * The caption to be displayed for the menu.
+ *
+ * @return The caption
+ */
+ String caption();
+
+ /**
+ * The list of {@link MenuItem} that will be displayed in the menu.
+ *
+ * @return The list of {@link MenuItem}.
+ */
+ List