diff --git a/build.gradle b/build.gradle index 54c42554..faaed309 100644 --- a/build.gradle +++ b/build.gradle @@ -14,9 +14,9 @@ repositories { } dependencies { - implementation 'net.portswigger.burp.extensions:montoya-api:0.10.1' + implementation 'net.portswigger.burp.extensions:montoya-api:1.0.0' implementation 'org.swinglabs:swingx:1.6.1' - implementation 'com.github.CoreyD97:Burp-Montoya-Utilities:896a540db7' + implementation 'com.github.CoreyD97:Burp-Montoya-Utilities:8501f80f05' implementation 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.15.2' implementation 'org.apache.httpcomponents:httpclient:4.5.13' implementation 'org.apache.commons:commons-text:1.10.0' diff --git a/src/main/java/com/nccgroup/loggerplusplus/LoggerContextMenuFactory.java b/src/main/java/com/nccgroup/loggerplusplus/LoggerContextMenuFactory.java index 27d78531..f1a950e0 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/LoggerContextMenuFactory.java +++ b/src/main/java/com/nccgroup/loggerplusplus/LoggerContextMenuFactory.java @@ -14,6 +14,7 @@ import org.apache.commons.text.StringEscapeUtils; import javax.swing.*; +import java.awt.*; import java.awt.event.ActionEvent; import java.util.Arrays; import java.util.HashMap; @@ -28,7 +29,7 @@ public LoggerContextMenuFactory(){ } @Override - public List provideMenuItems(ContextMenuEvent event) { + public List provideMenuItems(ContextMenuEvent event) { JMenuItem filterMenu = new JMenu("Logger++"); //We're handling a message editor context menu @@ -42,14 +43,14 @@ public List provideMenuItems(ContextMenuEvent event) { switch (event.invocationType()){ case MESSAGE_EDITOR_REQUEST: case MESSAGE_VIEWER_REQUEST: { - target = requestResponse.getRequestResponse().httpRequest(); + target = requestResponse.requestResponse().request(); try { if (selectedRange.startIndexInclusive() <= target.bodyOffset()) { context = LogEntryField.REQUEST_HEADERS; } else { context = LogEntryField.REQUEST_BODY; } - selectedBytes = Arrays.copyOfRange(target.asBytes().getBytes(), selectedRange.startIndexInclusive(), + selectedBytes = Arrays.copyOfRange(target.toByteArray().getBytes(), selectedRange.startIndexInclusive(), selectedRange.endIndexExclusive()); }catch (NullPointerException nPException){ return null; } break; @@ -57,14 +58,14 @@ public List provideMenuItems(ContextMenuEvent event) { case MESSAGE_EDITOR_RESPONSE: case MESSAGE_VIEWER_RESPONSE: { - target = requestResponse.getRequestResponse().httpResponse(); + target = requestResponse.requestResponse().response(); try { if (selectedRange.startIndexInclusive() <= target.bodyOffset()) { context = LogEntryField.RESPONSE_HEADERS; } else { context = LogEntryField.RESPONSE_BODY; } - selectedBytes = Arrays.copyOfRange(target.asBytes().getBytes(), selectedRange.startIndexInclusive(), + selectedBytes = Arrays.copyOfRange(target.toByteArray().getBytes(), selectedRange.startIndexInclusive(), selectedRange.endIndexExclusive()); } catch (NullPointerException nPException) { return null; diff --git a/src/main/java/com/nccgroup/loggerplusplus/LoggerPlusPlus.java b/src/main/java/com/nccgroup/loggerplusplus/LoggerPlusPlus.java index 74c1419e..55807ca0 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/LoggerPlusPlus.java +++ b/src/main/java/com/nccgroup/loggerplusplus/LoggerPlusPlus.java @@ -88,7 +88,7 @@ public void initialize(MontoyaApi montoya) { montoya.userInterface().registerSuiteTab(NAME, mainViewController.getUiComponent()); montoya.http().registerHttpHandler(logProcessor.getHttpHandler()); - montoya.proxy().registerResponseHandler(logProcessor.getProxyHttpResponseHandler()); + montoya.proxy().registerResponseHandler(logProcessor.getProxyResponseHandler()); //Add menu item to Burp's frame menu. Frame rootFrame = null; diff --git a/src/main/java/com/nccgroup/loggerplusplus/exports/HarSerializer.java b/src/main/java/com/nccgroup/loggerplusplus/exports/HarSerializer.java index 9fdee06c..de6f7097 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/exports/HarSerializer.java +++ b/src/main/java/com/nccgroup/loggerplusplus/exports/HarSerializer.java @@ -1,7 +1,7 @@ package com.nccgroup.loggerplusplus.exports; -import burp.api.montoya.http.message.cookies.Cookie; -import burp.api.montoya.http.message.headers.HttpHeader; +import burp.api.montoya.http.message.Cookie; +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.requests.HttpRequest; diff --git a/src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperController.java b/src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperController.java index 95cbb5bd..c87fbf91 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperController.java +++ b/src/main/java/com/nccgroup/loggerplusplus/grepper/GrepperController.java @@ -1,9 +1,8 @@ package com.nccgroup.loggerplusplus.grepper; -import burp.api.montoya.core.Annotations; +import burp.api.montoya.core.Marker; import burp.api.montoya.core.Range; import burp.api.montoya.http.message.HttpRequestResponse; -import burp.api.montoya.http.message.MarkedHttpRequestResponse; import com.coreyd97.BurpExtenderUtilities.Preferences; import com.nccgroup.loggerplusplus.LoggerPlusPlus; import com.nccgroup.loggerplusplus.logentry.LogEntry; @@ -60,15 +59,15 @@ public void reset() { //TODO SwingWorker } } - public MarkedHttpRequestResponse addMarkers(HttpRequestResponse requestResponse, List matches) { - List requestMarkers = new ArrayList<>(), responseMarkers = new ArrayList<>(); + public HttpRequestResponse addMarkers(HttpRequestResponse requestResponse, List matches) { + List requestMarkers = new ArrayList<>(), responseMarkers = new ArrayList<>(); for (GrepResults.Match match : matches) { - Range marker = Range.range(match.startIndex, match.endIndex); + Marker marker = Marker.marker(match.startIndex, match.endIndex); if (match.isRequest) requestMarkers.add(marker); else responseMarkers.add(marker); } - return requestResponse.withMarkers(requestMarkers, responseMarkers); + return requestResponse.withRequestMarkers(requestMarkers).withResponseMarkers(responseMarkers); } public void beginSearch(final Pattern pattern, final boolean inScopeOnly, final boolean searchRequests, final boolean searchResponses) { diff --git a/src/main/java/com/nccgroup/loggerplusplus/imports/LoggerImport.java b/src/main/java/com/nccgroup/loggerplusplus/imports/LoggerImport.java index c3d42c19..562fd692 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/imports/LoggerImport.java +++ b/src/main/java/com/nccgroup/loggerplusplus/imports/LoggerImport.java @@ -19,9 +19,12 @@ import burp.api.montoya.http.message.HttpRequestResponse; import burp.api.montoya.http.message.requests.HttpRequest; import burp.api.montoya.http.message.responses.HttpResponse; +import burp.api.montoya.utilities.Base64DecodingOptions; +import burp.api.montoya.utilities.Base64Utils; import com.nccgroup.loggerplusplus.LoggerPlusPlus; import com.nccgroup.loggerplusplus.logview.processor.EntryImportWorker; import lombok.extern.log4j.Log4j2; +import org.apache.logging.log4j.util.Base64Util; import javax.swing.*; import java.io.BufferedReader; @@ -90,10 +93,10 @@ public static ArrayList importWStalker() { String[] v = line.split(","); // Format: "base64(request),base64(response),url" String url = v[3]; - Base64.Decoder b64Decoder = LoggerPlusPlus.montoya.utilities().base64Utils().getDecoder(); + Base64Utils b64Decoder = LoggerPlusPlus.montoya.utilities().base64Utils(); HttpService httpService = HttpService.httpService(url); - HttpRequest httpRequest = HttpRequest.httpRequest(httpService, ByteArray.byteArray(b64Decoder.decode(v[0]))); - HttpResponse httpResponse = HttpResponse.httpResponse(ByteArray.byteArray(b64Decoder.decode(v[1]))); + HttpRequest httpRequest = HttpRequest.httpRequest(httpService, b64Decoder.decode(v[0], Base64DecodingOptions.URL)); + HttpResponse httpResponse = HttpResponse.httpResponse(b64Decoder.decode(v[1], Base64DecodingOptions.URL)); HttpRequestResponse requestResponse = HttpRequestResponse.httpRequestResponse(httpRequest, httpResponse); requests.add(requestResponse); diff --git a/src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java b/src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java index 0c652546..df693ac2 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logentry/LogEntry.java @@ -15,9 +15,9 @@ import burp.api.montoya.core.ToolType; import burp.api.montoya.http.HttpService; -import burp.api.montoya.http.MimeType; -import burp.api.montoya.http.message.cookies.Cookie; -import burp.api.montoya.http.message.headers.HttpHeader; +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.params.HttpParameter; import burp.api.montoya.http.message.params.HttpParameterType; import burp.api.montoya.http.message.requests.HttpRequest; @@ -414,7 +414,7 @@ private Status processResponse() { if (responseBodyLength < maxRespSize) { //Only title match HTML files. Prevents expensive regex running on e.g. binary downloads. if (this.responseInferredMimeType == MimeType.HTML) { - Matcher titleMatcher = Globals.HTML_TITLE_PATTERN.matcher(response.bodyAsString()); + Matcher titleMatcher = Globals.HTML_TITLE_PATTERN.matcher(response.bodyToString()); if (titleMatcher.find()) { this.title = titleMatcher.group(1); } @@ -422,7 +422,7 @@ private Status processResponse() { ReflectionController reflectionController = LoggerPlusPlus.instance.getReflectionController(); reflectedParameters = request.parameters().parallelStream() - .filter(parameter -> !reflectionController.isParameterFiltered(parameter) && reflectionController.validReflection(response.bodyAsString(), parameter)) + .filter(parameter -> !reflectionController.isParameterFiltered(parameter) && reflectionController.validReflection(response.bodyToString(), parameter)) .map(HttpParameter::name).collect(Collectors.toList()); // this.requestResponse = LoggerPlusPlus.montoya.saveBuffersToTempFiles(requestResponse); @@ -431,7 +431,7 @@ private Status processResponse() { ReflectionController reflectionController = LoggerPlusPlus.instance.getReflectionController(); reflectedParameters = request.parameters().parallelStream() .filter(parameter -> !reflectionController.isParameterFiltered(parameter) - && reflectionController.validReflection(new String(response.asBytes().getBytes(), 0, bodyOffset), parameter)) + && reflectionController.validReflection(response.bodyToString(), parameter)) .map(HttpParameter::name).collect(Collectors.toList()); //Trim the response down to a maximum size, but at least keep the headers! @@ -499,11 +499,11 @@ private Status processResponse() { } public byte[] getRequestBytes() { - return this.request.asBytes().getBytes(); + return this.request.toByteArray().getBytes(); } public byte[] getResponseBytes() { - return response.asBytes().getBytes(); + return response.toByteArray().getBytes(); } public void setReqestTime(Date requestTime) { @@ -639,12 +639,12 @@ public Object getValueByKey(LogEntryField columnName) { case REFLECTION_COUNT: return reflectedParameters.size(); case REQUEST_BODY: // request - return request.bodyAsString(); + return request.bodyToString(); case REQUEST_BODY_LENGTH: return request.body().length(); // .substring(request.length - requestBodyLength); case RESPONSE_BODY: // response - return response.bodyAsString(); + return response.bodyToString(); case RESPONSE_BODY_LENGTH: return response.body().length(); case RTT: diff --git a/src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java b/src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java index eafabc80..8bb866d2 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logview/MultipleLogEntryMenu.java @@ -2,9 +2,12 @@ import burp.api.montoya.core.BurpSuiteEdition; import burp.api.montoya.http.message.HttpRequestResponse; -import burp.api.montoya.scanner.BuiltInScanConfiguration; -import burp.api.montoya.scanner.InvalidLauncherConfigurationException; -import burp.api.montoya.scanner.Scan; +import burp.api.montoya.http.message.requests.HttpRequest; +import burp.api.montoya.scanner.AuditConfiguration; +import burp.api.montoya.scanner.BuiltInAuditConfiguration; +import burp.api.montoya.scanner.Crawl; +import burp.api.montoya.scanner.CrawlConfiguration; +import burp.api.montoya.scanner.audit.Audit; import com.nccgroup.loggerplusplus.LoggerPlusPlus; import com.nccgroup.loggerplusplus.exports.ContextMenuExportProvider; import com.nccgroup.loggerplusplus.exports.ExportController; @@ -101,17 +104,9 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem scanner = new JMenuItem(new AbstractAction("Crawl selected " + selectedEntries.size() + " urls") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - - for (LogEntry entry : selectedEntries) { - scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - } - - try { - scan.startCrawl(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); - } + List urls = selectedEntries.stream().map(logEntry -> logEntry.getUrl().toExternalForm()).toList(); + CrawlConfiguration config = CrawlConfiguration.crawlConfiguration(urls.toArray(String[]::new)); + Crawl crawl = LoggerPlusPlus.montoya.scanner().startCrawl(config); } }); this.add(scanner); @@ -119,17 +114,10 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem activeScan = new JMenuItem(new AbstractAction("Active scan selected " + selectedEntries.size() + " urls") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - scan.addConfiguration(BuiltInScanConfiguration.ACTIVE_AUDIT_CHECKS); - - for (LogEntry entry : selectedEntries) { - scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - } - - try { - scan.startAudit(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); + AuditConfiguration auditConfiguration = AuditConfiguration.auditConfiguration(BuiltInAuditConfiguration.LEGACY_ACTIVE_AUDIT_CHECKS); + Audit scan = LoggerPlusPlus.montoya.scanner().startAudit(auditConfiguration); + for (LogEntry selectedEntry : selectedEntries) { + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(selectedEntry.getRequest(), selectedEntry.getResponse())); } } }); @@ -139,17 +127,10 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem passiveScan = new JMenuItem(new AbstractAction("Passive scan selected " + selectedEntries.size() + " urls") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - scan.addConfiguration(BuiltInScanConfiguration.PASSIVE_AUDIT_CHECKS); - - for (LogEntry entry : selectedEntries) { - scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - } - - try { - scan.startAudit(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); + AuditConfiguration auditConfiguration = AuditConfiguration.auditConfiguration(BuiltInAuditConfiguration.LEGACY_PASSIVE_AUDIT_CHECKS); + Audit scan = LoggerPlusPlus.montoya.scanner().startAudit(auditConfiguration); + for (LogEntry selectedEntry : selectedEntries) { + scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(selectedEntry.getRequest(), selectedEntry.getResponse())); } } }); @@ -183,7 +164,7 @@ public void actionPerformed(ActionEvent actionEvent) { @Override public void actionPerformed(ActionEvent actionEvent) { for (LogEntry entry : selectedEntries) { - LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().asBytes()); + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().toByteArray()); } } }); @@ -193,7 +174,7 @@ public void actionPerformed(ActionEvent actionEvent) { public void actionPerformed(ActionEvent actionEvent) { for (LogEntry entry : selectedEntries) { if (entry.isComplete()) { //Do not add entries without a response - LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().asBytes()); + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().toByteArray()); } } } diff --git a/src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java b/src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java index 5b122528..c644e287 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logview/SingleLogEntryMenu.java @@ -2,9 +2,11 @@ import burp.api.montoya.core.BurpSuiteEdition; import burp.api.montoya.http.message.HttpRequestResponse; -import burp.api.montoya.scanner.BuiltInScanConfiguration; -import burp.api.montoya.scanner.InvalidLauncherConfigurationException; -import burp.api.montoya.scanner.Scan; +import burp.api.montoya.scanner.AuditConfiguration; +import burp.api.montoya.scanner.BuiltInAuditConfiguration; +import burp.api.montoya.scanner.Crawl; +import burp.api.montoya.scanner.CrawlConfiguration; +import burp.api.montoya.scanner.audit.Audit; import com.nccgroup.loggerplusplus.LoggerPlusPlus; import com.nccgroup.loggerplusplus.exports.ContextMenuExportProvider; import com.nccgroup.loggerplusplus.exports.ExportController; @@ -167,14 +169,8 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem spider = new JMenuItem(new AbstractAction("Crawl from here") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - - try { - scan.startCrawl(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); - } + CrawlConfiguration config = CrawlConfiguration.crawlConfiguration(entry.getUrl().toExternalForm()); + Crawl crawl = LoggerPlusPlus.montoya.scanner().startCrawl(config); } }); this.add(spider); @@ -182,15 +178,9 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem activeScan = new JMenuItem(new AbstractAction("Do an active scan") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - scan.addConfiguration(BuiltInScanConfiguration.ACTIVE_AUDIT_CHECKS); + AuditConfiguration auditConfiguration = AuditConfiguration.auditConfiguration(BuiltInAuditConfiguration.LEGACY_ACTIVE_AUDIT_CHECKS); + Audit scan = LoggerPlusPlus.montoya.scanner().startAudit(auditConfiguration); scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - - try { - scan.startAudit(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); - } } }); this.add(activeScan); @@ -199,15 +189,9 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem passiveScan = new JMenuItem(new AbstractAction("Do a passive scan") { @Override public void actionPerformed(ActionEvent actionEvent) { - Scan scan = LoggerPlusPlus.montoya.scanner().createScan(); - scan.addConfiguration(BuiltInScanConfiguration.PASSIVE_AUDIT_CHECKS); + AuditConfiguration auditConfiguration = AuditConfiguration.auditConfiguration(BuiltInAuditConfiguration.LEGACY_PASSIVE_AUDIT_CHECKS); + Audit scan = LoggerPlusPlus.montoya.scanner().startAudit(auditConfiguration); scan.addRequestResponse(HttpRequestResponse.httpRequestResponse(entry.getRequest(), entry.getResponse())); - - try { - scan.startAudit(); - } catch (InvalidLauncherConfigurationException e) { - log.error(e); - } } }); passiveScan.setEnabled(entry.isComplete() && isPro); @@ -235,14 +219,14 @@ public void actionPerformed(ActionEvent actionEvent) { JMenuItem comparerRequest = new JMenuItem(new AbstractAction("Request") { @Override public void actionPerformed(ActionEvent actionEvent) { - LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().asBytes()); + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getRequest().toByteArray()); } }); sendToComparer.add(comparerRequest); JMenuItem comparerResponse = new JMenuItem(new AbstractAction("Response") { @Override public void actionPerformed(ActionEvent actionEvent) { - LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().asBytes()); + LoggerPlusPlus.montoya.comparer().sendToComparer(entry.getResponse().toByteArray()); } }); sendToComparer.add(comparerResponse); diff --git a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/EntryImportWorker.java b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/EntryImportWorker.java index 63b1bead..1c7f1133 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/EntryImportWorker.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/EntryImportWorker.java @@ -4,7 +4,7 @@ import burp.api.montoya.http.message.HttpRequestResponse; import burp.api.montoya.http.message.requests.HttpRequest; import burp.api.montoya.http.message.responses.HttpResponse; -import burp.api.montoya.proxy.ProxyRequestResponse; +import burp.api.montoya.proxy.ProxyHttpRequestResponse; import com.nccgroup.loggerplusplus.logentry.LogEntry; import javax.swing.*; @@ -17,7 +17,7 @@ public class EntryImportWorker extends SwingWorker { private final LogProcessor logProcessor; private final ToolType originatingTool; - private final List proxyEntries; + private final List proxyEntries; private final List httpEntries; private final Consumer> interimConsumer; private final Runnable callback; @@ -50,8 +50,8 @@ protected Void doInBackground() throws Exception { request = proxyEntries.get(index).finalRequest(); response = proxyEntries.get(index).originalResponse(); }else{ - request = httpEntries.get(index).httpRequest(); - response = httpEntries.get(index).httpResponse(); + request = httpEntries.get(index).request(); + response = httpEntries.get(index).response(); } final LogEntry logEntry = new LogEntry(originatingTool, request, response); int finalIndex = index; @@ -86,7 +86,7 @@ public static class Builder { private final LogProcessor logProcessor; private ToolType originatingTool = ToolType.EXTENSIONS; - private List proxyEntries; + private List proxyEntries; private List httpEntries; private Consumer> interimConsumer; private Runnable callback; @@ -101,7 +101,7 @@ public Builder setOriginatingTool(ToolType originatingTool){ return this; } - public Builder setProxyEntries(List entries) { + public Builder setProxyEntries(List entries) { this.proxyEntries.addAll(entries); this.httpEntries.clear(); return this; diff --git a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessor.java b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessor.java index 70a57a11..c4b0b221 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessor.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessor.java @@ -1,14 +1,14 @@ package com.nccgroup.loggerplusplus.logview.processor; import burp.api.montoya.core.Annotations; -import burp.api.montoya.core.ToolSource; import burp.api.montoya.core.ToolType; -import burp.api.montoya.http.HttpHandler; -import burp.api.montoya.http.RequestResult; -import burp.api.montoya.http.ResponseResult; -import burp.api.montoya.http.message.requests.HttpRequest; +import burp.api.montoya.http.handler.*; import burp.api.montoya.http.message.responses.HttpResponse; -import burp.api.montoya.proxy.*; +import burp.api.montoya.proxy.ProxyHttpRequestResponse; +import burp.api.montoya.proxy.http.InterceptedResponse; +import burp.api.montoya.proxy.http.ProxyResponseHandler; +import burp.api.montoya.proxy.http.ProxyResponseReceivedAction; +import burp.api.montoya.proxy.http.ProxyResponseToBeSentAction; import com.coreyd97.BurpExtenderUtilities.Preferences; import com.nccgroup.loggerplusplus.LoggerPlusPlus; import com.nccgroup.loggerplusplus.exports.ExportController; @@ -50,7 +50,7 @@ public class LogProcessor { @Getter private final HttpHandler httpHandler; @Getter - private final ProxyHttpResponseHandler proxyHttpResponseHandler; + private final ProxyResponseHandler proxyResponseHandler; Logger logger = LogManager.getLogger(this); @@ -77,83 +77,88 @@ public LogProcessor(LogTableController logTableController, ExportController expo //TODO Enable new logging API when support for matching requests and their responses improves... this.httpHandler = createHttpHandler(); - this.proxyHttpResponseHandler = createProxyResponseHandler(); + this.proxyResponseHandler = createProxyResponseHandler(); } private HttpHandler createHttpHandler(){ return new HttpHandler() { @Override - public RequestResult handleHttpRequest(HttpRequest request, Annotations annotations, ToolSource toolSource) { - if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolSource.toolType()) - || !LoggerPlusPlus.isUrlInScope(request.url())){ - return RequestResult.requestResult(request,annotations); + public RequestToBeSentAction handleHttpRequestToBeSent(HttpRequestToBeSent requestToBeSent) { + if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(requestToBeSent.toolSource().toolType()) + || !LoggerPlusPlus.isUrlInScope(requestToBeSent.url())){ + return RequestToBeSentAction.continueWith(requestToBeSent); } Date arrivalTime = new Date(); //If we're handling a new request, create a log entry. //We must also handle proxy messages here, since the HTTP listener operates after the proxy listener - final LogEntry logEntry = new LogEntry(toolSource.toolType(), request, arrivalTime); + final LogEntry logEntry = new LogEntry(requestToBeSent.toolSource().toolType(), requestToBeSent, arrivalTime); //Set the entry's identifier to the HTTP request's hashcode. // For non-proxy messages, this doesn't change when we receive the response - Integer identifier = System.identityHashCode(request.body()); + Integer identifier = System.identityHashCode(requestToBeSent.body()); + log.info("HTTP Request - Request Identifier: " + identifier); + logEntry.setIdentifier(identifier); - annotations = LogProcessorHelper.addIdentifierInComment(identifier, annotations); + Annotations annotations = LogProcessorHelper.addIdentifierInComment(identifier, requestToBeSent.annotations()); //Submit a new task to process the entry submitNewEntryProcessingRunnable(logEntry); - return RequestResult.requestResult(request, annotations); + return RequestToBeSentAction.continueWith(requestToBeSent, annotations); } @Override - public ResponseResult handleHttpResponse(HttpResponse response, HttpRequest initiatingRequest, Annotations annotations, ToolSource toolSource) { - if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(toolSource.toolType()) - || !LoggerPlusPlus.isUrlInScope(initiatingRequest.url())){ - return ResponseResult.responseResult(response,annotations); + public ResponseReceivedAction handleHttpResponseReceived(HttpResponseReceived responseReceived) { + if (!(Boolean) preferences.getSetting(PREF_ENABLED) || !isValidTool(responseReceived.toolSource().toolType()) + || !LoggerPlusPlus.isUrlInScope(responseReceived.initiatingRequest().url())){ + return ResponseReceivedAction.continueWith(responseReceived); } Date arrivalTime = new Date(); - if (toolSource.isFromTool(ToolType.PROXY)) { + Annotations annotations = responseReceived.annotations(); + if (responseReceived.toolSource().isFromTool(ToolType.PROXY)) { //If the request came from the proxy, the response isn't final yet. //Just tag the comment with the identifier so we can match it up later. -// Integer identifier = System.identityHashCode(initiatingRequest); -// System.out.println("HTTP Response Proxy - Initiating Request: " + identifier); -// log.info("New Proxy Response: " + identifier); + Integer identifier = System.identityHashCode(responseReceived.initiatingRequest()); + log.info("HTTP Response Proxy - Response Received: " + identifier); // annotations = LogProcessorHelper.addIdentifierInComment(identifier, annotations); // return ResponseResult.responseResult(response, annotations); //Process proxy responses using processProxyMessage } else { //Otherwise, we have the final HTTP response, and can use the request hashcode to match it up with the log entry. - Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(annotations); + Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(responseReceived.annotations()); Integer identifier = (Integer) identifierAndAnnotation[0]; //TODO Ew. annotations = (Annotations) identifierAndAnnotation[1]; - updateRequestWithResponse(identifier, arrivalTime, response); + updateRequestWithResponse(identifier, arrivalTime, responseReceived); } - return ResponseResult.responseResult(response, annotations); + return ResponseReceivedAction.continueWith(responseReceived, annotations); } }; } - private ProxyHttpResponseHandler createProxyResponseHandler(){ - return new ProxyHttpResponseHandler() { + private ProxyResponseHandler createProxyResponseHandler(){ + return new ProxyResponseHandler() { @Override - public ResponseInitialInterceptResult handleReceivedResponse(InterceptedHttpResponse interceptedResponse, HttpRequest initiatingRequest, Annotations annotations) { - return ResponseInitialInterceptResult.followUserRules(interceptedResponse, annotations); //Do nothing + public ProxyResponseReceivedAction handleResponseReceived(InterceptedResponse interceptedResponse) { + return ProxyResponseReceivedAction.continueWith(interceptedResponse); //Do nothing } @Override - public ResponseFinalInterceptResult handleResponseToReturn(InterceptedHttpResponse interceptedResponse, HttpRequest initiatingRequest, Annotations annotations) { + public ProxyResponseToBeSentAction handleResponseToBeSent(InterceptedResponse interceptedResponse) { if(!((boolean) preferences.getSetting(PREF_ENABLED)) || !((boolean) preferences.getSetting(PREF_LOG_PROXY)) - || !LoggerPlusPlus.isUrlInScope(initiatingRequest.url())) { - return ResponseFinalInterceptResult.continueWith(interceptedResponse, annotations); + || !LoggerPlusPlus.isUrlInScope(interceptedResponse.initiatingRequest().url())) { + return ProxyResponseToBeSentAction.continueWith(interceptedResponse); } + Integer identifier2 = System.identityHashCode(interceptedResponse.initiatingRequest()); + log.info("Proxy Response - Identifier: " + identifier2); + Date arrivalTime = new Date(); - Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(annotations); + Object[] identifierAndAnnotation = LogProcessorHelper.extractAndRemoveIdentifierFromRequestResponseComment(interceptedResponse.annotations()); Integer identifier = (Integer) identifierAndAnnotation[0]; //TODO Ew. - annotations = (Annotations) identifierAndAnnotation[1]; + Annotations annotations = (Annotations) identifierAndAnnotation[1]; updateRequestWithResponse(identifier, arrivalTime, interceptedResponse); - return ResponseFinalInterceptResult.continueWith(interceptedResponse, annotations); + return ProxyResponseToBeSentAction.continueWith(interceptedResponse, annotations); } }; } @@ -340,10 +345,10 @@ public void importProxyHistory(boolean sendToAutoExporters) { //TODO Remove to more suitable UI class and show dialog //Build list of entries to import - List proxyHistory = LoggerPlusPlus.montoya.proxy().history(); + List proxyHistory = LoggerPlusPlus.montoya.proxy().history(); int maxEntries = preferences.getSetting(PREF_MAXIMUM_ENTRIES); int startIndex = Math.max(proxyHistory.size() - maxEntries, 0); - List entriesToImport = proxyHistory.subList(startIndex, proxyHistory.size()); + List entriesToImport = proxyHistory.subList(startIndex, proxyHistory.size()); //Build and start import worker EntryImportWorker importWorker = new EntryImportWorker.Builder(this) diff --git a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessorHelper.java b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessorHelper.java index 2ba7755b..d2be71a8 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessorHelper.java +++ b/src/main/java/com/nccgroup/loggerplusplus/logview/processor/LogProcessorHelper.java @@ -9,18 +9,18 @@ public class LogProcessorHelper { public static Annotations addIdentifierInComment(Integer identifier, Annotations annotations) { - String originalComment = annotations.comment() != null ? annotations.comment() : ""; - annotations = annotations.withComment(originalComment + "$LPP:" + identifier + "$"); + String originalComment = annotations.notes() != null ? annotations.notes() : ""; + annotations = annotations.withNotes(originalComment + "$LPP:" + identifier + "$"); return annotations; } public static Object[] extractAndRemoveIdentifierFromRequestResponseComment(Annotations annotations) { Integer identifier = null; - if (!StringUtils.isEmpty(annotations.comment())) { - Matcher matcher = Globals.LOG_ENTRY_ID_PATTERN.matcher(annotations.comment()); + if (!StringUtils.isEmpty(annotations.notes())) { + Matcher matcher = Globals.LOG_ENTRY_ID_PATTERN.matcher(annotations.notes()); if (matcher.find()) { identifier = Integer.parseInt(matcher.group(1)); - annotations = annotations.withComment(matcher.replaceAll("")); + annotations = annotations.withNotes(matcher.replaceAll("")); } } diff --git a/src/main/java/com/nccgroup/loggerplusplus/preferences/LoggerPreferenceFactory.java b/src/main/java/com/nccgroup/loggerplusplus/preferences/LoggerPreferenceFactory.java index c52c9a9c..dfb678e2 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/preferences/LoggerPreferenceFactory.java +++ b/src/main/java/com/nccgroup/loggerplusplus/preferences/LoggerPreferenceFactory.java @@ -16,6 +16,8 @@ import com.nccgroup.loggerplusplus.logentry.LogEntrySerializer; import com.nccgroup.loggerplusplus.logview.logtable.LogTableColumn; import com.nccgroup.loggerplusplus.util.Globals; +import lombok.extern.java.Log; +import lombok.extern.log4j.Log4j2; import org.apache.logging.log4j.Level; import javax.swing.*; @@ -23,6 +25,7 @@ import static com.nccgroup.loggerplusplus.util.Globals.*; +@Log4j2 public class LoggerPreferenceFactory extends PreferenceFactory { private HashMap defaultColorFilters; @@ -41,6 +44,7 @@ public LoggerPreferenceFactory(MontoyaApi montoya, IGsonProvider gsonProvider){ protected void createDefaults(){ defaultColorFilters = this.gsonProvider.getGson().fromJson( Globals.DEFAULT_COLOR_FILTERS_JSON, new TypeToken>(){}.getType()); + log.info(DEFAULT_LOG_TABLE_COLUMNS_JSON); defaultlogTableColumns = this.gsonProvider.getGson().fromJson( Globals.DEFAULT_LOG_TABLE_COLUMNS_JSON, new TypeToken>() {}.getType()); defaultBlacklistedReflections = new TreeSet(String.CASE_INSENSITIVE_ORDER); diff --git a/src/main/java/com/nccgroup/loggerplusplus/util/Globals.java b/src/main/java/com/nccgroup/loggerplusplus/util/Globals.java index a53c4e09..8ff26039 100644 --- a/src/main/java/com/nccgroup/loggerplusplus/util/Globals.java +++ b/src/main/java/com/nccgroup/loggerplusplus/util/Globals.java @@ -86,57 +86,57 @@ public enum Protocol {HTTP, HTTPS} public static final int CURRENT_COLUMN_VERSION = 9; private static int colOrder = 0; public static final String DEFAULT_LOG_TABLE_COLUMNS_JSON = new StringBuilder().append("[") - .append("{'id':" + NUMBER + ",'name':'Number','defaultVisibleName':'#','visibleName':'#','preferredWidth':65,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(NUMBER.getDescription()) + "'},") - .append("{'id':" + TAGS + ",'name':'Tags','defaultVisibleName':'Tags','visibleName':'Tags','preferredWidth':100,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(TAGS.getDescription()) + "'},") - .append("{'id':" + COMPLETE + ",'name':'Complete','defaultVisibleName':'Complete','visibleName':'Complete','preferredWidth':80,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(COMPLETE.getDescription()) + "'},") - .append("{'id':" + PROXY_TOOL + ",'name':'Tool','defaultVisibleName':'Tool','visibleName':'Tool','preferredWidth':70,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(PROXY_TOOL.getDescription()) + "'},") - .append("{'id':" + ISSSL + ",'name':'IsSSL','defaultVisibleName':'SSL','visibleName':'SSL','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(ISSSL.getDescription()) + "'},") - .append("{'id':" + METHOD + ",'name':'Method','defaultVisibleName':'Method','visibleName':'Method','preferredWidth':65,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(METHOD.getDescription()) + "'},") - .append("{'id':" + PROTOCOL + ",'name':'Protocol','defaultVisibleName':'Protocol','visibleName':'Protocol','preferredWidth':80,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(PROTOCOL.getDescription()) + "'},") - .append("{'id':" + HOSTNAME + ",'name':'Hostname','defaultVisibleName':'Host Name','visibleName':'Host Name','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HOSTNAME.getDescription()) + "'},") - .append("{'id':" + PORT + ",'name':'TargetPort','defaultVisibleName':'Port','visibleName':'Port','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(PORT.getDescription()) + "'},") - .append("{'id':" + HOST + ",'name':'Host','defaultVisibleName':'Host','visibleName':'Host','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(HOST.getDescription()) + "'},") - .append("{'id':" + PATH + ",'name':'Path','defaultVisibleName':'Path','visibleName':'Path','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(PATH.getDescription()) + "'},") - .append("{'id':" + EXTENSION + ",'name':'UrlExtension','defaultVisibleName':'Extension','visibleName':'Extension','preferredWidth':70,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(EXTENSION.getDescription()) + "'},") - .append("{'id':" + QUERY + ",'name':'Query','defaultVisibleName':'Query','visibleName':'Query','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(QUERY.getDescription()) + "'},") - .append("{'id':" + PATHQUERY + ",'name':'Path Query','defaultVisibleName':'Path Query','visibleName':'Path Query','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(PATHQUERY.getDescription()) + "'},") - .append("{'id':" + URL + ",'name':'Url','defaultVisibleName':'URL','visibleName':'URL','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(URL.getDescription()) + "'},") - .append("{'id':" + HASPARAMS + ",'name':'Has Params','defaultVisibleName':'Has Params','visibleName':'Has Params','preferredWidth':75,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HASPARAMS.getDescription()) + "'},") - .append("{'id':" + STATUS + ",'name':'Status','defaultVisibleName':'Status','visibleName':'Status','preferredWidth':55,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(STATUS.getDescription()) + "'},") - .append("{'id':" + TITLE + ",'name':'Title','defaultVisibleName':'Title','visibleName':'Title','preferredWidth':100,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(TITLE.getDescription()) + "'},") - .append("{'id':" + REQUEST_LENGTH + ",'name':'RequestLength','defaultVisibleName':'Request Length','visibleName':'Request Length','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REQUEST_LENGTH.getDescription()) + "'},") - .append("{'id':" + RESPONSE_LENGTH + ",'name':'ResponseLength','defaultVisibleName':'Response Length','visibleName':'Response Length','preferredWidth':125,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_LENGTH.getDescription()) + "'},") - .append("{'id':" + INFERRED_TYPE + ",'name':'InferredType','defaultVisibleName':'Inferred Type','visibleName':'Inferred Type','preferredWidth':100,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(INFERRED_TYPE.getDescription()) + "'},") - .append("{'id':" + COMMENT + ",'name':'Comment','defaultVisibleName':'Comment','visibleName':'Comment','preferredWidth':200,'readonly':false,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(COMMENT.getDescription()) + "'},") - .append("{'id':" + PARAMETER_COUNT + ",'name':'ParameterCount','defaultVisibleName':'Parameter Count','visibleName':'Parameter Count','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(PARAMETER_COUNT.getDescription()) + "'},") - .append("{'id':" + PARAMETERS + ",'name':'Parameters','defaultVisibleName':'Parameters','visibleName':'Parameters','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(PARAMETERS.getDescription()) + "'},") - .append("{'id':" + REFLECTED_PARAMS + ",'name':'ReflectedParams','defaultVisibleName':'Reflected Params','visibleName':'Reflected Params','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(REFLECTED_PARAMS.getDescription()) + "'},") - .append("{'id':" + REFLECTION_COUNT + ",'name':'ReflectionCount','defaultVisibleName':'Reflection Count','visibleName':'Reflection Count','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REFLECTION_COUNT.getDescription()) + "'},") - .append("{'id':" + ORIGIN + ",'name':'origin','defaultVisibleName':'Origin header','visibleName':'Origin header','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(ORIGIN.getDescription()) + "'},") - .append("{'id':" + MIME_TYPE + ",'name':'MimeType','defaultVisibleName':'MIME type','visibleName':'MIME type','preferredWidth':100,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(MIME_TYPE.getDescription()) + "'},") - .append("{'id':" + NEW_COOKIES + ",'name':'NewCookies','defaultVisibleName':'New Cookies','visibleName':'New Cookies','preferredWidth':125,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(NEW_COOKIES.getDescription()) + "'},") - .append("{'id':" + REQUEST_TIME + ",'name':'RequestTime','defaultVisibleName':'Request Time','visibleName':'Request Time','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(REQUEST_TIME.getDescription()) + "'},") - .append("{'id':" + RESPONSE_TIME + ",'name':'ResponseTime','defaultVisibleName':'Response Time','visibleName':'Response Time','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_TIME.getDescription()) + "'},") - .append("{'id':" + RESPONSE_HASH + ",'name':'ResponseHash','defaultVisibleName':'Response Hash','visibleName':'Response Hash','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_HASH.getDescription()) + "'},") - .append("{'id':" + RTT + ",'name':'RTT','defaultVisibleName':'RTT (ms)','visibleName':'RTT (ms)','preferredWidth':100,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(RTT.getDescription()) + "'},") - .append("{'id':" + LISTENER_INTERFACE + ",'name':'ListenerInterface','defaultVisibleName':'Proxy Listener Interface','visibleName':'Proxy Listener Interface','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':true,'description':'" + StringEscapeUtils.escapeJson(LISTENER_INTERFACE.getDescription()) + "'},") - .append("{'id':" + CLIENT_IP + ",'name':'ClientIP','defaultVisibleName':'Proxy Client IP','visibleName':'Proxy Client IP','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(CLIENT_IP.getDescription()) + "'},") - .append("{'id':" + RESPONSE_CONTENT_TYPE + ",'name':'ResponseContentType','defaultVisibleName':'Response Content-Type','visibleName':'Response Content-Type','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_CONTENT_TYPE.getDescription()) + "'},") - .append("{'id':" + HASGETPARAM + ",'name':'HasQueryStringParam','defaultVisibleName':'Query String?','visibleName':'Query String?','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HASGETPARAM.getDescription()) + "'},") - .append("{'id':" + HASPOSTPARAM + ",'name':'HasBodyParam','defaultVisibleName':'Body Params?','visibleName':'Body Params?','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HASPOSTPARAM.getDescription()) + "'},") - .append("{'id':" + HASCOOKIEPARAM + ",'name':'HasCookieParam','defaultVisibleName':'Sent Cookie?','visibleName':'Sent Cookie?','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HASCOOKIEPARAM.getDescription()) + "'},") - .append("{'id':" + SENTCOOKIES + ",'name':'SentCookies','defaultVisibleName':'Sent Cookies','visibleName':'Sent Cookies','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(SENTCOOKIES.getDescription()) + "'},") - .append("{'id':" + USES_COOKIE_JAR + ",'name':'UsesCookieJar','defaultVisibleName':'Contains cookie jar?','visibleName':'Contains cookie jar?','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(USES_COOKIE_JAR.getDescription()) + "'},") - .append("{'id':" + REQUEST_CONTENT_TYPE + ",'name':'RequestContentType','defaultVisibleName':'Request Content Type','visibleName':'Request Type','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REQUEST_CONTENT_TYPE.getDescription()) + "'},") - .append("{'id':" + REFERRER + ",'name':'Referrer','defaultVisibleName':'Referrer','visibleName':'Referrer','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REFERRER.getDescription()) + "'},") - .append("{'id':" + REDIRECT_URL + ",'name':'Redirect','defaultVisibleName':'Redirect','visibleName':'Redirect','preferredWidth':250,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REDIRECT_URL.getDescription()) + "'},") - .append("{'id':" + HAS_SET_COOKIES + ",'name':'HasSetCookies','defaultVisibleName':'Set-Cookie?','visibleName':'Set-Cookie?','preferredWidth':50,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(HAS_SET_COOKIES.getDescription()) + "'},") - .append("{'id':" + REQUEST_BODY + ",'name':'Request','defaultVisibleName':'Request Body','visibleName':'Request Body','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REQUEST_BODY.getDescription()) + "'},") - .append("{'id':" + REQUEST_BODY_LENGTH + ",'name':'RequestBodyLength','defaultVisibleName':'Request Body Length','visibleName':'Request Body Length','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REQUEST_BODY_LENGTH.getDescription()) + "'},") - .append("{'id':" + REQUEST_HEADERS + ",'name':'RequestHeaders','defaultVisibleName':'Request Headers','visibleName':'Request Headers','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(REQUEST_HEADERS.getDescription()) + "'},") - .append("{'id':" + RESPONSE_BODY + ",'name':'Response','defaultVisibleName':'Response Body','visibleName':'Response Body','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_BODY.getDescription()) + "'},") - .append("{'id':" + RESPONSE_BODY_LENGTH + ",'name':'ResponseBodyLength','defaultVisibleName':'Response Body Length','visibleName':'Response Body Length','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_BODY_LENGTH.getDescription()) + "'},") - .append("{'id':" + RESPONSE_HEADERS + ",'name':'ResponseHeaders','defaultVisibleName':'Response Headers','visibleName':'Response Headers','preferredWidth':150,'readonly':true,'order':" + colOrder++ + ",'visible':false,'description':'" + StringEscapeUtils.escapeJson(RESPONSE_HEADERS.getDescription()) + "'}") + .append("{\"id\":" + NUMBER + ",\"name\":\"Number\",\"defaultVisibleName\":\"#\",\"visibleName\":\"#\",\"preferredWidth\":65,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(NUMBER.getDescription()) + "\"},") + .append("{\"id\":" + TAGS + ",\"name\":\"Tags\",\"defaultVisibleName\":\"Tags\",\"visibleName\":\"Tags\",\"preferredWidth\":100,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(TAGS.getDescription()) + "\"},") + .append("{\"id\":" + COMPLETE + ",\"name\":\"Complete\",\"defaultVisibleName\":\"Complete\",\"visibleName\":\"Complete\",\"preferredWidth\":80,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(COMPLETE.getDescription()) + "\"},") + .append("{\"id\":" + PROXY_TOOL + ",\"name\":\"Tool\",\"defaultVisibleName\":\"Tool\",\"visibleName\":\"Tool\",\"preferredWidth\":70,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(PROXY_TOOL.getDescription()) + "\"},") + .append("{\"id\":" + ISSSL + ",\"name\":\"IsSSL\",\"defaultVisibleName\":\"SSL\",\"visibleName\":\"SSL\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(ISSSL.getDescription()) + "\"},") + .append("{\"id\":" + METHOD + ",\"name\":\"Method\",\"defaultVisibleName\":\"Method\",\"visibleName\":\"Method\",\"preferredWidth\":65,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(METHOD.getDescription()) + "\"},") + .append("{\"id\":" + PROTOCOL + ",\"name\":\"Protocol\",\"defaultVisibleName\":\"Protocol\",\"visibleName\":\"Protocol\",\"preferredWidth\":80,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(PROTOCOL.getDescription()) + "\"},") + .append("{\"id\":" + HOSTNAME + ",\"name\":\"Hostname\",\"defaultVisibleName\":\"Host Name\",\"visibleName\":\"Host Name\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HOSTNAME.getDescription()) + "\"},") + .append("{\"id\":" + PORT + ",\"name\":\"TargetPort\",\"defaultVisibleName\":\"Port\",\"visibleName\":\"Port\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(PORT.getDescription()) + "\"},") + .append("{\"id\":" + HOST + ",\"name\":\"Host\",\"defaultVisibleName\":\"Host\",\"visibleName\":\"Host\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(HOST.getDescription()) + "\"},") + .append("{\"id\":" + PATH + ",\"name\":\"Path\",\"defaultVisibleName\":\"Path\",\"visibleName\":\"Path\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(PATH.getDescription()) + "\"},") + .append("{\"id\":" + EXTENSION + ",\"name\":\"UrlExtension\",\"defaultVisibleName\":\"Extension\",\"visibleName\":\"Extension\",\"preferredWidth\":70,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(EXTENSION.getDescription()) + "\"},") + .append("{\"id\":" + QUERY + ",\"name\":\"Query\",\"defaultVisibleName\":\"Query\",\"visibleName\":\"Query\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(QUERY.getDescription()) + "\"},") + .append("{\"id\":" + PATHQUERY + ",\"name\":\"Path Query\",\"defaultVisibleName\":\"Path Query\",\"visibleName\":\"Path Query\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(PATHQUERY.getDescription()) + "\"},") + .append("{\"id\":" + URL + ",\"name\":\"Url\",\"defaultVisibleName\":\"URL\",\"visibleName\":\"URL\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(URL.getDescription()) + "\"},") + .append("{\"id\":" + HASPARAMS + ",\"name\":\"Has Params\",\"defaultVisibleName\":\"Has Params\",\"visibleName\":\"Has Params\",\"preferredWidth\":75,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HASPARAMS.getDescription()) + "\"},") + .append("{\"id\":" + STATUS + ",\"name\":\"Status\",\"defaultVisibleName\":\"Status\",\"visibleName\":\"Status\",\"preferredWidth\":55,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(STATUS.getDescription()) + "\"},") + .append("{\"id\":" + TITLE + ",\"name\":\"Title\",\"defaultVisibleName\":\"Title\",\"visibleName\":\"Title\",\"preferredWidth\":100,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(TITLE.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_LENGTH + ",\"name\":\"RequestLength\",\"defaultVisibleName\":\"Request Length\",\"visibleName\":\"Request Length\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_LENGTH.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_LENGTH + ",\"name\":\"ResponseLength\",\"defaultVisibleName\":\"Response Length\",\"visibleName\":\"Response Length\",\"preferredWidth\":125,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_LENGTH.getDescription()) + "\"},") + .append("{\"id\":" + INFERRED_TYPE + ",\"name\":\"InferredType\",\"defaultVisibleName\":\"Inferred Type\",\"visibleName\":\"Inferred Type\",\"preferredWidth\":100,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(INFERRED_TYPE.getDescription()) + "\"},") + .append("{\"id\":" + COMMENT + ",\"name\":\"Comment\",\"defaultVisibleName\":\"Comment\",\"visibleName\":\"Comment\",\"preferredWidth\":200,\"readonly\":false,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(COMMENT.getDescription()) + "\"},") + .append("{\"id\":" + PARAMETER_COUNT + ",\"name\":\"ParameterCount\",\"defaultVisibleName\":\"Parameter Count\",\"visibleName\":\"Parameter Count\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(PARAMETER_COUNT.getDescription()) + "\"},") + .append("{\"id\":" + PARAMETERS + ",\"name\":\"Parameters\",\"defaultVisibleName\":\"Parameters\",\"visibleName\":\"Parameters\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(PARAMETERS.getDescription()) + "\"},") + .append("{\"id\":" + REFLECTED_PARAMS + ",\"name\":\"ReflectedParams\",\"defaultVisibleName\":\"Reflected Params\",\"visibleName\":\"Reflected Params\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(REFLECTED_PARAMS.getDescription()) + "\"},") + .append("{\"id\":" + REFLECTION_COUNT + ",\"name\":\"ReflectionCount\",\"defaultVisibleName\":\"Reflection Count\",\"visibleName\":\"Reflection Count\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REFLECTION_COUNT.getDescription()) + "\"},") + .append("{\"id\":" + ORIGIN + ",\"name\":\"origin\",\"defaultVisibleName\":\"Origin header\",\"visibleName\":\"Origin header\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(ORIGIN.getDescription()) + "\"},") + .append("{\"id\":" + MIME_TYPE + ",\"name\":\"MimeType\",\"defaultVisibleName\":\"MIME type\",\"visibleName\":\"MIME type\",\"preferredWidth\":100,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(MIME_TYPE.getDescription()) + "\"},") + .append("{\"id\":" + NEW_COOKIES + ",\"name\":\"NewCookies\",\"defaultVisibleName\":\"New Cookies\",\"visibleName\":\"New Cookies\",\"preferredWidth\":125,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(NEW_COOKIES.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_TIME + ",\"name\":\"RequestTime\",\"defaultVisibleName\":\"Request Time\",\"visibleName\":\"Request Time\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_TIME.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_TIME + ",\"name\":\"ResponseTime\",\"defaultVisibleName\":\"Response Time\",\"visibleName\":\"Response Time\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_TIME.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_HASH + ",\"name\":\"ResponseHash\",\"defaultVisibleName\":\"Response Hash\",\"visibleName\":\"Response Hash\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_HASH.getDescription()) + "\"},") + .append("{\"id\":" + RTT + ",\"name\":\"RTT\",\"defaultVisibleName\":\"RTT (ms)\",\"visibleName\":\"RTT (ms)\",\"preferredWidth\":100,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(RTT.getDescription()) + "\"},") + .append("{\"id\":" + LISTENER_INTERFACE + ",\"name\":\"ListenerInterface\",\"defaultVisibleName\":\"Proxy Listener Interface\",\"visibleName\":\"Proxy Listener Interface\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":true,\"description\":\"" + StringEscapeUtils.escapeJson(LISTENER_INTERFACE.getDescription()) + "\"},") + .append("{\"id\":" + CLIENT_IP + ",\"name\":\"ClientIP\",\"defaultVisibleName\":\"Proxy Client IP\",\"visibleName\":\"Proxy Client IP\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(CLIENT_IP.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_CONTENT_TYPE + ",\"name\":\"ResponseContentType\",\"defaultVisibleName\":\"Response Content-Type\",\"visibleName\":\"Response Content-Type\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_CONTENT_TYPE.getDescription()) + "\"},") + .append("{\"id\":" + HASGETPARAM + ",\"name\":\"HasQueryStringParam\",\"defaultVisibleName\":\"Query String?\",\"visibleName\":\"Query String?\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HASGETPARAM.getDescription()) + "\"},") + .append("{\"id\":" + HASPOSTPARAM + ",\"name\":\"HasBodyParam\",\"defaultVisibleName\":\"Body Params?\",\"visibleName\":\"Body Params?\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HASPOSTPARAM.getDescription()) + "\"},") + .append("{\"id\":" + HASCOOKIEPARAM + ",\"name\":\"HasCookieParam\",\"defaultVisibleName\":\"Sent Cookie?\",\"visibleName\":\"Sent Cookie?\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HASCOOKIEPARAM.getDescription()) + "\"},") + .append("{\"id\":" + SENTCOOKIES + ",\"name\":\"SentCookies\",\"defaultVisibleName\":\"Sent Cookies\",\"visibleName\":\"Sent Cookies\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(SENTCOOKIES.getDescription()) + "\"},") + .append("{\"id\":" + USES_COOKIE_JAR + ",\"name\":\"UsesCookieJar\",\"defaultVisibleName\":\"Contains cookie jar?\",\"visibleName\":\"Contains cookie jar?\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(USES_COOKIE_JAR.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_CONTENT_TYPE + ",\"name\":\"RequestContentType\",\"defaultVisibleName\":\"Request Content Type\",\"visibleName\":\"Request Type\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_CONTENT_TYPE.getDescription()) + "\"},") + .append("{\"id\":" + REFERRER + ",\"name\":\"Referrer\",\"defaultVisibleName\":\"Referrer\",\"visibleName\":\"Referrer\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REFERRER.getDescription()) + "\"},") + .append("{\"id\":" + REDIRECT_URL + ",\"name\":\"Redirect\",\"defaultVisibleName\":\"Redirect\",\"visibleName\":\"Redirect\",\"preferredWidth\":250,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REDIRECT_URL.getDescription()) + "\"},") + .append("{\"id\":" + HAS_SET_COOKIES + ",\"name\":\"HasSetCookies\",\"defaultVisibleName\":\"Set-Cookie?\",\"visibleName\":\"Set-Cookie?\",\"preferredWidth\":50,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(HAS_SET_COOKIES.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_BODY + ",\"name\":\"Request\",\"defaultVisibleName\":\"Request Body\",\"visibleName\":\"Request Body\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_BODY.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_BODY_LENGTH + ",\"name\":\"RequestBodyLength\",\"defaultVisibleName\":\"Request Body Length\",\"visibleName\":\"Request Body Length\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_BODY_LENGTH.getDescription()) + "\"},") + .append("{\"id\":" + REQUEST_HEADERS + ",\"name\":\"RequestHeaders\",\"defaultVisibleName\":\"Request Headers\",\"visibleName\":\"Request Headers\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(REQUEST_HEADERS.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_BODY + ",\"name\":\"Response\",\"defaultVisibleName\":\"Response Body\",\"visibleName\":\"Response Body\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_BODY.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_BODY_LENGTH + ",\"name\":\"ResponseBodyLength\",\"defaultVisibleName\":\"Response Body Length\",\"visibleName\":\"Response Body Length\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_BODY_LENGTH.getDescription()) + "\"},") + .append("{\"id\":" + RESPONSE_HEADERS + ",\"name\":\"ResponseHeaders\",\"defaultVisibleName\":\"Response Headers\",\"visibleName\":\"Response Headers\",\"preferredWidth\":150,\"readonly\":true,\"order\":" + colOrder++ + ",\"visible\":false,\"description\":\"" + StringEscapeUtils.escapeJson(RESPONSE_HEADERS.getDescription()) + "\"}") .append("]").toString(); diff --git a/src/test/java/Test.java b/src/test/java/Test.java index e2ec439c..3c80ed09 100644 --- a/src/test/java/Test.java +++ b/src/test/java/Test.java @@ -1,12 +1,20 @@ +import com.nccgroup.loggerplusplus.LoggerPlusPlus; + import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class Test { public static void main(String[] args) { try { Method main = Class.forName("burp.StartBurp").getMethod("main", String[].class); - main.invoke(null, (Object) args); + ArrayList argList = new ArrayList<>(Arrays.stream(args).toList()); + argList.add("--developer-extension-class-name=" + LoggerPlusPlus.class.getName()); + main.invoke(null, (Object) argList.toArray(new String[]{})); }catch (Exception e){ System.err.println("Cannot start burp. Check the burp jar is correctly included in the classpath."); + e.printStackTrace(); } } }