diff --git a/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRendition.java b/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRendition.java index 69d271ac3..cc9a5577c 100644 --- a/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRendition.java +++ b/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRendition.java @@ -19,13 +19,13 @@ package com.adobe.aem.commons.assetshare.content.renditions; +import com.adobe.aem.commons.assetshare.util.UrlUtil; +import com.day.text.Text; +import org.apache.http.client.utils.URIUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.Optional; /** @@ -46,13 +46,8 @@ public AssetRendition(URI uri, Long size, String mimeType) { } public AssetRendition(String uri, Long size, String mimeType) { - try { - uri = URLEncoder.encode(uri, "UTF-8"); - } catch (UnsupportedEncodingException ex) { - log.warn("Unable to encode String URI [ {} ] using UTF-8. Continuing using URI unencoded...", uri); - } - uri = uri.replace("+", "%20"); + uri = UrlUtil.escape(uri, true); setBinaryUri(URI.create(uri)); setSize(size); diff --git a/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImpl.java b/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImpl.java index 684dba124..258c44993 100644 --- a/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImpl.java +++ b/core/src/main/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImpl.java @@ -146,6 +146,8 @@ public AssetRendition getRendition(AssetModel assetModel, AssetRenditionParamete if (StringUtils.isNotBlank(renditionRedirect)) { try { + renditionRedirect = UrlUtil.escape(renditionRedirect, true); + final String extension = getExtensionFromAscExtQueryParameter(renditionRedirect); renditionRedirect = cleanURI(renditionRedirect); diff --git a/core/src/main/java/com/adobe/aem/commons/assetshare/util/UrlUtil.java b/core/src/main/java/com/adobe/aem/commons/assetshare/util/UrlUtil.java index 896d45660..8a2786e18 100644 --- a/core/src/main/java/com/adobe/aem/commons/assetshare/util/UrlUtil.java +++ b/core/src/main/java/com/adobe/aem/commons/assetshare/util/UrlUtil.java @@ -21,16 +21,14 @@ import com.day.text.Text; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; public class UrlUtil { + private static final Logger log = LoggerFactory.getLogger(UrlUtil.class); /** * This variant is the default behavior and prevents double escaping. @@ -77,6 +75,7 @@ public static final String escape(final String unescaped, final boolean preventD } catch (MalformedURLException e) { // Treat as internal path + log.debug("Could not evaluate unescaped string [ {} ] as a URL. Falling back to escape as path.", e); return escapePath(tmp); } } diff --git a/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRenditionTest.java b/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRenditionTest.java new file mode 100644 index 000000000..f8dccb11b --- /dev/null +++ b/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/AssetRenditionTest.java @@ -0,0 +1,43 @@ +package com.adobe.aem.commons.assetshare.content.renditions; + +import com.adobe.aem.commons.assetshare.util.UrlUtil; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class AssetRenditionTest { + + @Test + public void getBinaryUri() { + + AssetRendition assetRendition = new AssetRendition("/content/dam/test.jpg", 123L, "image/jpeg"); + assertEquals("/content/dam/test.jpg", assetRendition.getBinaryUri().toString()); + + assetRendition = new AssetRendition("/content/dam/test asset.jpg", 123L, "image/jpeg"); + assertEquals("/content/dam/test%20asset.jpg", assetRendition.getBinaryUri().toString()); + + assetRendition = new AssetRendition("/content/dam/test+with+plus.jpg", 123L, "image/jpeg"); + assertEquals("/content/dam/test%2bwith%2bplus.jpg", assetRendition.getBinaryUri().toString()); + + assetRendition = new AssetRendition("https://test.com/content/dam/test asset.jpg", 123L, "image/jpeg"); + assertEquals("https://test.com/content/dam/test%20asset.jpg", assetRendition.getBinaryUri().toString()); + + assetRendition = new AssetRendition("https://smartimaging.scene7.com/is/image/DynamicMediaNA/test (test):Medium", 123L, "image/jpeg"); + assertEquals("https://smartimaging.scene7.com/is/image/DynamicMediaNA/test%20(test)%3aMedium", assetRendition.getBinaryUri().toString()); + + assetRendition = new AssetRendition("https://smartimaging.scene7.com/is/image/DynamicMediaNA/test (test)?$grayscale$", 123L, "image/jpeg"); + assertEquals("https://smartimaging.scene7.com/is/image/DynamicMediaNA/test%20(test)?$grayscale$", assetRendition.getBinaryUri().toString()); + } + + @Test + public void getSize() { + AssetRendition assetRendition = new AssetRendition("/content/dam/test.jpg", 123L, "image/jpeg"); + assertEquals(Long.valueOf(123), assetRendition.getSize().get()); + } + + @Test + public void getMimeType() { + AssetRendition assetRendition = new AssetRendition("/content/dam/test.jpg", 123L, "image/jpeg"); + assertEquals("image/jpeg", assetRendition.getMimeType()); + } +} \ No newline at end of file diff --git a/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImplTest.java b/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImplTest.java index cf081fa9c..44d654710 100644 --- a/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImplTest.java +++ b/core/src/test/java/com/adobe/aem/commons/assetshare/content/renditions/impl/dispatchers/ExternalRedirectRenditionDispatcherImplTest.java @@ -185,4 +185,27 @@ public void dispatch_WithSpacesInPath() throws IOException, ServletException { assertEquals(302, ctx.response().getStatus()); assertEquals("/content/dam/test%20with%20spaces.png.test.500.500.png", ctx.response().getHeader("Location")); } + + + @Test + public void dispatch_WithHostAndSpacesInPath() throws IOException, ServletException { + ctx.registerInjectActivateService(new ExternalRedirectRenditionDispatcherImpl(), + ImmutableMap.builder(). + put("rendition.mappings", new String[]{ + "testing=https://test.com${asset.path}.test.500.500.${asset.extension}"}). + put("redirect", 302). + build()); + + final AssetRenditionDispatcher assetRenditionDispatcher = ctx.getService(AssetRenditionDispatcher.class); + + doReturn(DamUtil.resolveToAsset(ctx.resourceResolver().getResource("/content/dam/test with spaces.png"))).when(assetResolver).resolveAsset(ctx.request()); + ctx.currentResource("/content/dam/test with spaces.png"); + ctx.requestPathInfo().setExtension("rendition"); + ctx.requestPathInfo().setSuffix("testing/download/asset.rendition"); + + assetRenditionDispatcher.dispatch(ctx.request(), ctx.response()); + + assertEquals(302, ctx.response().getStatus()); + assertEquals("https://test.com/content/dam/test%20with%20spaces.png.test.500.500.png", ctx.response().getHeader("Location")); + } } \ No newline at end of file