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 2020/12/18 22:26:00 UTC
svn commit: r1884613 - in /jackrabbit/oak/trunk:
oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/
oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/directaccess/
oak-blob-plugins/src/test/java/org/apac...
Author: mattryan
Date: Fri Dec 18 22:26:00 2020
New Revision: 1884613
URL: http://svn.apache.org/viewvc?rev=1884613&view=rev
Log:
OAK-9304 Use ISO-8859-1 encoding in filename portion of DBA download URI specification
Modified:
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/Utils.java
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-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java?rev=1884613&r1=1884612&r2=1884613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/S3Backend.java Fri Dec 18 22:26:00 2020
@@ -17,10 +17,6 @@
package org.apache.jackrabbit.oak.blob.cloud.s3;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.filter;
-import static java.lang.Thread.currentThread;
-
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
@@ -43,6 +39,22 @@ import java.util.concurrent.ExecutorServ
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import org.apache.commons.io.IOUtils;
+import org.apache.jackrabbit.core.data.DataIdentifier;
+import org.apache.jackrabbit.core.data.DataRecord;
+import org.apache.jackrabbit.core.data.DataStoreException;
+import org.apache.jackrabbit.core.data.util.NamedThreadFactory;
+import org.apache.jackrabbit.oak.commons.PropertiesUtil;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
+import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadToken;
+import org.apache.jackrabbit.oak.spi.blob.AbstractDataRecord;
+import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.HttpMethod;
@@ -83,22 +95,10 @@ import com.google.common.cache.CacheBuil
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.protocol.HTTP;
-import org.apache.jackrabbit.core.data.DataIdentifier;
-import org.apache.jackrabbit.core.data.DataRecord;
-import org.apache.jackrabbit.core.data.DataStoreException;
-import org.apache.jackrabbit.core.data.util.NamedThreadFactory;
-import org.apache.jackrabbit.oak.commons.PropertiesUtil;
-import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordDownloadOptions;
-import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUpload;
-import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadException;
-import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.DataRecordUploadToken;
-import org.apache.jackrabbit.oak.spi.blob.AbstractDataRecord;
-import org.apache.jackrabbit.oak.spi.blob.AbstractSharedBackend;
-import org.jetbrains.annotations.NotNull;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.filter;
+import static java.lang.Thread.currentThread;
/**
* A data store backend that stores data on Amazon S3.
@@ -188,7 +188,7 @@ public class S3Backend extends AbstractS
+ "] not configured and cannot be derived from environment");
}
} else if (Utils.DEFAULT_AWS_BUCKET_REGION.equals(region)) {
- region = Region.US_Standard.toString();
+ region = Region.US_Standard.toString();
}
createBucketIfNeeded(region);
@@ -262,7 +262,15 @@ public class S3Backend extends AbstractS
private void createBucketIfNeeded(final String region) {
try {
if (!s3service.doesBucketExist(bucket)) {
- CreateBucketRequest req = new CreateBucketRequest(bucket, region);
+ String bucketRegion = region;
+ if (Utils.US_EAST_1_AWS_BUCKET_REGION.equals(region)) {
+ // The SDK has changed such that if the region is us-east-1
+ // the region value should not be provided in the
+ // request to create the bucket.
+ // See https://stackoverflow.com/questions/51912072/invalidlocationconstraint-error-while-creating-s3-bucket-when-the-used-command-i
+ bucketRegion = null;
+ }
+ CreateBucketRequest req = new CreateBucketRequest(bucket, bucketRegion);
s3service.createBucket(req);
if (Utils.waitForBucket(s3service, bucket)) {
LOG.error("Bucket [{}] does not exist in [{}] and was not automatically created",
Modified: jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/Utils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/Utils.java?rev=1884613&r1=1884612&r2=1884613&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/Utils.java (original)
+++ jackrabbit/oak/trunk/oak-blob-cloud/src/main/java/org/apache/jackrabbit/oak/blob/cloud/s3/Utils.java Fri Dec 18 22:26:00 2020
@@ -24,6 +24,10 @@ import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.amazonaws.AmazonClientException;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
@@ -36,9 +40,6 @@ import com.amazonaws.services.s3.model.O
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.util.StringUtils;
import com.google.common.collect.Maps;
-import org.jetbrains.annotations.NotNull;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Amazon S3 utilities.
@@ -57,6 +58,11 @@ public final class Utils {
public static final String DEFAULT_AWS_BUCKET_REGION = "us-standard";
/**
+ * The value for the us-east-1 region.
+ */
+ public static final String US_EAST_1_AWS_BUCKET_REGION = "us-east-1";
+
+ /**
* constants to define endpoint to various AWS region
*/
public static final String AWSDOTCOM = "amazonaws.com";
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=1884613&r1=1884612&r2=1884613&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 Fri Dec 18 22:26:00 2020
@@ -22,13 +22,15 @@ package org.apache.jackrabbit.oak.plugin
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;
+import com.google.common.base.Charsets;
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.Sets;
+
/**
* Contains download options for downloading a data record directly from a
* storage location using the direct download feature.
@@ -155,9 +157,12 @@ public class DataRecordDownloadOptions {
private String formatContentDispositionHeader(@NotNull final String dispositionType,
@NotNull final String fileName,
@Nullable final String rfc8187EncodedFileName) {
+ String iso_8859_1_fileName = new String(Charsets.ISO_8859_1.encode(fileName).array()).replace("\"", "\\\"");
return null != rfc8187EncodedFileName ?
- String.format("%s; filename=\"%s\"; filename*=UTF-8''%s", dispositionType, fileName, rfc8187EncodedFileName) :
- String.format("%s; filename=\"%s\"", dispositionType, fileName);
+ String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
+ dispositionType, iso_8859_1_fileName, rfc8187EncodedFileName) :
+ String.format("%s; filename=\"%s\"",
+ dispositionType, iso_8859_1_fileName);
}
private String rfc8187Encode(@NotNull final String input) {
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=1884613&r1=1884612&r2=1884613&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 Fri Dec 18 22:26:00 2020
@@ -18,15 +18,6 @@
*/
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.StringWriter;
@@ -35,14 +26,12 @@ import java.net.URI;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.net.ssl.HttpsURLConnection;
-import com.google.common.base.Strings;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.core.data.DataIdentifier;
import org.apache.jackrabbit.core.data.DataRecord;
@@ -55,6 +44,19 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+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);
@@ -174,42 +176,67 @@ public abstract class AbstractDataRecord
@Test
public void testGetDownloadURIWithCustomHeadersIT() throws DataStoreException, IOException {
+ List<String> fileNames = Lists.newArrayList(
+ "image.png",
+ "beautiful landscape.png",
+ "\"filename-with-double-quotes\".png",
+ "filename-with-one\"double-quote.jpg",
+ "UmlaÌutfile.png"
+ );
+ List<String> iso_8859_1_fileNames = Lists.newArrayList(
+ "image.png",
+ "beautiful landscape.png",
+ "\\\"filename-with-double-quotes\\\".png",
+ "filename-with-one\\\"double-quote.jpg",
+ "Umla?utfile.png"
+ );
+ List<String> rfc8187_fileNames = Lists.newArrayList(
+ "image.png",
+ "beautiful%20landscape.png",
+ "%22filename-with-double-quotes%22.png",
+ "filename-with-one%22double-quote.jpg",
+ "Umla%CC%88utfile.png"
+ );
+
DataRecord record = null;
DataRecordAccessProvider dataStore = getDataStore();
try {
InputStream testStream = randomStream(0, 256);
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(
- new BlobDownloadOptions(
- mimeType,
- null,
- fileName,
- dispositionType
- )
- );
- URI uri = dataStore.getDownloadURI(record.getIdentifier(),
- downloadOptions);
+ for (int i=0; i<fileNames.size(); i++) {
+ String fileName = fileNames.get(i);
+ String iso_8859_1_fileName = iso_8859_1_fileNames.get(i);
+ String encodedFileName = rfc8187_fileNames.get(i);
+ DataRecordDownloadOptions downloadOptions =
+ DataRecordDownloadOptions.fromBlobDownloadOptions(
+ new BlobDownloadOptions(
+ mimeType,
+ null,
+ fileName,
+ dispositionType
+ )
+ );
+ URI uri = dataStore.getDownloadURI(record.getIdentifier(),
+ downloadOptions
+ );
+
+ HttpsURLConnection conn = (HttpsURLConnection) uri.toURL().openConnection();
+ conn.setRequestMethod("GET");
+ assertEquals(200, conn.getResponseCode());
+
+ assertEquals(mimeType, conn.getHeaderField("Content-Type"));
+ assertEquals(
+ String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
+ dispositionType, iso_8859_1_fileName, encodedFileName
+ ),
+ conn.getHeaderField("Content-Disposition")
+ );
- HttpsURLConnection conn = (HttpsURLConnection) uri.toURL().openConnection();
- conn.setRequestMethod("GET");
- assertEquals(200, conn.getResponseCode());
-
- assertEquals(mimeType, conn.getHeaderField("Content-Type"));
- assertEquals(
- String.format("%s; filename=\"%s\"; filename*=UTF-8''%s",
- dispositionType, fileName,
- encodedFileName
- ),
- conn.getHeaderField("Content-Disposition")
- );
-
- testStream.reset();
- assertTrue(Arrays.equals(toByteArray(testStream), toByteArray(conn.getInputStream())));
+ testStream.reset();
+ assertTrue(Arrays.equals(toByteArray(testStream), toByteArray(conn.getInputStream())));
+ }
}
finally {
if (null != record) {
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=1884613&r1=1884612&r2=1884613&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 Fri Dec 18 22:26:00 2020
@@ -19,16 +19,19 @@
package org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
+import java.util.List;
+
+import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
+import org.junit.Test;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
-import org.apache.jackrabbit.oak.api.blob.BlobDownloadOptions;
-import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
public class DataRecordDownloadOptionsTest {
private static final String MEDIA_TYPE_IMAGE_PNG = "image/png";
@@ -255,4 +258,44 @@ public class DataRecordDownloadOptionsTe
null
);
}
+
+ @Test
+ public void testGetContentDispositionWithSpecialCharacterFilenames() {
+ List<String> filenames = Lists.newArrayList(
+ "image.png",
+ "text.txt",
+ "filename with spaces.jpg",
+ "\"filename-with-double-quotes\".jpg",
+ "filename-with-one\"double-quote.jpg",
+ "UmlaÌutfile.jpg"
+ );
+ List<String> iso_8859_1_filenames = Lists.newArrayList(
+ "image.png",
+ "text.txt",
+ "filename with spaces.jpg",
+ "\\\"filename-with-double-quotes\\\".jpg",
+ "filename-with-one\\\"double-quote.jpg",
+ "Umla?utfile.jpg"
+ );
+ List<String> rfc8187_filenames = Lists.newArrayList(
+ "image.png",
+ "text.txt",
+ "filename%20with%20spaces.jpg",
+ "%22filename-with-double-quotes%22.jpg",
+ "filename-with-one%22double-quote.jpg",
+ "Umla%CC%88utfile.jpg"
+ );
+
+ for (String dispositionType : Lists.newArrayList(DISPOSITION_TYPE_INLINE, DISPOSITION_TYPE_ATTACHMENT)) {
+ for (int i=0; i<filenames.size(); i++) {
+ String fileName = filenames.get(i);
+ String iso_8859_1_fileName = iso_8859_1_filenames.get(i);
+ String rfc8187_fileName = rfc8187_filenames.get(i);
+ verifyContentDispositionHeader(
+ getOptions(null, null, fileName, dispositionType),
+ getContentDispositionHeader(iso_8859_1_fileName, rfc8187_fileName, dispositionType)
+ );
+ }
+ }
+ }
}