From 6d7c217faea8e5d2b59ab040061228fdeda489d4 Mon Sep 17 00:00:00 2001 From: trypa11 <67585616+trypa11@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:32:27 +0300 Subject: [PATCH] Application/XML support for request bodies This commit adds support for handling Application/XML content types in request bodies.This enhancement resolves Issue #6767 Signed-off-by:Tryfon Iason Papatriantafyllou --- addOns/openapi/CHANGELOG.md | 1 + .../swagger/RequestModelConverter.java | 11 ++---- .../openapi/generators/BodyGenerator.java | 38 +++++++++++++++++++ .../resources/help/contents/openapi.html | 2 - .../openapi/v3/BodyGeneratorUnitTest.java | 35 ++++++++++------- 5 files changed, 63 insertions(+), 24 deletions(-) diff --git a/addOns/openapi/CHANGELOG.md b/addOns/openapi/CHANGELOG.md index f9f07cc1c31..5292269d334 100644 --- a/addOns/openapi/CHANGELOG.md +++ b/addOns/openapi/CHANGELOG.md @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Allow to import the OpenAPI definitions with a user (Issue 7739). - Honour context exclusions when importing (Issue 8021). +- Application/XML support for request bodies (Issue 6767). ### Fixed - Allow to select the contexts of the Automation Framework plan when configuring the job. diff --git a/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/converter/swagger/RequestModelConverter.java b/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/converter/swagger/RequestModelConverter.java index ef8d2c31a43..46b8945c973 100644 --- a/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/converter/swagger/RequestModelConverter.java +++ b/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/converter/swagger/RequestModelConverter.java @@ -26,7 +26,6 @@ import io.swagger.v3.oas.models.parameters.RequestBody; import java.util.List; import java.util.Map; -import org.parosproxy.paros.Constant; import org.parosproxy.paros.network.HttpHeaderField; import org.zaproxy.zap.extension.openapi.generators.Generators; import org.zaproxy.zap.extension.openapi.generators.HeadersGenerator; @@ -85,13 +84,9 @@ private String generateBody() { return generators.getBodyGenerator().generateMultiPart(schema, encoding); } - if (content.containsKey(CONTENT_APPLICATION_XML)) { - generators.addErrorMessage( - Constant.messages.getString( - "openapi.unsupportedcontent", - operation.getOperationId(), - CONTENT_APPLICATION_XML)); - return ""; + if (content.containsKey("application/xml")) { + schema = content.get("application/xml").getSchema(); + return generators.getBodyGenerator().generateXml(schema); } if (!content.isEmpty()) { diff --git a/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/generators/BodyGenerator.java b/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/generators/BodyGenerator.java index 10c4f85a71d..e6529b5e28e 100644 --- a/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/generators/BodyGenerator.java +++ b/addOns/openapi/src/main/java/org/zaproxy/zap/extension/openapi/generators/BodyGenerator.java @@ -332,6 +332,44 @@ public String generateMultiPart(Schema schema, Map encoding return ""; } + @SuppressWarnings("rawtypes") + public String generateXml(Schema schema) { + if (schema == null) { + return ""; + } + + StringBuilder xml = new StringBuilder(); + String elementName = null; + generateXmlElements(schema, xml); + return xml.toString(); + } + + @SuppressWarnings("rawtypes") + private void generateXmlElements(Schema schema, StringBuilder xml) { + for (Map.Entry property : schema.getProperties().entrySet()) { + String elementName = property.getKey(); + xml.append("<"); + xml.append(elementName); + xml.append(">"); + + if (property.getValue().getProperties() != null) { + generateXmlElements(property.getValue(), xml); + } else { + String value = dataGenerator.generateValue(elementName, property.getValue(), false); + if ("string".equalsIgnoreCase(property.getValue().getType()) + && value.startsWith("\"") + && value.endsWith("\"")) { + value = value.substring(1, value.length() - 1); // Remove surrounding quotes + } + xml.append(value); + } + + xml.append("\n"); + } + } + private static String getPropertyContentType(Schema schema) { String type; diff --git a/addOns/openapi/src/main/javahelp/org/zaproxy/zap/extension/openapi/resources/help/contents/openapi.html b/addOns/openapi/src/main/javahelp/org/zaproxy/zap/extension/openapi/resources/help/contents/openapi.html index 9dce8c0354c..e85ae831d53 100644 --- a/addOns/openapi/src/main/javahelp/org/zaproxy/zap/extension/openapi/resources/help/contents/openapi.html +++ b/addOns/openapi/src/main/javahelp/org/zaproxy/zap/extension/openapi/resources/help/contents/openapi.html @@ -9,8 +9,6 @@

OpenAPI Support

This add-on allows you to spider and import OpenAPI (Swagger) definitions, versions 1.2, 2.0, and 3.0. -
-Note: Generation of XML content is currently not supported.

The add-on will automatically detect any OpenAPI definitions and spider them as long as they are in scope.

diff --git a/addOns/openapi/src/test/java/org/zaproxy/zap/extension/openapi/v3/BodyGeneratorUnitTest.java b/addOns/openapi/src/test/java/org/zaproxy/zap/extension/openapi/v3/BodyGeneratorUnitTest.java index c16301d20c3..476b4db20e8 100644 --- a/addOns/openapi/src/test/java/org/zaproxy/zap/extension/openapi/v3/BodyGeneratorUnitTest.java +++ b/addOns/openapi/src/test/java/org/zaproxy/zap/extension/openapi/v3/BodyGeneratorUnitTest.java @@ -19,10 +19,6 @@ */ package org.zaproxy.zap.extension.openapi.v3; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.emptyString; -import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -716,19 +712,30 @@ void shouldGenerateBodyWithNoSchema() throws IOException { } @Test - void shouldNotGenerateContentForApplicationXml() throws IOException { + void shouldGenerateXmlObject() throws IOException { // Given - OpenAPI definition = parseResource("openapi_xml_bodies.yaml"); - OperationModel operationModel = - new OperationModel("/xml", definition.getPaths().get("/xml").getPost(), null); + OpenAPI openAPI = parseResource("openapi_xml_bodies.yaml"); + // When - String content = new RequestModelConverter().convert(operationModel, generators).getBody(); + String xmlString = + generators + .getBodyGenerator() + .generateXml( + openAPI.getPaths() + .get("/xml") + .getPost() + .getRequestBody() + .getContent() + .get("application/xml") + .getSchema()); + // Then - assertThat(content, is(emptyString())); - assertThat( - generators.getErrorMessages(), - contains( - "Not generating request body for operation xml, the content type application/xml is not supported.")); + String expectedOutput = + "John Doe\n" + + "true\n" + + "10\n"; + + assertEquals(expectedOutput, xmlString); } @Test