diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java index 8e274dd08..06057f9f1 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java @@ -40,7 +40,7 @@ public class StaticContentTest { public void testInvalidRersources2() throws Exception { try (final WebClient webClient = new WebClient()) { try { - webClient.getPage(ParameterUtils.getBaseUrl() + "/struts/..%252f"); + webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f"); Assert.fail("Previous request should have failed"); } catch (FailingHttpStatusCodeException e) { } @@ -49,7 +49,7 @@ public class StaticContentTest { /*public void testInvalidRersources3() throws IOException { try { - beginAt("/struts/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/"); + beginAt("/static/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/"); fail("Previous request should have failed"); } catch (TestingEngineResponseException ex) { // ok diff --git a/bundles/admin/src/main/resources/osgi/admin/shell.ftl b/bundles/admin/src/main/resources/osgi/admin/shell.ftl index aa7d8a9f2..62d0cce6c 100644 --- a/bundles/admin/src/main/resources/osgi/admin/shell.ftl +++ b/bundles/admin/src/main/resources/osgi/admin/shell.ftl @@ -22,13 +22,13 @@
@@ -43,8 +48,8 @@ import java.util.*; * *
* This class is used to serve common static content needed when using various parts of Struts, such as JavaScript - * files, CSS files, etc. It works by looking for requests to /struts/* (or /static/*), and then mapping the value after "/struts/" - * to common packages in Struts and, optionally, in your class path. By default, the following packages are + * files, CSS files, etc. It works by looking for requests to {@link #uiStaticContentPath}/* and then mapping the value + * after to common packages in Struts and, optionally, in your class path. By default, the following packages are * automatically searched: *
* @@ -55,7 +60,7 @@ import java.util.*; * * *
- * This means that you can simply request /struts/xhtml/styles.css and the XHTML UI theme's default stylesheet
+ * This means that you can simply request {@link #uiStaticContentPath}/xhtml/styles.css and the XHTML UI theme's default stylesheet
* will be returned. Likewise, many of the AJAX UI components require various JavaScript files, which are found in the
* org.apache.struts2.static package. If you wish to add additional packages to be searched, you can add a comma
* separated (space, tab and new line will do as well) list in the filter init parameter named "packages". Be
@@ -68,7 +73,7 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
/**
* Provide a logging instance.
*/
- private Logger LOG = LogManager.getLogger(DefaultStaticContentLoader.class);
+ private final Logger LOG = LogManager.getLogger(DefaultStaticContentLoader.class);
/**
* Store set of path prefixes to use with static resources.
@@ -80,6 +85,11 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
*/
protected boolean serveStatic;
+ /**
+ * Store state of {@link StrutsConstants#STRUTS_UI_STATIC_CONTENT_PATH} setting.
+ */
+ protected String uiStaticContentPath;
+
/**
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
*/
@@ -100,20 +110,23 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
*
- * @param serveStaticContent
- * New setting
+ * @param serveStaticContent New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
public void setServeStaticContent(String serveStaticContent) {
this.serveStatic = BooleanUtils.toBoolean(serveStaticContent);
}
+ @Inject(StrutsConstants.STRUTS_UI_STATIC_CONTENT_PATH)
+ public void setStaticContentPath(String uiStaticContentPath) {
+ this.uiStaticContentPath = StaticContentLoader.Validator.validateStaticContentPath(uiStaticContentPath);
+ }
+
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE
* setting.
*
- * @param serveStaticBrowserCache
- * New setting
+ * @param serveStaticBrowserCache New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
public void setServeStaticBrowserCache(String serveStaticBrowserCache) {
@@ -122,6 +135,7 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
/**
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
+ *
* @param encoding New setting
*/
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
@@ -164,8 +178,7 @@ public class DefaultStaticContentLoader implements StaticContentLoader {
/**
* Create a string array from a comma-delimited list of packages.
*
- * @param packages
- * A comma-delimited String listing packages
+ * @param packages A comma-delimited String listing packages
* @return A string array of packages
*/
protected List
diff --git a/core/src/main/resources/template/simple/optiontransferselect.ftl b/core/src/main/resources/template/simple/optiontransferselect.ftl
index 910dc6a95..e0d00eef0 100644
--- a/core/src/main/resources/template/simple/optiontransferselect.ftl
+++ b/core/src/main/resources/template/simple/optiontransferselect.ftl
@@ -19,7 +19,7 @@
*/
-->
<#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
- " <#include "/${parameters.templateDir}/simple/nonce.ftl" /> >
+ " <#include "/${parameters.templateDir}/simple/nonce.ftl" /> >
<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
#if><#t/>
diff --git a/core/src/main/resources/template/simple/updownselect.ftl b/core/src/main/resources/template/simple/updownselect.ftl
index 4f57b849a..f1185d3a5 100644
--- a/core/src/main/resources/template/simple/updownselect.ftl
+++ b/core/src/main/resources/template/simple/updownselect.ftl
@@ -19,7 +19,7 @@
*/
-->
<#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
- " <#include "/${parameters.templateDir}/simple/nonce.ftl" /> >
+ " <#include "/${parameters.templateDir}/simple/nonce.ftl" /> >
<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
#if><#t/>
diff --git a/core/src/main/resources/template/xhtml/form-validate.ftl b/core/src/main/resources/template/xhtml/form-validate.ftl
index 3a67f445a..33e8b5507 100644
--- a/core/src/main/resources/template/xhtml/form-validate.ftl
+++ b/core/src/main/resources/template/xhtml/form-validate.ftl
@@ -19,7 +19,7 @@
*/
-->
<#if parameters.validate!false == true>
- >
+ >
<#if parameters.onsubmit??>
${tag.addParameter('onsubmit', "${parameters.onsubmit}; return validateForm_${parameters.id?replace('[^a-zA-Z0-9_]', '_', 'r')}();")}
<#else>
diff --git a/core/src/main/resources/template/xhtml/head.ftl b/core/src/main/resources/template/xhtml/head.ftl
index 48678f269..7b5bfe08d 100644
--- a/core/src/main/resources/template/xhtml/head.ftl
+++ b/core/src/main/resources/template/xhtml/head.ftl
@@ -18,5 +18,5 @@
* under the License.
*/
-->
- />
+ />
<#include "/${parameters.templateDir}/simple/head.ftl" />
diff --git a/core/src/main/resources/template/xhtml/tooltip.ftl b/core/src/main/resources/template/xhtml/tooltip.ftl
index d0b35e726..faa69f69b 100644
--- a/core/src/main/resources/template/xhtml/tooltip.ftl
+++ b/core/src/main/resources/template/xhtml/tooltip.ftl
@@ -23,7 +23,7 @@
<#if parameters.tooltipIconPath??><#t/>
src='<@s.url value="${parameters.tooltipIconPath}" includeParams="none" encode="false" />'
<#else><#t/>
- src='<@s.url value="/struts/tooltip.gif" includeParams="none" encode="false" />'
+ src='<@s.url value="${parameters.staticContentPath}/tooltip.gif" includeParams="none" encode="false" />'
#if><#t/>
<#if (parameters.jsTooltipEnabled!'false') == 'true'>
onmouseover="domTT_activate(this, event, 'content', '<#outputformat 'JavaScript'>${parameters.tooltip}#outputformat>'<#t/>
diff --git a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
index 387d6b591..e4b0c6373 100644
--- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
+++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
@@ -25,6 +25,8 @@ import org.apache.struts2.StrutsInternalTestCase;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateEngine;
import org.apache.struts2.components.template.TemplateEngineManager;
+import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
+import org.apache.struts2.dispatcher.StaticContentLoader;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
@@ -343,4 +345,39 @@ public class UIBeanTest extends StrutsInternalTestCase {
assertEquals(nonceVal, dblSelect.getParameters().get("nonce"));
}
+
+ public void testSetNullUiStaticContentPath() {
+ // given
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ MockHttpServletResponse res = new MockHttpServletResponse();
+
+ TextField field = new TextField(stack, req, res);
+
+ // when
+ field.setStaticContentPath(null);
+ // then
+ assertEquals(StaticContentLoader.DEFAULT_STATIC_CONTENT_PATH, field.uiStaticContentPath);
+
+ // when
+ field.setStaticContentPath(" ");
+ // then
+ assertEquals(StaticContentLoader.DEFAULT_STATIC_CONTENT_PATH, field.uiStaticContentPath);
+
+ // when
+ field.setStaticContentPath("content");
+ // then
+ assertEquals("/content", field.uiStaticContentPath);
+
+ // when
+ field.setStaticContentPath("/content");
+ // then
+ assertEquals("/content", field.uiStaticContentPath);
+
+ // when
+ field.setStaticContentPath("/content/");
+ // then
+ assertEquals("/content", field.uiStaticContentPath);
+ }
+
}
diff --git a/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java b/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java
index 01503dd42..a9efe5920 100644
--- a/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java
+++ b/core/src/test/java/org/apache/struts2/config/entities/ConstantConfigTest.java
@@ -18,11 +18,17 @@
*/
package org.apache.struts2.config.entities;
+import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TestBean;
import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.components.TextField;
+import org.apache.struts2.dispatcher.StaticContentLoader;
import org.junit.Assert;
import org.junit.Test;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.springframework.mock.web.MockHttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
@@ -109,4 +115,30 @@ public class ConstantConfigTest {
map.get(StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES));
}
+ @Test
+ public void testSettingStaticContentPath() {
+ // given
+ ConstantConfig config = new ConstantConfig();
+
+ // when
+ config.setStaticContentPath(null);
+ // then
+ Assert.assertEquals(StaticContentLoader.DEFAULT_STATIC_CONTENT_PATH, config.getStaticContentPath());
+
+ // when
+ config.setStaticContentPath(" ");
+ // then
+ Assert.assertEquals(StaticContentLoader.DEFAULT_STATIC_CONTENT_PATH, config.getStaticContentPath());
+
+ // when
+ config.setStaticContentPath("content");
+ // then
+ Assert.assertEquals("/content", config.getStaticContentPath());
+
+ // when
+ config.setStaticContentPath("/content");
+ // then
+ Assert.assertEquals("/content", config.getStaticContentPath());
+ }
+
}
diff --git a/core/src/test/java/org/apache/struts2/dispatcher/DefaultStaticContentLoaderTest.java b/core/src/test/java/org/apache/struts2/dispatcher/DefaultStaticContentLoaderTest.java
index 8f8eda1eb..b472ce5c9 100644
--- a/core/src/test/java/org/apache/struts2/dispatcher/DefaultStaticContentLoaderTest.java
+++ b/core/src/test/java/org/apache/struts2/dispatcher/DefaultStaticContentLoaderTest.java
@@ -30,13 +30,12 @@ import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
public class DefaultStaticContentLoaderTest extends StrutsInternalTestCase {
+
private HttpServletRequest requestMock;
private HttpServletResponse responseMock;
- private HostConfig hostConfigMock;
private DefaultStaticContentLoader defaultStaticContentLoader;
- public void testParsePackages() throws Exception {
-
+ public void testParsePackages() {
DefaultStaticContentLoader filterDispatcher = new DefaultStaticContentLoader();
List