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

reta pushed a commit to branch 3.6.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit d61e808c843b7ba63668528bb21b2c202a9a8692
Author: sstremler <[email protected]>
AuthorDate: Fri Apr 10 02:23:34 2026 +0200

    [CXF-9207] Add space after semicolon in multipart Content-Disposition 
headers (#3018)
    
    (cherry picked from commit e92e6ebe085113183dacd3286ede8722496f5336)
---
 .../org/apache/cxf/attachment/AttachmentUtil.java  |   2 +-
 .../cxf/jaxrs/provider/MultipartProvider.java      |  24 ++++-----
 .../cxf/systest/jaxrs/JAXRSMultipartTest.java      |  58 ++++++++++++---------
 .../cxf/systest/jaxrs/resources/java;test.jpg      | Bin 0 -> 1262 bytes
 4 files changed, 47 insertions(+), 37 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java 
b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
index eff623103d..f8fdd69216 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
@@ -557,7 +557,7 @@ public final class AttachmentUtil {
             if (f.exists() && f.isFile()) {
                 file = f.getName();
             }
-            att.setHeader("Content-Disposition", "attachment;name=\"" + file + 
"\"");
+            att.setHeader("Content-Disposition", "attachment; name=\"" + file 
+ "\"");
         }
         att.setXOP(isXop);
         return att;
diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
index 4a0d74ebd1..2f1d03e2c4 100644
--- 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
+++ 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/provider/MultipartProvider.java
@@ -347,7 +347,7 @@ public class MultipartProvider extends 
AbstractConfigurableProvider
         } else if (File.class.isAssignableFrom(obj.getClass())) {
             File f = (File)obj;
             ContentDisposition cd = 
mainMediaType.startsWith(MediaType.MULTIPART_FORM_DATA)
-                ? new ContentDisposition("form-data;name=file;filename=" + 
f.getName()) :  null;
+                ? new ContentDisposition("form-data; name=\"file\"; 
filename=\"" + f.getName() + "\"") :  null;
             return new Attachment(AttachmentUtil.BODY_ATTACHMENT_ID, 
Files.newInputStream(f.toPath()), cd);
         } else if (Attachment.class.isAssignableFrom(obj.getClass())) {
             Attachment att = (Attachment)obj;
@@ -358,14 +358,14 @@ public class MultipartProvider extends 
AbstractConfigurableProvider
                                      att.getObject().getClass(), new 
Annotation[]{},
                                      att.getContentType().toString(), id);
             MediaType mediaType = httpHeaders.getMediaType();
-            Attachment ret = null;
+            Attachment ret;
             if (MediaType.MULTIPART_FORM_DATA_TYPE.isCompatible(mediaType)
                 && att.getHeader("Content-Disposition") == null) {
                 ContentDisposition cd = new 
-                    ContentDisposition("form-data;name=\"" 
+                    ContentDisposition("form-data; name=\""
                         + att.getContentId() + "\"");
-                MultivaluedMap<String, String> newHeaders = 
-                    new MetadataMap<String, String>(att.getHeaders(), false, 
true);
+                MultivaluedMap<String, String> newHeaders =
+                        new MetadataMap<>(att.getHeaders(), false, true);
                 newHeaders.putSingle("Content-Disposition", cd.toString());
                 ret = new Attachment(att.getContentId(), dh, newHeaders);
             } else {
@@ -451,12 +451,12 @@ public class MultipartProvider extends 
AbstractConfigurableProvider
     }
 
     private static class MessageBodyWriterDataHandler<T> extends DataHandler {
-        private MessageBodyWriter<T> writer;
-        private T obj;
-        private Class<T> cls;
-        private Type genericType;
-        private Annotation[] anns;
-        private MediaType contentType;
+        private final MessageBodyWriter<T> writer;
+        private final T obj;
+        private final Class<T> cls;
+        private final Type genericType;
+        private final Annotation[] anns;
+        private final MediaType contentType;
         MessageBodyWriterDataHandler(MessageBodyWriter<T> writer,
                                      T obj,
                                      Class<T> cls,
@@ -476,7 +476,7 @@ public class MultipartProvider extends 
AbstractConfigurableProvider
         public void writeTo(OutputStream os) {
             try {
                 writer.writeTo(obj, cls, genericType, anns, contentType,
-                               new MetadataMap<String, Object>(), os);
+                        new MetadataMap<>(), os);
             } catch (IOException ex) {
                 throw ExceptionUtils.toInternalServerErrorException(ex, null);
             }
diff --git 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
index d892dfc0e6..55dddc44f9 100644
--- 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
+++ 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSMultipartTest.java
@@ -28,6 +28,7 @@ import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.PushbackInputStream;
 import java.lang.annotation.Annotation;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -94,15 +95,15 @@ import static org.junit.Assert.assertTrue;
 public class JAXRSMultipartTest extends AbstractBusClientServerTestBase {
     public static final String PORT = MultipartServer.PORT;
     public static final String PORTINV = 
allocatePort(JAXRSMultipartTest.class, 1);
-    
+
     @BeforeClass
     public static void startServers() throws Exception {
         assertTrue("server did not launch correctly",
                    launchServer(MultipartServer.class, true));
     }
 
-    
-    
+
+
     @Test
     public void testBookAsRootAttachmentStreamSource() throws Exception {
         String address = "http://localhost:"; + PORT + 
"/bookstore/books/stream";
@@ -526,7 +527,7 @@ public class JAXRSMultipartTest extends 
AbstractBusClientServerTestBase {
     }
 
     @Test
-    public void testNullPartProxy() throws Exception {
+    public void testNullPartProxy() {
         ByteArrayOutputStream output = new ByteArrayOutputStream();
         PrintWriter writer = new PrintWriter(output, true);
 
@@ -536,8 +537,8 @@ public class JAXRSMultipartTest extends 
AbstractBusClientServerTestBase {
             JAXRSClientFactory.create("http://localhost:"; + PORT, 
MultipartStore.class);
         WebClient.getConfig(store).getOutInterceptors().add(out);
         assertEquals("nobody home2", store.testNullParts("value1", null));
-        String expected = "Content-Disposition: form-data;name=\"someid\"";
-        assertTrue(output.toString().indexOf(expected) != -1);
+        String expected = "Content-Disposition: form-data; name=\"someid\"";
+        assertTrue(output.toString().contains(expected));
     }
 
     @Test
@@ -1029,23 +1030,12 @@ public class JAXRSMultipartTest extends 
AbstractBusClientServerTestBase {
 
     @Test
     public void testUploadImageFromForm2() throws Exception {
-        File file =
-            new 
File(getClass().getResource("/org/apache/cxf/systest/jaxrs/resources/java.jpg")
-                               .toURI().getPath());
-        String address = "http://localhost:"; + PORT + 
"/bookstore/books/formimage2";
-        WebClient client = WebClient.create(address);
-        client.type("multipart/form-data").accept("multipart/form-data");
-        
WebClient.getConfig(client).getRequestContext().put("support.type.as.multipart",
-                                                            "true");
-        MultipartBody body2 = client.post(file, MultipartBody.class);
-        InputStream is2 = 
body2.getRootAttachment().getDataHandler().getInputStream();
-        byte[] image1 = IOUtils.readBytesFromStream(
-            
getClass().getResourceAsStream("/org/apache/cxf/systest/jaxrs/resources/java.jpg"));
-        byte[] image2 = IOUtils.readBytesFromStream(is2);
-        assertArrayEquals(image1, image2);
-        ContentDisposition cd2 = 
body2.getRootAttachment().getContentDisposition();
-        assertEquals("form-data;name=file;filename=java.jpg", cd2.toString());
-        assertEquals("java.jpg", cd2.getParameter("filename"));
+        this.uploadImageFromForm2("java.jpg");
+    }
+
+    @Test
+    public void testUploadImageFromForm2WithSemicolon() throws Exception {
+        this.uploadImageFromForm2("java;test.jpg");
     }
 
     @Test
@@ -1165,7 +1155,7 @@ public class JAXRSMultipartTest extends 
AbstractBusClientServerTestBase {
 
         Attachment att = new Attachment(headers, handler, null);
         try (Response response = client.post(att)) {
-            assertEquals(response.getStatus(), 200);
+            assertEquals(200, response.getStatus());
         }
 
         client.close();
@@ -1277,6 +1267,26 @@ public class JAXRSMultipartTest extends 
AbstractBusClientServerTestBase {
         return str;
     }
 
+    private void uploadImageFromForm2(String filename) throws 
URISyntaxException, IOException {
+        File file =
+                new 
File(getClass().getResource("/org/apache/cxf/systest/jaxrs/resources/" + 
filename)
+                        .toURI().getPath());
+        String address = "http://localhost:"; + PORT + 
"/bookstore/books/formimage2";
+        WebClient client = WebClient.create(address);
+        client.type("multipart/form-data").accept("multipart/form-data");
+        
WebClient.getConfig(client).getRequestContext().put("support.type.as.multipart",
+                "true");
+        MultipartBody body2 = client.post(file, MultipartBody.class);
+        InputStream is2 = 
body2.getRootAttachment().getDataHandler().getInputStream();
+        byte[] image1 = IOUtils.readBytesFromStream(
+                
getClass().getResourceAsStream("/org/apache/cxf/systest/jaxrs/resources/" + 
filename));
+        byte[] image2 = IOUtils.readBytesFromStream(is2);
+        assertArrayEquals(image1, image2);
+        ContentDisposition cd2 = 
body2.getRootAttachment().getContentDisposition();
+        assertEquals("form-data; name=\"file\"; filename=\"" + filename + 
"\"", cd2.toString());
+        assertEquals(filename, cd2.getParameter("filename"));
+    }
+
     /**
      * Windows attachment handling
      */
diff --git 
a/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/java;test.jpg
 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/java;test.jpg
new file mode 100644
index 0000000000..dc59bee5e2
Binary files /dev/null and 
b/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/resources/java;test.jpg
 differ

Reply via email to