You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:13:36 UTC

[sling-org-apache-sling-security] 06/15: SLING-4604 - Multiple Content-Disposition headers added

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.security-1.0.12
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-security.git

commit bdc96884cd9694180f0e239b68cc5ce06af00170
Author: Antonio Sanso <as...@apache.org>
AuthorDate: Tue Jul 14 12:17:17 2015 +0000

    SLING-4604 - Multiple Content-Disposition headers added
    
    * added patch from Rob Ryan (thanks)
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/security@1690911 13f79535-47bb-0310-9956-ffa450edef68
---
 .../security/impl/ContentDispositionFilter.java    |  13 +-
 .../impl/ContentDispositionFilterTest.java         | 150 ++++++++++++++++++++-
 2 files changed, 159 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java b/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java
index aae95dc..9c0999d 100644
--- a/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java
+++ b/src/main/java/org/apache/sling/security/impl/ContentDispositionFilter.java
@@ -173,6 +173,9 @@ public class ContentDispositionFilter implements Filter {
 
         private static final String CONTENT_DISPOSTION_ATTACHMENT = "attachment";
         
+        static final String ATTRIBUTE_NAME =
+                "org.apache.sling.security.impl.ContentDispositionFilter.RewriterResponse.contentType";
+        
         /** The current request. */
         private final SlingHttpServletRequest request;
 
@@ -185,8 +188,14 @@ public class ContentDispositionFilter implements Filter {
          * @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
          */
         public void setContentType(String type) { 
-            String pathInfo = request.getPathInfo();
+            String previousContentType = (String) request.getAttribute(ATTRIBUTE_NAME);
+            
+            if (previousContentType != null && previousContentType.equals(type)) {
+                return;
+            }
+            request.setAttribute(ATTRIBUTE_NAME, type);
 
+            String pathInfo = request.getPathInfo();
             if (contentDispositionPaths.contains(pathInfo)) {
 
                 if (contentTypesMapping.containsKey(pathInfo)) {
@@ -218,7 +227,9 @@ public class ContentDispositionFilter implements Filter {
         }    
         
         private void setContentDisposition() {
+            if (!this.containsHeader(CONTENT_DISPOSTION)) {
             this.addHeader(CONTENT_DISPOSTION, CONTENT_DISPOSTION_ATTACHMENT);
         }
     }
 }
+}
diff --git a/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java b/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java
index 91d26b1..7c989e7 100644
--- a/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java
+++ b/src/test/java/org/apache/sling/security/impl/ContentDispositionFilterTest.java
@@ -20,9 +20,12 @@ import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.Map;
 import java.util.Set;
+
 import junitx.util.PrivateAccessor;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.security.impl.ContentDispositionFilter.RewriterResponse;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.integration.junit4.JUnit4Mockery;
@@ -221,6 +224,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/libs"));
                 allowing(response).setContentType("text/html");
@@ -254,6 +260,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("text/html");
@@ -282,10 +291,15 @@ public class ContentDispositionFilterTest {
             }
         });    
         PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ComponentContext.class},new Object[]{ctx});
-        ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
+        final ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
         
         context.checking(new Expectations() {
             {
+                allowing(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated"));
                 allowing(response).setContentType("text/html");
@@ -318,6 +332,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/libs"));
                 allowing(response).setContentType("text/html");
@@ -347,10 +364,15 @@ public class ContentDispositionFilterTest {
             }
         });    
         PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ComponentContext.class},new Object[]{ctx});
-        ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
+        final ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
         
         context.checking(new Expectations() {
             {
+                allowing(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("text/html");
@@ -383,6 +405,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated"));
                 allowing(response).setContentType("text/html");
@@ -415,6 +440,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/libs"));
                 allowing(response).setContentType("text/html");
@@ -448,6 +476,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("text/html");
@@ -480,6 +511,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated"));
                 allowing(response).setContentType("text/html");
@@ -508,10 +542,15 @@ public class ContentDispositionFilterTest {
             }
         });    
         PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ComponentContext.class},new Object[]{ctx});
-        ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
+        final ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
         
         context.checking(new Expectations() {
             {
+                allowing(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "image/jpeg");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated"));
                 allowing(response).setContentType("image/jpeg");
@@ -544,6 +583,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/libs"));
                 allowing(response).setContentType("text/html");
@@ -577,6 +619,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("text/html");
@@ -609,6 +654,9 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("text/html");
@@ -641,6 +689,11 @@ public class ContentDispositionFilterTest {
         
         context.checking(new Expectations() {
             {
+                allowing(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                allowing(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "image/jpeg");
                 allowing(request).getPathInfo();
                 will(returnValue("/content/usergenerated/author"));
                 allowing(response).setContentType("image/jpeg");
@@ -650,4 +703,95 @@ public class ContentDispositionFilterTest {
         });       
         rewriterResponse.setContentType("image/jpeg");
     }
+    
+    /**
+     * Test repeated setContentType calls don't add multiple headers, case 1 resetting the same mimetype
+     * @throws Throwable
+     */
+    @Test
+    public void test_doFilter15() throws Throwable{       
+        final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
+        final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
+        contentDispositionFilter = new ContentDispositionFilter();
+        
+        final ComponentContext ctx = context.mock(ComponentContext.class);
+        final Dictionary props = new Hashtable<String, String[]>();
+        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
+        
+        context.checking(new Expectations() {
+            {
+                allowing(ctx).getProperties();
+                will(returnValue(props));
+                
 }
+        });    
+        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ComponentContext.class},new Object[]{ctx});
+        final ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
+        
+        context.checking(new Expectations() {
+            {
+                allowing(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                exactly(1).of(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                exactly(1).of(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue("text/html"));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
+                allowing(request).getPathInfo();
+                will(returnValue("/content/usergenerated"));
+                allowing(response).setContentType("text/html");
+                //CONTENT DISPOSITION IS SET
+                exactly(1).of(response).addHeader("Content-Disposition", "attachment");
+            }
+        });       
+        rewriterResponse.setContentType("text/html");
+        rewriterResponse.setContentType("text/html");
+    } 
+    /**
+     * Test repeated setContentType calls don't add multiple headers, case 2 changing mime type
+     * @throws Throwable
+     */
+    @Test
+    public void test_doFilter16() throws Throwable{       
+        final SlingHttpServletRequest request = context.mock(SlingHttpServletRequest.class);
+        final SlingHttpServletResponse response = context.mock(SlingHttpServletResponse.class);
+        contentDispositionFilter = new ContentDispositionFilter();
+        
+        final ComponentContext ctx = context.mock(ComponentContext.class);
+        final Dictionary props = new Hashtable<String, String[]>();
+        props.put("sling.content.disposition.paths", new String []{"/content/usergenerated"});
+        
+        context.checking(new Expectations() {
+            {
+                allowing(ctx).getProperties();
+                will(returnValue(props));
+                
+            }
+        });    
+        PrivateAccessor.invoke(contentDispositionFilter,"activate",  new Class[]{ComponentContext.class},new Object[]{ctx});
+        final ContentDispositionFilter.RewriterResponse rewriterResponse = contentDispositionFilter. new RewriterResponse(request, response);
+        
+        context.checking(new Expectations() {
+            {
+                exactly(1).of(response).containsHeader("Content-Disposition");
+                will(returnValue(false));
+                exactly(1).of(response).containsHeader("Content-Disposition");
+                will(returnValue(true));
+                exactly(1).of(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue(null));
+                exactly(1).of(request).getAttribute(RewriterResponse.ATTRIBUTE_NAME);
+                will(returnValue("text/html"));
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/xml");
+                allowing(request).setAttribute(RewriterResponse.ATTRIBUTE_NAME, "text/html");
+                allowing(request).getPathInfo();
+                will(returnValue("/content/usergenerated"));
+                allowing(response).setContentType("text/html");
+                allowing(response).setContentType("text/xml");
+                //CONTENT DISPOSITION IS SET
+                exactly(1).of(response).addHeader("Content-Disposition", "attachment");
+            }
+        });       
+        rewriterResponse.setContentType("text/html");
+        rewriterResponse.setContentType("text/xml");
+    }
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.