Skip to content

Commit

Permalink
WICKET-7024 URL sanitization for not mounted resources
Browse files Browse the repository at this point in the history
  • Loading branch information
pedrosans committed Nov 1, 2024
1 parent 755a63a commit 117d4f5
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public ResourceReferenceRegistry getResourceReferenceRegistry()
private final ResourceReferenceRegistry registry = new ResourceReferenceRegistry()
{
@Override
protected ResourceReference createDefaultResourceReference(Key key)
protected ResourceReference createDefaultResourceReference(Key key, boolean updateCache)
{
// Do not create package resource here because it requires "real" application
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.mock.MockApplication;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.resource.CssPackageResource;
import org.apache.wicket.request.resource.CssResourceReference;
import org.apache.wicket.request.resource.PackageResource;
import org.apache.wicket.request.resource.ResourceReference;
import org.apache.wicket.request.resource.ResourceReferenceRegistry;
import org.apache.wicket.request.resource.*;
import org.apache.wicket.util.file.Files;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
Expand All @@ -54,7 +50,7 @@ class LessResourceReferenceTest extends WicketTestCase
* An {@link org.apache.wicket.request.resource.IResourceReferenceFactory} that creates
* LessResourceReference for resources with extension '.less'
*/
static class LessResourceReferenceFactory extends ResourceReferenceRegistry.DefaultResourceReferenceFactory
static class LessResourceReferenceFactory implements IResourceReferenceFactory
{
@Override
public ResourceReference create(ResourceReference.Key key)
Expand All @@ -68,7 +64,8 @@ public ResourceReference create(ResourceReference.Key key)
}
else
{
result = super.create(key);
result = new ResourceReferenceRegistry.DefaultResourceReferenceFactory().create(
key);
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
class PackageResourceReferenceTest extends WicketTestCase
{
private static Class<PackageResourceReferenceTest> scope = PackageResourceReferenceTest.class;
private static final Locale defaultLocale = Locale.CHINA;
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 @@ -444,13 +444,15 @@ public void decodeStyleFromUrl()
}

@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")));
when(resourceStreamLocator.locate(scope, "org/apache/wicket/core/request/resource/a.css",
"yellow", null, null, null, false)).thenReturn(
new UrlResourceStream(scope.getResource("a.css")));

tester.getApplication().getResourceSettings()
.setResourceStreamLocator(new CachingResourceStreamLocator(resourceStreamLocator));
Expand All @@ -460,8 +462,12 @@ public void doNotFindResourceInTheCache()
tester.executeUrl(
"wicket/resource/org.apache.wicket.core.request.resource.PackageResourceReferenceTest/a.css?-yellow");

// WICKET-7129: proposal to remove the duplicated resource resolution
verify(resourceStreamLocator, times(2)).locate(PackageResourceReferenceTest.class,
"org/apache/wicket/core/request/resource/a.css", "yellow", null, null, null, false);
verify(resourceStreamLocator, times(2)).locate(PackageResourceReferenceTest.class,
"org/apache/wicket/core/request/resource/a.css", "yellow", null, defaultLocale, null, false);
"org/apache/wicket/core/request/resource/a.css", "yellow", null, defaultLocale, null,
false);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,20 @@ public IRequestHandler mapRequest(Request request)

Class<?> scope = resolveClass(className);

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

if (scope != null && scope.getPackage() != null)
{
ResourceReference auxRes = getContext().getResourceReferenceRegistry()
.getResourceReference(scope, name.toString(), attributes.getLocale(),
attributes.getStyle(), attributes.getVariation(), true, true, false);
if (auxRes != null)
{
IResource resource = auxRes.getResource();
if (resource instanceof PackageResource packageResource)
{
attributes = PackageResource.sanitize(attributes, scope, name.toString());
}
}

ResourceReference res = getContext().getResourceReferenceRegistry()
.getResourceReference(scope, name.toString(), attributes.getLocale(),
attributes.getStyle(), attributes.getVariation(), true, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -737,15 +737,50 @@ public static boolean exists(final ResourceReference.Key key)
* @param variation
* The component's variation (of the style)
* @return {@code true} if a resource could be loaded, {@code false} otherwise
*
* @deprecated @see {@link PackageResource#exists(Class, String, Locale, String, String, boolean)}
*/
public static boolean exists(final Class<?> scope, final String path, final Locale locale,
final String style, final String variation)
{
return exists(scope, path, locale, style, variation, true);
}

/**
* Checks whether a resource for a given set of criteria exists.
*
* @param scope
* This argument will be used to get the class loader for loading the package
* resource, and to determine what package it is in. Typically this is the class in
* which you call this method
* @param path
* The path to the resource
* @param locale
* The locale of the resource
* @param style
* The style of the resource (see {@link org.apache.wicket.Session})
* @param variation
* The component's variation (of the style)
* @param updateCache
* if the server resource stream reference cache should be updated
* @return {@code true} if a resource could be loaded, {@code false} otherwise
*/
public static boolean exists(final Class<?> scope, final String path, final Locale locale,
final String style, final String variation, final boolean updateCache)
{
String absolutePath = Packages.absolutePath(scope, path);
return Application.get()
.getResourceSettings()
.getResourceStreamLocator()
.locate(scope, absolutePath, style, variation, locale, null, false) != null;
IResourceStreamLocator resourceStreamLocator = Application.get().getResourceSettings()
.getResourceStreamLocator();
if (resourceStreamLocator instanceof CachingResourceStreamLocator cache)
{
return cache.locate(scope, absolutePath, style, variation, locale, null, false,
updateCache) != null;
}
else
{
return resourceStreamLocator.locate(scope, absolutePath, style, variation, locale, null,
false) != null;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,15 @@ public static class DefaultResourceReferenceFactory implements IResourceReferenc
{
@Override
public ResourceReference create(Key key)
{
return create(key, true);
}

public ResourceReference create(Key key, boolean updateCache)
{
ResourceReference result = null;
if (PackageResource.exists(key))
if (PackageResource.exists(key.getScopeClass(), key.getName(), key.getLocale(),
key.getStyle(), key.getVariation(), updateCache))
{
result = new PackageResourceReference(key);
}
Expand Down Expand Up @@ -180,17 +186,28 @@ public final ResourceReference unregisterResourceReference(final Key key)
return removed;
}

/**
* @deprecated @see {@link ResourceReferenceRegistry#getResourceReference(Class, String, Locale, String, String, boolean, boolean, boolean)}
*/
public final ResourceReference getResourceReference(final Class<?> scope, final String name,
final Locale locale, final String style, final String variation, final boolean strict,
final boolean createIfNotFound)
{
return getResourceReference(scope, name, locale, style, variation, strict, createIfNotFound,
true);
}

/**
* Get a resource reference matching the parameters from the registry or if not found and
* requested, create an default resource reference and add it to the registry.
* <p>
* Part of the search is scanning the class (scope) and it's superclass for static
* ResourceReference fields. Found fields get registered automatically (but are different from
* auto-generated ResourceReferences).
*
*
* @see #createDefaultResourceReference(org.apache.wicket.request.resource.ResourceReference.Key)
* @see ClassScanner
*
*
* @param scope
* The scope of resource reference (e.g. the Component's class)
* @param name
Expand All @@ -206,16 +223,25 @@ public final ResourceReference unregisterResourceReference(final Key key)
* @param createIfNotFound
* If true a default resource reference is created if no entry can be found in the
* registry. The newly created resource reference will be added to the registry.
* @param updateCache
* If true, the server resource stream reference cache should be updated
* @return Either the resource reference found in the registry or, if requested, a resource
* reference automatically created based on the parameters provided. The automatically
* created resource reference will automatically be added to the registry.
*/
public final ResourceReference getResourceReference(final Class<?> scope, final String name,
final Locale locale, final String style, final String variation, final boolean strict,
final boolean createIfNotFound)
public ResourceReference getResourceReference(Class<?> scope, String name, Locale locale,
String style, String variation, boolean strict, boolean createIfNotFound, boolean updateCache)
{
return getResourceReference(new Key(scope.getName(), name, locale, style, variation),
strict, createIfNotFound);
strict, createIfNotFound, updateCache);
}

/**
* @deprecated @see {@link ResourceReferenceRegistry#getResourceReference(Key, boolean, boolean, boolean)}
*/
public final ResourceReference getResourceReference(final Key key, final boolean strict,
final boolean createIfNotFound){
return getResourceReference(key, strict, createIfNotFound, true);
}

/**
Expand All @@ -236,12 +262,14 @@ public final ResourceReference getResourceReference(final Class<?> scope, final
* @param createIfNotFound
* If true a default resource reference is created if no entry can be found in the
* registry. The newly created resource reference will be added to the registry.
* @param strict
* If true, the server resource stream reference cache should be updated
* @return Either the resource reference found in the registry or, if requested, a resource
* reference automatically created based on the parameters provided. The automatically
* created resource reference will automatically be added to the registry.
*/
public final ResourceReference getResourceReference(final Key key, final boolean strict,
final boolean createIfNotFound)
final boolean createIfNotFound, boolean updateCache)
{
ResourceReference resource = _getResourceReference(key.getScope(), key.getName(),
key.getLocale(), key.getStyle(), key.getVariation(), strict);
Expand All @@ -262,7 +290,7 @@ public final ResourceReference getResourceReference(final Key key, final boolean
// Still nothing found => Shall a new reference be auto-created?
if ((resource == null) && createIfNotFound)
{
resource = addDefaultResourceReference(key);
resource = addDefaultResourceReference(key, updateCache);
}
}

Expand Down Expand Up @@ -334,12 +362,12 @@ private ResourceReference _getResourceReference(final String scope, final String
* the data making up the resource reference
* @return The default resource created
*/
private ResourceReference addDefaultResourceReference(final Key key)
private ResourceReference addDefaultResourceReference(final Key key, final boolean updateCache)
{
// Can be subclassed to create other than PackagedResourceReference
ResourceReference reference = createDefaultResourceReference(key);
ResourceReference reference = createDefaultResourceReference(key, updateCache);

if (reference != null)
if (reference != null && updateCache)
{
// number of RRs which can be auto-added is restricted (cache size). Remove entries, and
// unregister excessive ones, if needed.
Expand Down Expand Up @@ -383,6 +411,14 @@ private void enforceAutoAddedCacheSize(int maxSize)
}
}

/**
* @deprecated @see {@link ResourceReferenceRegistry#createDefaultResourceReference(Key, boolean)}
*/
protected ResourceReference createDefaultResourceReference(final Key key)
{
return createDefaultResourceReference(key, true);
}

/**
* Creates a default resource reference in case no registry entry and it was requested to create
* one.
Expand All @@ -393,14 +429,20 @@ private void enforceAutoAddedCacheSize(int maxSize)
* the data making up the resource reference
* @return The {@link ResourceReference} created or {@code null} if not successful
*/
protected ResourceReference createDefaultResourceReference(final Key key)
protected ResourceReference createDefaultResourceReference(final Key key, final boolean updateCache)
{
IResourceReferenceFactory factory = getResourceReferenceFactory();
if (factory == null)
{
factory = new DefaultResourceReferenceFactory();
}
return factory.create(key);
if (factory instanceof DefaultResourceReferenceFactory defaultFactory)
{
return defaultFactory.create(key, updateCache);

} else {
return factory.create(key);
}
}

/**
Expand Down

0 comments on commit 117d4f5

Please sign in to comment.