You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jmeter.apache.org by fs...@apache.org on 2020/12/22 10:20:11 UTC

[jmeter] branch master updated: POST multipart/form-data cURL code with quoted arguments is not imported correctly

This is an automated email from the ASF dual-hosted git repository.

fschumacher pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/jmeter.git


The following commit(s) were added to refs/heads/master by this push:
     new bb0c455  POST multipart/form-data cURL code with quoted arguments is not imported correctly
bb0c455 is described below

commit bb0c4557e10278f334844f8c1af873b708981b08
Author: Felix Schumacher <fe...@internetallee.de>
AuthorDate: Tue Dec 22 11:19:21 2020 +0100

    POST multipart/form-data cURL code with quoted arguments is not imported correctly
    
    Bugzilla Id: 65013
---
 .../jmeter/protocol/http/curl/BasicCurlParser.java | 17 ++++++++---
 .../http/gui/action/ParseCurlCommandAction.java    |  9 +++++-
 .../apache/jmeter/curl/BasicCurlParserTest.java    | 34 ++++++++++++++++++++++
 .../gui/action/ParseCurlCommandActionTest.java     | 23 +++++++++++++++
 xdocs/changes.xml                                  |  1 +
 5 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
index 8d95da2..9471130 100644
--- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
+++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/curl/BasicCurlParser.java
@@ -710,9 +710,9 @@ public class BasicCurlParser {
                     String key = nameAndValue.substring(0, indexOfEqual).trim();
                     String value = nameAndValue.substring(indexOfEqual + 1).trim();
                     if ("form-string".equals(option.getDescriptor().getName())) {
-                        request.addFormStringData(key, value);
+                        request.addFormStringData(key, unquote(value));
                     } else {
-                        request.addFormData(key, value);
+                        request.addFormData(key, unquote(value));
                     }
                     request.setMethod("POST");
                 } else if (option.getDescriptor().getId() == USER_AGENT_OPT) {
@@ -955,7 +955,7 @@ public class BasicCurlParser {
            postdata = encodePostdata(postdata);
        } else {
            if (postdata.charAt(0) == '@' && !"data-raw".equals(dataOptionName)) {
-               postdata = postdata.substring(1, postdata.length());
+               postdata = unquote(postdata.substring(1, postdata.length()));
                postdata = readFromFile(postdata);
                if (!"data-binary".equals(dataOptionName)) {
                    postdata = deleteLineBreak(postdata);
@@ -965,6 +965,15 @@ public class BasicCurlParser {
        return postdata;
    }
 
+   private String unquote(String value) {
+       LoggerFactory.getLogger(this.getClass()).info("Unquote {}", value, new RuntimeException(""));
+       if (value.charAt(0) == '"') {
+           String result = value.substring(1, value.length() - 1);
+           return result.replaceAll("\\\\(.)", "$1");
+       }
+       return value;
+   }
+
    /**
     * Encode the post data
     *
@@ -975,7 +984,7 @@ public class BasicCurlParser {
         if (postdata.contains("@")) {
             String contentFile = null;
             String[] arr = postdata.split("@", 2);
-            String dataToEncode = readFromFile(arr[1]);
+            String dataToEncode = readFromFile(unquote(arr[1]));
             try {
                 contentFile = URLEncoder.encode(dataToEncode, StandardCharsets.UTF_8.name());
             } catch (UnsupportedEncodingException e) {
diff --git a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
index 49ca3d8..e03ae17 100644
--- a/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
+++ b/src/protocol/http/src/main/java/org/apache/jmeter/protocol/http/gui/action/ParseCurlCommandAction.java
@@ -526,7 +526,7 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
             boolean isContainsFile = "@".equals(formValue.substring(0, 1));
             boolean isContainsContentType = formValue.toLowerCase().contains(TYPE_FORM);
             if (isContainsFile) {
-                formValue = formValue.substring(1, formValue.length());
+                formValue = unquote(formValue.substring(1, formValue.length()));
                 String contentType;
                 if (isContainsContentType) {
                     String[] formValueWithType = formValue.split(TYPE_FORM);
@@ -552,6 +552,13 @@ public class ParseCurlCommandAction extends AbstractAction implements MenuCreato
         }
     }
 
+    private String unquote(String substring) {
+        if (substring.charAt(0) == '"') {
+            return substring.substring(1, substring.length() - 1).replaceAll("\\\\(.)", "$1");
+        }
+        return substring;
+    }
+
     private void createProxyServer(Request request, HTTPSamplerProxy httpSampler) {
         Map<String, String> proxyServer = request.getProxyServer();
         for (Map.Entry<String, String> proxyPara : proxyServer.entrySet()) {
diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/curl/BasicCurlParserTest.java b/src/protocol/http/src/test/java/org/apache/jmeter/curl/BasicCurlParserTest.java
index c9f9228..adfa954 100644
--- a/src/protocol/http/src/test/java/org/apache/jmeter/curl/BasicCurlParserTest.java
+++ b/src/protocol/http/src/test/java/org/apache/jmeter/curl/BasicCurlParserTest.java
@@ -423,6 +423,40 @@ public class BasicCurlParserTest {
     }
 
     @Test
+    public void testFormWithQuotedValue() {
+        String cmdLine = "curl 'https://www.exaple.invalid/' "
+                + "--form 'test=\"something quoted\"'";
+        BasicCurlParser basicCurlParser = new BasicCurlParser();
+        BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+        Map<String, String> res = request.getFormData();
+        assertEquals("something quoted", res.get("test"),
+                "With method 'form', we should post form data");
+    }
+
+    @Test
+    public void testFormWithQuotedValueWithQuotes() {
+        String cmdLine = "curl 'https://www.exaple.invalid/' "
+                + "--form 'test=\"something \\\"quoted\\\"\"'";
+        BasicCurlParser basicCurlParser = new BasicCurlParser();
+        BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+        Map<String, String> res = request.getFormData();
+        assertEquals("something \"quoted\"", res.get("test"),
+                "With method 'form', we should post form data");
+    }
+
+    @Test
+    public void testFormWithQuotedFilename() {
+        // The quotes will be removed later by the consumer, which is ParseCurlCommandAction
+        String cmdLine = "curl 'https://www.exaple.invalid/' "
+                + "--form 'image=@\"/some/file.jpg\"'";
+        BasicCurlParser basicCurlParser = new BasicCurlParser();
+        BasicCurlParser.Request request = basicCurlParser.parse(cmdLine);
+        Map<String, String> res = request.getFormData();
+        assertEquals("@\"/some/file.jpg\"", res.get("image"),
+                "With method 'form', we should post form data");
+    }
+
+    @Test
     public void testFormString() {
         String cmdLine = "curl 'https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit/action_page.php' "
                 + "-H 'cache-control: no-cache' --form-string 'image=@C:\\Test\\test.jpg' ";
diff --git a/src/protocol/http/src/test/java/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java b/src/protocol/http/src/test/java/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java
index 04c99de..15b984c 100644
--- a/src/protocol/http/src/test/java/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java
+++ b/src/protocol/http/src/test/java/org/apache/jmeter/gui/action/ParseCurlCommandActionTest.java
@@ -49,6 +49,7 @@ import org.apache.jmeter.protocol.http.curl.BasicCurlParser.Request;
 import org.apache.jmeter.protocol.http.gui.action.ParseCurlCommandAction;
 import org.apache.jmeter.protocol.http.sampler.HTTPSamplerFactory;
 import org.apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
+import org.apache.jmeter.protocol.http.util.HTTPFileArg;
 import org.apache.jmeter.testelement.TestElement;
 import org.apache.jmeter.testelement.TestPlan;
 import org.apache.jmeter.threads.ThreadGroup;
@@ -292,6 +293,28 @@ public class ParseCurlCommandActionTest {
     }
 
     @Test
+    public void testCreateHttpRequestWithQuotedFilenameAsData() throws Exception {
+        ParseCurlCommandAction p = new ParseCurlCommandAction();
+        BasicCurlParser basicCurlParser = new BasicCurlParser();
+        ThreadGroup threadGroup = new ThreadGroup();
+        TestPlan testPlan = new TestPlan();
+        HashTree tree = new HashTree();
+        HashTree testPlanHT = tree.add(testPlan);
+        HashTree threadGroupHT = testPlanHT.add(threadGroup);
+        Request request = basicCurlParser.parse("curl 'http://jmeter.apache.org/' -X POST --form 'pic=@\"/some/file.jpg\"'");
+        Method method = getMethodFor("createHttpRequest", Request.class, HashTree.class, String.class);
+        HTTPSamplerProxy httpSampler = (HTTPSamplerProxy) method.invoke(p, request, threadGroupHT, "comment");
+        assertEquals("/", httpSampler.getPath(), "path should be set in httpsampler");
+        assertEquals("jmeter.apache.org", httpSampler.getDomain(), "domain should be set in httpsampler");
+        assertEquals(80, httpSampler.getPort(), "port should be 80 in httpsampler");
+        assertEquals("POST", httpSampler.getMethod(), "method should be set in httpsampler");
+        HTTPFileArg fileArg = httpSampler.getHTTPFiles()[0];
+        assertEquals("pic", fileArg.getParamName());
+        assertEquals("/some/file.jpg", fileArg.getPath());
+        assertEquals("image/jpeg", fileArg.getMimeType());
+    }
+
+    @Test
     public void testConfigureTimeout() throws Exception {
         ParseCurlCommandAction p = new ParseCurlCommandAction();
         BasicCurlParser basicCurlParser = new BasicCurlParser();
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
index 6396c56..afac388 100644
--- a/xdocs/changes.xml
+++ b/xdocs/changes.xml
@@ -186,6 +186,7 @@ Summary
   <li><bug>64984</bug>Darklaf LAF: Selecting a Test element does not work under certain screen resolutions on Windows. With the help of Jannis Weis</li>
   <li><bug>65008</bug>SampleResult.setIgnore() called from PostProcessor is not considered</li>
   <li><bug>64993</bug>Daklaf LAF: Menu navigation not working with keyboard shortcuts. With the help of Jannis Weis</li>
+  <li><bug>65013</bug>POST multipart/form-data cURL code with quoted arguments is not imported correctly</li>
 </ul>
 
  <!--  =================== Thanks =================== -->