You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ma...@apache.org on 2019/02/27 23:27:59 UTC

svn commit: r1854489 - in /jackrabbit/oak/trunk/oak-blob-plugins/src: main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/ test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/

Author: mattryan
Date: Wed Feb 27 23:27:59 2019
New Revision: 1854489

URL: http://svn.apache.org/viewvc?rev=1854489&view=rev
Log:
OAK-8013: Disable filename* part of Content-Disposition specification for direct binary access.

Modified:
    jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
    jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java?rev=1854489&r1=1854488&r2=1854489&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java Wed Feb 27 23:27:59 2019
@@ -20,9 +20,11 @@
 package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
 
 import java.nio.charset.StandardCharsets;
+import java.util.Set;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
 import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
@@ -35,6 +37,16 @@ public class DataRecordDownloadOptions {
     static final String DISPOSITION_TYPE_INLINE = "inline";
     static final String DISPOSITION_TYPE_ATTACHMENT = "attachment";
 
+    private static final char[] hex = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+    };
+    private static final Set<Character> rfc5987AllowedChars = Sets.newHashSet(
+            '0','1','2','3','4','5','6','7','8','9',
+                    'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
+                    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+                    '!','#','$','&','+','-','.','^','_','`','|','~'
+    );
+
     /**
      * Create an instance of this class directly from a {@link
      * BlobDownloadOptions} instance.
@@ -126,11 +138,7 @@ public class DataRecordDownloadOptions {
                 if (Strings.isNullOrEmpty(dispositionType)) {
                     dispositionType = DISPOSITION_TYPE_INLINE;
                 }
-                contentDispositionHeader =
-                        String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
-                                dispositionType, fileName,
-                                new String(fileName.getBytes(StandardCharsets.UTF_8))
-                        );
+                contentDispositionHeader = formatContentDispositionHeader(dispositionType, fileName, null);
             }
             else if (DISPOSITION_TYPE_ATTACHMENT.equals(this.dispositionType)) {
                 contentDispositionHeader = DISPOSITION_TYPE_ATTACHMENT;
@@ -139,6 +147,31 @@ public class DataRecordDownloadOptions {
         return contentDispositionHeader;
     }
 
+    private String formatContentDispositionHeader(@NotNull final String dispositionType,
+                                                  @NotNull final String fileName,
+                                                  @Nullable final String rfc8187EncodedFileName) {
+        return null != rfc8187EncodedFileName ?
+                String.format("%s; filename=\"%s\"; filename*=UTF-8''%s", dispositionType, fileName, rfc8187EncodedFileName) :
+                String.format("%s; filename=\"%s\"", dispositionType, fileName);
+    }
+
+    private String rfc8187Encode(@NotNull final String input) {
+        byte[] bytes = input.getBytes(StandardCharsets.UTF_8);
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            char c = (char) b;
+            if (rfc5987AllowedChars.contains(c)) {
+                sb.append(c);
+            }
+            else {
+                sb.append('%');
+                sb.append(hex[0x0F & (b >>> 4)]);
+                sb.append(hex[b & 0x0F]);
+            }
+        }
+        return sb.toString();
+    }
+
     /**
      * Returns the media type of this instance.
      *

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java?rev=1854489&r1=1854488&r2=1854489&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java Wed Feb 27 23:27:59 2019
@@ -18,12 +18,20 @@
  */
 package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
 
+import static com.google.common.io.ByteStreams.toByteArray;
+import static org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreUtils.randomStream;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.URI;
 import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Map;
 
@@ -43,15 +51,6 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static com.google.common.io.ByteStreams.toByteArray;
-import static org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreUtils.randomStream;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 public abstract class AbstractDataRecordAccessProviderTest {
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractDataRecordAccessProviderTest.class);
 
@@ -150,6 +149,7 @@ public abstract class AbstractDataRecord
             record = doSynchronousAddRecord((DataStore) dataStore, testStream);
             String mimeType = "image/png";
             String fileName = "album cover.png";
+            String encodedFileName = "album%20cover.png";
             String dispositionType = "inline";
             DataRecordDownloadOptions downloadOptions =
                     DataRecordDownloadOptions.fromBlobDownloadOptions(
@@ -168,10 +168,19 @@ public abstract class AbstractDataRecord
             assertEquals(200, conn.getResponseCode());
 
             assertEquals(mimeType, conn.getHeaderField("Content-Type"));
+//            This proper behavior is disabled due to https://github.com/Azure/azure-sdk-for-java/issues/2900
+//            (see also https://issues.apache.org/jira/browse/OAK-8013).  We can re-enable the full test
+//            once the issue is resolved.  -MR
+//            assertEquals(
+//                    String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
+//                            dispositionType, fileName,
+//                            new String(encodedFileName.getBytes(StandardCharsets.UTF_8))
+//                    ),
+//                    conn.getHeaderField("Content-Disposition")
+//            );
             assertEquals(
-                    String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
-                            dispositionType, fileName,
-                            new String(fileName.getBytes(StandardCharsets.UTF_8))
+                    String.format("%s; filename=\"%s\"",
+                            dispositionType, fileName
                     ),
                     conn.getHeaderField("Content-Disposition")
             );

Modified: jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java?rev=1854489&r1=1854488&r2=1854489&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java (original)
+++ jackrabbit/oak/trunk/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java Wed Feb 27 23:27:59 2019
@@ -130,8 +130,12 @@ public class DataRecordDownloadOptionsTe
             dispositionType = DISPOSITION_TYPE_INLINE;
         }
         String fileNameStar = new String(fileName.getBytes(StandardCharsets.UTF_8));
-        return String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
-                dispositionType, fileName, fileNameStar);
+//        This proper behavior is disabled due to https://github.com/Azure/azure-sdk-for-java/issues/2900
+//        (see also https://issues.apache.org/jira/browse/OAK-8013).  We can re-enable the full test
+//        once the issue is resolved.  -MR
+//        return String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
+//                dispositionType, fileName, fileNameStar);
+        return String.format("%s; filename=\"%s\"", dispositionType, fileName);
     }
 
     @Test