Author: mattryan
Date: Sat Mar 2 02:42:53 2019
New Revision: 1854622
URL: http://svn.apache.org/viewvc?rev=1854622&view=rev
Log:
OAK-8013: Disable filename* part of Content-Disposition specification for
direct binary access.
Modified:
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
Modified:
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java?rev=1854622&r1=1854621&r2=1854622&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
(original)
+++
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptions.java
Sat Mar 2 02:42:53 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/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java?rev=1854622&r1=1854621&r2=1854622&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
(original)
+++
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/AbstractDataRecordAccessProviderTest.java
Sat Mar 2 02:42:53 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/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java?rev=1854622&r1=1854621&r2=1854622&view=diff
==============================================================================
---
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
(original)
+++
jackrabbit/oak/branches/1.10/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/DataRecordDownloadOptionsTest.java
Sat Mar 2 02:42:53 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