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/06/12 15:40:43 UTC

[cxf] 02/02: CXF-8698: Content-ID of attachments for outgoing requests are URL-decoded instead of URL-encoded (#950)

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 82b537613df4d89800e9a321d40c566c2a6906a0
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sun Jun 12 10:23:22 2022 -0400

    CXF-8698: Content-ID of attachments for outgoing requests are URL-decoded instead of URL-encoded (#950)
    
    (cherry picked from commit b89c16dbe17777c2ca2a123223b46473fd640328)
---
 .../cxf/attachment/AttachmentSerializer.java       | 31 +++++++++++++++++++++-
 .../org/apache/cxf/attachment/AttachmentUtil.java  | 22 ++++++++++-----
 .../cxf/attachment/AttachmentSerializerTest.java   | 20 +++++++++++---
 3 files changed, 62 insertions(+), 11 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java b/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
index 3e65de369f..b46f715c6d 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentSerializer.java
@@ -25,6 +25,7 @@ import java.io.OutputStream;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.net.URLDecoder;
+import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.Iterator;
@@ -215,7 +216,35 @@ public class AttachmentSerializer {
         if (attachmentId != null) {
             attachmentId = checkAngleBrackets(attachmentId);
             writer.write("Content-ID: <");
-            writer.write(URLDecoder.decode(attachmentId, StandardCharsets.UTF_8.name()));
+            
+            // 
+            // 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 ">".  
+            //
+            if (attachmentId.startsWith("cid:")) {
+                writer.write(URLDecoder.decode(attachmentId.substring(4),
+                    StandardCharsets.UTF_8.name()));
+            } else { 
+                //
+                // RFC-2392 (https://datatracker.ietf.org/doc/html/rfc2392) says:
+                // 
+                //   content-id = url-addr-spec
+                //   url-addr-spec = addr-spec ; URL encoding of RFC 822 addr-spec
+                // 
+                // RFC-822 addr-spec (https://datatracker.ietf.org/doc/html/rfc822#appendix-D) says:
+                //  
+                //   addr-spec = local-part "@" domain ; global address
+                //
+                String[] address = attachmentId.split("@", 2);
+                if (address.length == 2) {
+                    writer.write(attachmentId);
+                } else {
+                    writer.write(URLEncoder.encode(attachmentId, StandardCharsets.UTF_8.name()));
+                }
+            }
             writer.write(">\r\n");
         }
         // headers like Content-Disposition need to be serialized
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 7c72f00449..f62ebee76b 100644
--- a/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
+++ b/core/src/main/java/org/apache/cxf/attachment/AttachmentUtil.java
@@ -355,13 +355,21 @@ public final class AttachmentUtil {
             }
             // strip cid:
             if (id.startsWith("cid:")) {
-                id = id.substring(4);
-            }
-            // urldecode. Is this bad even without cid:? What does decode do with malformed %-signs, anyhow?
-            try {
-                id = URLDecoder.decode(id, StandardCharsets.UTF_8.name());
-            } catch (UnsupportedEncodingException e) {
-                //ignore, keep id as is
+                //
+                // 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
+                }
             }
         }
         if (id == null) {
diff --git a/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java b/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java
index dcdfe72f09..14e8b2a642 100644
--- a/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java
+++ b/core/src/test/java/org/apache/cxf/attachment/AttachmentSerializerTest.java
@@ -172,13 +172,27 @@ public class AttachmentSerializerTest {
         assertEquals("<test.xml>", part2.getHeader("Content-ID")[0]);
 
     }
-
+    
     @Test
     public void testMessageMTOM() throws Exception {
+        doTestMessageMTOM("test.xml", "<test.xml>");
+    }
+
+    @Test
+    public void testMessageMTOMCid() throws Exception {
+        doTestMessageMTOM("cid:http%3A%2F%2Fcxf.apache.org%2F", "<http://cxf.apache.org/>");
+    }
+
+    @Test
+    public void testMessageMTOMUrlDecoded() throws Exception {
+        doTestMessageMTOM("test+me.xml", "<test%2Bme.xml>");
+    }
+
+    private void doTestMessageMTOM(String contentId, String expectedContentId) throws Exception {
         MessageImpl msg = new MessageImpl();
 
         Collection<Attachment> atts = new ArrayList<>();
-        AttachmentImpl a = new AttachmentImpl("test.xml");
+        AttachmentImpl a = new AttachmentImpl(contentId);
 
         InputStream is = getClass().getResourceAsStream("my.wav");
         ByteArrayDataSource ds = new ByteArrayDataSource(is, "application/octet-stream");
@@ -235,7 +249,7 @@ public class AttachmentSerializerTest {
         MimeBodyPart part2 = (MimeBodyPart) multipart.getBodyPart(1);
         assertEquals("application/octet-stream", part2.getHeader("Content-Type")[0]);
         assertEquals("binary", part2.getHeader("Content-Transfer-Encoding")[0]);
-        assertEquals("<test.xml>", part2.getHeader("Content-ID")[0]);
+        assertEquals(expectedContentId, part2.getHeader("Content-ID")[0]);
 
     }