diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java index 35db96db7a..2dac50810d 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/resource/CssLinkResourceTransformer.java @@ -101,7 +101,10 @@ public class CssLinkResourceTransformer implements ResourceTransformer { for (CssLinkInfo info : sortedInfos) { writer.write(content.substring(index, info.getStart())); String link = content.substring(info.getStart(), info.getEnd()); - String newLink = transformerChain.getResolverChain().resolveUrlPath(link, Arrays.asList(resource)); + String newLink = null; + if(!hasScheme(link)) { + newLink = transformerChain.getResolverChain().resolveUrlPath(link, Arrays.asList(resource)); + } if (logger.isTraceEnabled()) { if (newLink != null && !link.equals(newLink)) { logger.trace("Link modified: " + newLink + " (original: " + link + ")"); @@ -118,6 +121,11 @@ public class CssLinkResourceTransformer implements ResourceTransformer { return new TransformedResource(resource, writer.toString().getBytes(DEFAULT_CHARSET)); } + private boolean hasScheme(String link) { + int schemeIndex = link.indexOf(":"); + return schemeIndex > 0 && !link.substring(0, schemeIndex).contains("/"); + } + protected static interface CssLinkParser { diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/CssLinkResourceTransformerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/CssLinkResourceTransformerTests.java index 6afc078836..a37c7e52da 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/CssLinkResourceTransformerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/CssLinkResourceTransformerTests.java @@ -17,10 +17,12 @@ package org.springframework.web.servlet.resource; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; @@ -77,8 +79,7 @@ public class CssLinkResourceTransformerTests { "@import url(bar-11e16cf79faee7ac698c805cf28248d2.css);\n\n" + "@import \"foo-e36d2e05253c6c7085a91522ce43a0b4.css\";\n" + "@import 'foo-e36d2e05253c6c7085a91522ce43a0b4.css';\n\n" + - "body { background: url(\"images/image-f448cd1d5dba82b774f3202c878230b3.png\") }\n\n" + - "li { list-style: url(http://www.example.com/redball.png) disc }\n"; + "body { background: url(\"images/image-f448cd1d5dba82b774f3202c878230b3.png\") }\n"; String result = new String(transformedResource.getByteArray(), "UTF-8"); result = StringUtils.deleteAny(result, "\r"); @@ -92,4 +93,26 @@ public class CssLinkResourceTransformerTests { assertSame(expected, actual); } + @Test + public void transformExtLinksNotAllowed() throws Exception { + ResourceResolverChain resolverChain = Mockito.mock(DefaultResourceResolverChain.class); + ResourceTransformerChain transformerChain = new DefaultResourceTransformerChain(resolverChain, + Arrays.asList(new CssLinkResourceTransformer())); + + Resource externalCss = new ClassPathResource("test/external.css", getClass()); + Resource resource = transformerChain.transform(this.request, externalCss); + TransformedResource transformedResource = (TransformedResource) resource; + + String expected = "@import url(\"http://example.org/fonts/css\");\n" + + "body { background: url(\"file:///home/spring/image.png\") }"; + String result = new String(transformedResource.getByteArray(), "UTF-8"); + result = StringUtils.deleteAny(result, "\r"); + assertEquals(expected, result); + + Mockito.verify(resolverChain, Mockito.never()) + .resolveUrlPath("http://example.org/fonts/css", Arrays.asList(externalCss)); + Mockito.verify(resolverChain, Mockito.never()) + .resolveUrlPath("file:///home/spring/image.png", Arrays.asList(externalCss)); + } + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/PathResourceResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/PathResourceResolverTests.java new file mode 100644 index 0000000000..e119fde68b --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/PathResourceResolverTests.java @@ -0,0 +1,46 @@ +package org.springframework.web.servlet.resource; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; + +/** + * Unit tests for + * {@link org.springframework.web.servlet.resource.PathResourceResolver}. + * + * @author Brian Clozel + */ +public class PathResourceResolverTests { + + private ResourceResolverChain chain; + + private List locations; + + @Before + public void setup() { + + List resolvers = new ArrayList<>(); + resolvers.add(new PathResourceResolver()); + this.chain = new DefaultResourceResolverChain(resolvers); + + this.locations = new ArrayList<>(); + this.locations.add(new ClassPathResource("test/", getClass())); + } + + @Test + public void resolveResourceInternal() { + String file = "bar.css"; + Resource expected = new ClassPathResource("test/" + file, getClass()); + Resource actual = this.chain.resolveResource(null, file, this.locations); + + assertEquals(expected, actual); + } + +} diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/external.css b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/external.css new file mode 100644 index 0000000000..aa0afb2bbc --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/external.css @@ -0,0 +1,2 @@ +@import url("http://example.org/fonts/css"); +body { background: url("file:///home/spring/image.png") } \ No newline at end of file diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/main.css b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/main.css index ac14294bf3..a6265ea7ac 100644 --- a/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/main.css +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/resource/test/main.css @@ -7,5 +7,3 @@ @import 'foo.css'; body { background: url("images/image.png") } - -li { list-style: url(http://www.example.com/redball.png) disc }