Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WICKET-7024 decode PackageResourceReference URL attributes only insid… #1021

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,29 @@
*/
package org.apache.wicket.core.request.resource;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.StringContains.containsString;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.times;

import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;

import org.apache.wicket.Application;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.ThreadContext;
import org.apache.wicket.core.util.resource.UrlResourceStream;
import org.apache.wicket.core.util.resource.locator.IResourceStreamLocator;
import org.apache.wicket.core.util.resource.locator.caching.CachingResourceStreamLocator;
import org.apache.wicket.markup.IMarkupResourceStreamProvider;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
import org.apache.wicket.protocol.http.mock.MockHttpServletResponse;
import org.apache.wicket.request.Request;
Expand All @@ -43,8 +55,12 @@
import org.apache.wicket.request.resource.ResourceReference.UrlAttributes;
import org.apache.wicket.response.ByteArrayResponse;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.tester.WicketTestCase;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

/**
Expand All @@ -53,6 +69,7 @@
class PackageResourceReferenceTest extends WicketTestCase
{
private static Class<PackageResourceReferenceTest> scope = PackageResourceReferenceTest.class;
private static final Locale defaultLocale = Locale.CHINA;
private static final Locale[] locales = { null, new Locale("en"), new Locale("en", "US") };
private static final String[] styles = { null, "style" };
private static final String[] variations = { null, "var" };
Expand Down Expand Up @@ -396,4 +413,110 @@ void noRequestCycle()
assertEquals(variations[1], resource.getResourceStream().getVariation());
}

@Test
public void getResourceWithNoStyle()
{
tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css");

assertThat(tester.getLastResponseAsString(), not(containsString("color")));
}

@Test
public void getStyleFromSession()
{
tester.getSession().setStyle("blue");
tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css");

assertThat(tester.getLastResponseAsString(), containsString("blue"));
}

@Test
public void decodeStyleFromUrl()
{
tester.getSession().setStyle("blue");
tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css?-orange");

assertThat(tester.getLastResponseAsString(), containsString("orange"));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also assert that there is no blue

assertThat(tester.getLastResponseAsString(), not(containsString("blue")));
}

@Test
@Disabled
public void doNotFindResourceInTheCache()
{
IResourceStreamLocator resourceStreamLocator = mock(IResourceStreamLocator.class);
when(resourceStreamLocator.locate(scope, "org/apache/wicket/core/request/resource/a.css",
"yellow", null, defaultLocale, null, false)).thenReturn(
new UrlResourceStream(scope.getResource("a.css")));

tester.getApplication().getResourceSettings()
.setResourceStreamLocator(new CachingResourceStreamLocator(resourceStreamLocator));

tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css?-yellow");
tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css?-yellow");

verify(resourceStreamLocator, times(2)).locate(PackageResourceReferenceTest.class,
"org/apache/wicket/core/request/resource/a.css", "yellow", null, defaultLocale, null, false);
}

@Test
public void doNotFindMountedResourceInTheCache()
{
IResourceStreamLocator resourceStreamLocator = mock(IResourceStreamLocator.class);
when(resourceStreamLocator.locate(scope, "org/apache/wicket/core/request/resource/a.css",
"yellow", null, defaultLocale, null, false)).thenReturn(
new UrlResourceStream(scope.getResource("a.css")));

tester.getApplication().getResourceSettings()
.setResourceStreamLocator(new CachingResourceStreamLocator(resourceStreamLocator));
tester.getApplication()
.mountResource("/a.css", new PackageResourceReference(scope, "a.css"));

tester.executeUrl("a.css?-yellow");
tester.executeUrl("a.css?-yellow");

verify(resourceStreamLocator, times(2)).locate(scope,
"org/apache/wicket/core/request/resource/a.css", "yellow", null, defaultLocale, null,
false);
}

/**
* @see https://issues.apache.org/jira/browse/WICKET-7024
*/
@Test
public void notDecodeStyleFromUrl()
{
tester.executeUrl(
"wicket/bookmarkable/org.apache.wicket.core.request.resource.PackageResourceReferenceTest$TestPage?0-1.0-resumeButton&_=1730041277224");

TestPage page = (TestPage)tester.getLastRenderedPage();

assertThat(page.resource.getStyle(), not(is("1.0")));
}

public static class TestPage extends WebPage implements IMarkupResourceStreamProvider
{
CssPackageResource resource;

@Override
protected void onConfigure()
{
super.onConfigure();
resource = (CssPackageResource)new PackageResourceReference(scope, "a.css")
.getResource();
}

@Override
public IResourceStream getMarkupResourceStream(MarkupContainer container,
Class<?> containerClass)
{
return new StringResourceStream("<html><head></head><body></body></html>");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.a{
color: blue;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.a{
color: orange;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@
import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
import org.apache.wicket.request.mapper.parameter.IPageParametersEncoder;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.request.resource.IResource;
import org.apache.wicket.request.resource.MetaInfStaticResourceReference;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.request.resource.ResourceReferenceRegistry;
import org.apache.wicket.request.resource.*;
import org.apache.wicket.request.resource.caching.IResourceCachingStrategy;
import org.apache.wicket.request.resource.caching.IStaticCacheableResource;
import org.apache.wicket.request.resource.caching.ResourceUrl;
Expand Down Expand Up @@ -133,6 +130,8 @@ public IRequestHandler mapRequest(Request request)

Class<?> scope = resolveClass(className);

// attributes = PackageResource.sanitize(attributes, scope, name.toString());

if (scope != null && scope.getPackage() != null)
{
ResourceReference res = getContext().getResourceReferenceRegistry()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,18 @@ else if (stream instanceof UrlResourceStream)
}
}

/**
* @deprecated
*/
@Override
public IResourceStream locate(Class<?> scope, String path, String style, String variation,
Locale locale, String extension, boolean strict)
{
return locate(scope, path, style, variation, locale, extension, strict, true);
}

public IResourceStream locate(Class<?> scope, String path, String style, String variation,
Locale locale, String extension, boolean strict, boolean updateCache)
{
CacheKey key = new CacheKey(scope.getName(), path, extension, locale, style, variation, strict);
IResourceStreamReference resourceStreamReference = cache.get(key);
Expand All @@ -121,7 +130,10 @@ public IResourceStream locate(Class<?> scope, String path, String style, String
{
result = delegate.locate(scope, path, style, variation, locale, extension, strict);

updateCache(key, result);
if (updateCache)
{
updateCache(key, result);
}
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.core.util.lang.WicketObjects;
import org.apache.wicket.core.util.resource.locator.IResourceStreamLocator;
import org.apache.wicket.core.util.resource.locator.caching.CachingResourceStreamLocator;
import org.apache.wicket.javascript.IJavaScriptCompressor;
import org.apache.wicket.markup.html.IPackageResourceGuard;
import org.apache.wicket.mock.MockWebRequest;
Expand Down Expand Up @@ -149,6 +150,13 @@ public PackageResourceBlockedException(String message)
*/
private boolean cachingEnabled = true;

/**
* controls whether
* {@link org.apache.wicket.core.util.resource.locator.caching.CachingResourceStreamLocator}
* should update the cache
*/
private boolean serverResourceStreamReferenceCacheUpdate = true;

/**
* text encoding (may be null) - only makes sense for character-based resources
*/
Expand Down Expand Up @@ -240,6 +248,27 @@ public void setCachingEnabled(final boolean enabled)
this.cachingEnabled = enabled;
}

/**
* Returns true if the cache should be updated for this resource
*
* @return if the cache update is enabled
*/
public boolean isServerResourceStreamReferenceCacheUpdate()
{
return serverResourceStreamReferenceCacheUpdate;
}

/**
* Sets the cache update for this resource to be enabled
*
* @param enabled
* if the cache update should be enabled
*/
public void setServerResourceStreamReferenceCacheUpdate(final boolean enabled)
{
this.serverResourceStreamReferenceCacheUpdate = enabled;
}

/**
* get text encoding (intended for character-based resources)
*
Expand Down Expand Up @@ -531,8 +560,8 @@ private ResourceResponse sendResourceError(ResourceResponse resourceResponse, in
@Override
public IResourceStream getResourceStream()
{
return internalGetResourceStream(getCurrentStyle(), getCurrentLocale());
}
return internalGetResourceStream(getCurrentStyle(), getCurrentLocale(), isServerResourceStreamReferenceCacheUpdate());
}

/**
* @return whether {@link org.apache.wicket.resource.ITextResourceCompressor} can be used to
Expand All @@ -552,13 +581,23 @@ public void setCompress(boolean compress)
this.compress = compress;
}

private IResourceStream internalGetResourceStream(final String style, final Locale locale)
private IResourceStream internalGetResourceStream(final String style, final Locale locale, boolean updateCache)
{
IResourceStreamLocator resourceStreamLocator = Application.get()
.getResourceSettings()
.getResourceStreamLocator();
IResourceStream resourceStream = resourceStreamLocator.locate(getScope(), absolutePath,
style, variation, locale, null, false);
IResourceStream resourceStream = null;

if (resourceStreamLocator instanceof CachingResourceStreamLocator cache)
{
resourceStream = cache.locate(getScope(), absolutePath, style, variation, locale, null,
false, updateCache);
}
else
{
resourceStream = resourceStreamLocator.locate(getScope(), absolutePath, style,
variation, locale, null, false);
}

String realPath = absolutePath;
if (resourceStream instanceof IFixedLocationResourceStream)
Expand Down Expand Up @@ -855,4 +894,40 @@ public PackageResource readBuffered(boolean readBuffered)
this.readBuffered = readBuffered;
return this;
}

public static ResourceReference.UrlAttributes sanitize(
ResourceReference.UrlAttributes urlAttributes, Class<?> scope, String name)
{
PackageResource urlResource = new PackageResource(scope, name, urlAttributes.getLocale(),
urlAttributes.getStyle(), urlAttributes.getVariation());
urlResource.setServerResourceStreamReferenceCacheUpdate(false);
IResourceStream filesystemMatch = urlResource.getResourceStream();

ResourceReference.Key urlKey = new ResourceReference.Key(scope.getName(), name,
urlAttributes.getLocale(), urlAttributes.getStyle(), urlAttributes.getVariation());

ResourceReference.Key filesystemKey = new ResourceReference.Key(scope.getName(), name,
filesystemMatch.getLocale(), filesystemMatch.getStyle(),
filesystemMatch.getVariation());

try
{
filesystemMatch.close();
}
catch (IOException e)
{
log.error("failed to close", e);
}

if (!urlKey.equals(filesystemKey))
{
return new ResourceReference.UrlAttributes(filesystemKey.getLocale(),
filesystemKey.getStyle(), filesystemKey.getVariation());
}
else
{
return urlAttributes;
}
}

}
Loading