From 8b1baaa6005613e74bd8738981e28280fb296fa8 Mon Sep 17 00:00:00 2001 From: Pedro Santos Date: Sat, 21 Dec 2024 16:23:27 -0300 Subject: [PATCH] WICKET-7137 move sanitizer code to PackageResourceUrlSanitizer --- .../mapper/BasicResourceReferenceMapper.java | 2 +- .../resource/IResourceUrlSanitizer.java | 42 +++++++++++++ .../request/resource/PackageResource.java | 27 +------- .../resource/PackageResourceReference.java | 2 +- .../resource/PackageResourceUrlSanitizer.java | 62 +++++++++++++++++++ .../request/resource/ResourceReference.java | 12 ++++ .../wicket/settings/ResourceSettings.java | 23 +++++++ 7 files changed, 142 insertions(+), 28 deletions(-) create mode 100644 wicket-core/src/main/java/org/apache/wicket/request/resource/IResourceUrlSanitizer.java create mode 100644 wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceUrlSanitizer.java diff --git a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapper.java b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapper.java index 73edb9c6104..d353cd22740 100755 --- a/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapper.java +++ b/wicket-core/src/main/java/org/apache/wicket/core/request/mapper/BasicResourceReferenceMapper.java @@ -132,7 +132,7 @@ public IRequestHandler mapRequest(Request request) if (scope != null && scope.getPackage() != null) { - ResourceReference.UrlAttributes sanitized = PackageResource.sanitize(attributes, scope, name.toString()); + ResourceReference.UrlAttributes sanitized = attributes.sanitize(scope, name.toString()); boolean createIfNotFound = false; if (sanitized != null) { diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/IResourceUrlSanitizer.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/IResourceUrlSanitizer.java new file mode 100644 index 00000000000..ecb1ee9c35b --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/IResourceUrlSanitizer.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.request.resource; + +import org.apache.wicket.request.resource.ResourceReference.UrlAttributes; + +/** + * Sanitizes the resource URL parameters. Implementations should be concerned to return a set of + * style/locale/variation that is safe to end up as keys in the server resource cache, without + * causing unnecessary values to be kept in the primary memory. + * + * @author Pedro Santos + */ +public interface IResourceUrlSanitizer +{ + + /** + * Sanitizes the {@link UrlAttributes} and returns a new instance with style/locale/variation + * values that are safe to be kept in-memory. + * + * @param urlAttributes + * @param scope + * @param name + * @return null if there are no resource matching the scope/name + */ + public UrlAttributes sanitize(UrlAttributes urlAttributes, Class scope, String name); + +} diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java index 49df1dd8ae8..64c1845ee4f 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResource.java @@ -706,7 +706,7 @@ public static boolean exists(final Class scope, final String path, final Loca return getResourceStream(scope, path, locale, style, variation, true) != null; } - private static IResourceStream getResourceStream(final Class scope, final String path, final Locale locale, + public static IResourceStream getResourceStream(final Class scope, final String path, final Locale locale, final String style, final String variation, final boolean updateCache) { String absolutePath = Packages.absolutePath(scope, path); @@ -869,29 +869,4 @@ public PackageResource readBuffered(boolean readBuffered) return this; } - /** - * @return UrlAttributes with an existent locale/style/variation if a resource is bound to the - * scope+name, otherwise returns null - */ - public static ResourceReference.UrlAttributes sanitize( - ResourceReference.UrlAttributes urlAttributes, Class scope, String name) - { - IResourceStream filesystemMatch = getResourceStream(scope, name, urlAttributes.getLocale(), - urlAttributes.getStyle(), urlAttributes.getVariation(), false); - if (filesystemMatch == null) - { - return null; - } - try - { - filesystemMatch.close(); - } - catch (IOException e) - { - log.error("failed to close", e); - } - return new ResourceReference.UrlAttributes(filesystemMatch.getLocale(), - filesystemMatch.getStyle(), filesystemMatch.getVariation()); - } - } diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceReference.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceReference.java index 3a5958cfd9d..5129ac27a96 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceReference.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceReference.java @@ -123,7 +123,7 @@ public PackageResource getResource() //resource attributes (locale, style, variation) might be encoded in the URL final Url url = requestCycle.getRequest().getUrl(); urlAttributes = ResourceUtil.decodeResourceReferenceAttributes(url); - urlAttributes = PackageResource.sanitize(urlAttributes, scope, name); + urlAttributes = urlAttributes.sanitize(scope, name); } String currentVariation = getCurrentVariation(urlAttributes); diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceUrlSanitizer.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceUrlSanitizer.java new file mode 100644 index 00000000000..ad264d6d2a7 --- /dev/null +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/PackageResourceUrlSanitizer.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.wicket.request.resource; + +import static org.apache.wicket.request.resource.PackageResource.getResourceStream; + +import java.io.IOException; + +import org.apache.wicket.request.resource.ResourceReference.UrlAttributes; +import org.apache.wicket.util.resource.IResourceStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Sanitizes the URL based on existing package resource style/locale/variations + * + * @author Pedro Santos + */ +public class PackageResourceUrlSanitizer implements IResourceUrlSanitizer +{ + private static final Logger log = LoggerFactory.getLogger(PackageResourceUrlSanitizer.class); + + /** + * @return UrlAttributes with an existent locale/style/variation if a resource is bound to the + * scope+name, otherwise returns null + */ + @Override + public UrlAttributes sanitize(UrlAttributes urlAttributes, Class scope, String name) + { + IResourceStream filesystemMatch = getResourceStream(scope, name, urlAttributes.getLocale(), + urlAttributes.getStyle(), urlAttributes.getVariation(), false); + if (filesystemMatch == null) + { + return null; + } + try + { + filesystemMatch.close(); + } + catch (IOException e) + { + log.error("failed to close", e); + } + return new ResourceReference.UrlAttributes(filesystemMatch.getLocale(), + filesystemMatch.getStyle(), filesystemMatch.getVariation()); + } + +} diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java index 7e97cab8d6d..9b96144ff2c 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/ResourceReference.java @@ -350,6 +350,18 @@ public String getVariation() return variation; } + /** + * @param scope + * @param name + * @return sanitized URL attributes if a sanitizer is set for the app + */ + public UrlAttributes sanitize(Class scope, String name) + { + IResourceUrlSanitizer sanitizer = Application.get().getResourceSettings() + .getUrlSanitizer(); + return sanitizer == null ? this : sanitizer.sanitize(this, scope, name); + } + @Override public boolean equals(Object obj) { diff --git a/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java b/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java index 9c56ce1d54a..b8966c50a8e 100644 --- a/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java +++ b/wicket-core/src/main/java/org/apache/wicket/settings/ResourceSettings.java @@ -36,6 +36,8 @@ import org.apache.wicket.markup.html.IPackageResourceGuard; import org.apache.wicket.markup.html.SecurePackageResourceGuard; import org.apache.wicket.request.http.WebResponse; +import org.apache.wicket.request.resource.IResourceUrlSanitizer; +import org.apache.wicket.request.resource.PackageResourceUrlSanitizer; import org.apache.wicket.request.resource.caching.FilenameWithVersionResourceCachingStrategy; import org.apache.wicket.request.resource.caching.IResourceCachingStrategy; import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy; @@ -163,6 +165,9 @@ public class ResourceSettings implements IPropertiesFactoryContext // resource caching strategy private IResourceCachingStrategy resourceCachingStrategy; + // resource URL sanitizer + private IResourceUrlSanitizer resourceUrlSanitizer = new PackageResourceUrlSanitizer(); + // application these settings are bound to private final Application application; @@ -690,6 +695,24 @@ public ResourceSettings setCachingStrategy(IResourceCachingStrategy strategy) return this; } + /** + * @return the resource URL sanitizer, null if none + */ + public IResourceUrlSanitizer getUrlSanitizer() + { + return resourceUrlSanitizer; + } + + /** + * Sets the resource URL sanitizer + * + * @param resourceUrlSanitizer + */ + public void setUrlSanitizer(IResourceUrlSanitizer resourceUrlSanitizer) + { + this.resourceUrlSanitizer = resourceUrlSanitizer; + } + /** * Sets whether to use pre-minified resources when available. Minified resources are detected by * name. The minified version of {@code x.js} is expected to be called {@code x.min.js}. For css