You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2022/07/15 13:54:49 UTC

[cxf] branch 3.6.x-fixes updated: CXF-8733: [regression] Content-ID of attachments for outgoing requests is not URL-decoded (#968)

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


The following commit(s) were added to refs/heads/3.6.x-fixes by this push:
     new 952cd07527 CXF-8733: [regression] Content-ID of attachments for outgoing requests is not URL-decoded (#968)
952cd07527 is described below

commit 952cd07527d9abb0b6665d7483913afe1c1ae5e7
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Fri Jul 15 09:54:42 2022 -0400

    CXF-8733: [regression] Content-ID of attachments for outgoing requests is not URL-decoded (#968)
---
 .../org/apache/cxf/attachment/AttachmentUtil.java  |  23 +--
 .../AttachmentSerializerDeserializerTest.java      | 188 +++++++++++++++++++++
 2 files changed, 196 insertions(+), 15 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 f62ebee76b..ce393ee54d 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
@@ -355,21 +355,14 @@ public final class AttachmentUtil {
             }
             // strip cid:
             if (id.startsWith("cid:")) {
-                //
-                // RFC-2392 (https://datatracker.ietf.org/doc/html/rfc2392) says:
-                //
-                // A "cid" URL is converted to the corresponding Content-ID message
-                // header [MIME] by removing the "cid:" prefix, converting the % encoded
-                // character to their equivalent US-ASCII characters, and enclosing the
-                // remaining parts with an angle bracket pair, "<" and ">".  
-                //
-                try {
-                    id = id.substring(4);
-                    // urldecode
-                    id = URLDecoder.decode(id, StandardCharsets.UTF_8.name());
-                } catch (UnsupportedEncodingException e) {
-                    //ignore, keep id as is
-                }
+                id = id.substring(4);
+            }
+
+            try {
+                // urldecode
+                id = URLDecoder.decode(id, StandardCharsets.UTF_8.name());
+            } catch (UnsupportedEncodingException e) {
+                //ignore, keep id as is
             }
         }
         if (id == null) {
diff --git a/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerDeserializerTest.java b/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerDeserializerTest.java
new file mode 100644
index 0000000000..99d5c11492
--- /dev/null
+++ b/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerDeserializerTest.java
@@ -0,0 +1,188 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.attachment;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.activation.DataHandler;
+import javax.mail.MessagingException;
+import javax.mail.util.ByteArrayDataSource;
+
+import org.apache.cxf.helpers.IOUtils;
+import org.apache.cxf.message.Attachment;
+import org.apache.cxf.message.Message;
+import org.apache.cxf.message.MessageImpl;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class AttachmentSerializerDeserializerTest {
+
+    @Test
+    public void testMessageWriteXopOn1() throws Exception {
+        doTestMessageSerde(true, "text/xml");
+    }
+
+    @Test
+    public void testMessageWriteXopOn2() throws Exception {
+        doTestMessageSerde(true, "application/soap+xml; action=\"urn:foo\"");
+    }
+
+    @Test
+    public void testMessageWriteXopOff1() throws Exception {
+        doTestMessageSerde(false, "text/xml");
+    }
+
+    @Test
+    public void testMessageWriteXopOff2() throws Exception {
+        doTestMessageSerde(false, "application/soap+xml; action=\"urn:foo\"");
+    }
+
+    private void doTestMessageSerde(boolean xop, String soapContentType) throws Exception {
+        MessageImpl in = new MessageImpl();
+
+        Collection<Attachment> atts = new ArrayList<>();
+        AttachmentImpl a = new AttachmentImpl("test.xml");
+
+        InputStream is = getClass().getResourceAsStream("my.wav");
+        ByteArrayDataSource ds = new ByteArrayDataSource(is, "application/octet-stream");
+        a.setDataHandler(new DataHandler(ds));
+
+        atts.add(a);
+
+        in.setAttachments(atts);
+
+        // Set the SOAP content type
+        in.put(Message.CONTENT_TYPE, soapContentType);
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        in.setContent(OutputStream.class, out);
+
+        AttachmentSerializer serializer = new AttachmentSerializer(in);
+        if (!xop) {
+            // default is "on"
+            serializer.setXop(xop);
+        }
+
+        serializer.writeProlog();
+        out.write("<soap:Body/>".getBytes());
+
+        serializer.writeAttachments();
+        out.flush();
+
+        doTestMessageRead(in, "test.xml");
+        is.close();
+    }
+
+    private void doTestMessageRead(Message in, String contentId) 
+            throws IOException, MessagingException {
+
+        final MessageImpl msg = new MessageImpl();
+        msg.put(Message.CONTENT_TYPE, "multipart/related;");
+        
+        final ByteArrayOutputStream out = (ByteArrayOutputStream)in.getContent(OutputStream.class);
+        try (ByteArrayInputStream content = new ByteArrayInputStream(out.toByteArray())) {
+            msg.setContent(InputStream.class, content);
+            
+            AttachmentDeserializer deserializer = new AttachmentDeserializer(msg);
+            deserializer.initializeAttachments();
+    
+            Collection<Attachment> atts = msg.getAttachments();
+            assertNotNull(atts);
+    
+            Iterator<Attachment> itr = atts.iterator();
+            assertTrue(itr.hasNext());
+    
+            Attachment a = itr.next();
+            assertNotNull(a);
+    
+            assertEquals("binary", a.getHeader("Content-Transfer-Encoding"));
+            assertEquals(contentId, a.getId());
+    
+            // check the cached output stream
+            InputStream attBody = msg.getContent(InputStream.class);
+            try (ByteArrayOutputStream attOut = new ByteArrayOutputStream()) {
+                IOUtils.copy(attBody, attOut);
+                assertEquals("<soap:Body/>", attOut.toString());
+            }
+        }
+    }
+    
+    @Test
+    public void testMessageMTOM() throws Exception {
+        doTestMessageMTOM("test.xml", "<test.xml>", "test.xml");
+    }
+
+    @Test
+    public void testMessageMTOMCid() throws Exception {
+        doTestMessageMTOM("cid:http%3A%2F%2Fcxf.apache.org%2F", "<http://cxf.apache.org/>", "http://cxf.apache.org/");
+    }
+
+    @Test
+    public void testMessageMTOMUrlDecoded() throws Exception {
+        doTestMessageMTOM("test+me.xml", "<test%2Bme.xml>", "test+me.xml");
+    }
+
+    private void doTestMessageMTOM(String contentId, String expectedEncocedContentId, 
+            String expectedDecocedContentId) throws Exception {
+        MessageImpl msg = new MessageImpl();
+
+        Collection<Attachment> atts = new ArrayList<>();
+        AttachmentImpl a = new AttachmentImpl(contentId);
+
+        InputStream is = getClass().getResourceAsStream("my.wav");
+        ByteArrayDataSource ds = new ByteArrayDataSource(is, "application/octet-stream");
+        a.setDataHandler(new DataHandler(ds));
+
+        atts.add(a);
+
+        msg.setAttachments(atts);
+
+        // Set the SOAP content type
+        msg.put(Message.CONTENT_TYPE, "application/soap+xml");
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        msg.setContent(OutputStream.class, out);
+
+        AttachmentSerializer serializer = new AttachmentSerializer(msg);
+
+        serializer.writeProlog();
+
+        String ct = (String) msg.get(Message.CONTENT_TYPE);
+        assertTrue(ct.indexOf("multipart/related;") == 0);
+        assertTrue(ct.indexOf("start=\"<ro...@cxf.apache.org>\"") > -1);
+        assertTrue(ct.indexOf("start-info=\"application/soap+xml\"") > -1);
+
+        out.write("<soap:Body/>".getBytes());
+
+        serializer.writeAttachments();
+        out.flush();
+
+        doTestMessageRead(msg, expectedDecocedContentId);
+    }
+}
\ No newline at end of file