Refactoring script and link elements for CSP nonce propagation
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
index 8de2f85..a8c8394 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp
@@ -27,14 +27,14 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Orders</title>
- <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
- <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+ <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
<![endif]-->
</head>
<body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
index e576804..b7ce725 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp
@@ -27,14 +27,14 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Orders</title>
- <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
- <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+ <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
<![endif]-->
</head>
<body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
index 2d9af8f..918c75d 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp
@@ -27,13 +27,13 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Orders</title>
- <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
- <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+ <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
<![endif]-->
</head>
<body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
index e96b57a..2b42d54 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp
@@ -27,14 +27,14 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Orders</title>
- <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
- <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+ <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
<![endif]-->
</head>
<body>
diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
index cfe3941..c947db0 100644
--- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
+++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp
@@ -27,14 +27,14 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Orders</title>
- <link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
- <link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/bootstrap.min.css" rel="stylesheet">
+ <s:link href="${pageContext.request.contextPath}/css/app.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
+ <s:script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></s:script>
+ <s:script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></s:script>
<![endif]-->
</head>
<body>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
index 1ae656a..0f0d4ed 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -63,26 +63,26 @@
<title><decorator:title default="Struts2 Showcase"/></title>
- <link href="<s:url value='/styles/bootstrap.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all">
- <link href="<s:url value='/styles/main.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all"/>
+ <s:link href="<s:url value='/styles/bootstrap.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all">
+ <s:link href="<s:url value='/styles/main.css' encode='false' includeParams='none'/>" rel="stylesheet" type="text/css" media="all"/>
- <script src="<s:url value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>"></script>
- <script src="<s:url value='/js/bootstrap.min.js' encode='false' includeParams='none'/>"></script>
- <script type="text/javascript">
+ <s:script src="<s:url value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>"></s:script>
+ <s:script src="<s:url value='/js/bootstrap.min.js' encode='false' includeParams='none'/>"></s:script>
+ <s:script type="text/javascript">
$(function () {
var alerts = $('ul.alert').wrap('<div />');
alerts.prepend('<a class="close" data-dismiss="alert" href="#">×</a>');
alerts.alert();
});
- </script>
+ </s:script>
<!-- Prettify -->
- <link href="<s:url value='/styles/prettify.css' encode='false' includeParams='none'/>" rel="stylesheet">
- <script src="<s:url value='/js/prettify.js' encode='false' includeParams='none'/>"></script>
+ <s:link href="<s:url value='/styles/prettify.css' encode='false' includeParams='none'/>" rel="stylesheet">
+ <s:script src="<s:url value='/js/prettify.js' encode='false' includeParams='none'/>"></s:script>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
- <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
+ <s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></s:script>
<![endif]-->
<decorator:head/>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
index fbfd233..3064aa2 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp
@@ -72,7 +72,7 @@
</div>
</div>
-<script type="text/javascript">
+<s:script type="text/javascript">
/********************************************************************
* JS just used on this page.
* Usually this would be placed in a JS file
@@ -196,6 +196,6 @@
$(window).bind('load', function() {
$('form').bind('submit', ajaxFormValidation);
});
-</script>
+</s:script>
</body>
</html>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
index 2dc69b8..51d26e7 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-dwr.jsp
@@ -26,10 +26,10 @@
<head>
<title>Struts2 Showcase - Validation - DWR</title>
<s:head/>
- <script type='text/javascript' src='../dwr/engine.js'></script>
- <script type='text/javascript' src='../dwr/util.js'></script>
- <script type='text/javascript' src='../dwr/interface/validator.js'></script>
- <script type='text/javascript'>
+ <s:script type='text/javascript' src='../dwr/engine.js'></s:script>
+ <s:script type='text/javascript' src='../dwr/util.js'></s:script>
+ <s:script type='text/javascript' src='../dwr/interface/validator.js'></s:script>
+ <s:script type='text/javascript'>
var dwrValidateReply = function(data) {
var validationResult = '';
for (index = 0; index < data.actionErrors.length; ++index) {
@@ -62,7 +62,7 @@
validator.doPost('/validation', 'quizDwr', postData, dwrValidateReply);
return false;
}
- </script>
+ </s:script>
</head>
<body>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
index 5623c54..1255d2a 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp
@@ -64,11 +64,11 @@
</div>
-<script>
+<s:script>
$('#codeTab a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})
-</script>
+</s:script>
</body>
</html>
diff --git a/core/src/main/java/org/apache/struts2/components/Link.java b/core/src/main/java/org/apache/struts2/components/Link.java
index 4345c50..b766849 100644
--- a/core/src/main/java/org/apache/struts2/components/Link.java
+++ b/core/src/main/java/org/apache/struts2/components/Link.java
@@ -166,10 +166,5 @@
if (title != null) {
addParameter("title", findString(title));
}
-
- if (stack.getActionContext().getSession().containsKey("nonce")) {
- String nonceValue = stack.getActionContext().getSession().get("nonce").toString();
- addParameter("nonce", nonceValue);
- }
}
}
diff --git a/core/src/main/java/org/apache/struts2/components/Script.java b/core/src/main/java/org/apache/struts2/components/Script.java
index f2a2081..447eaf7 100644
--- a/core/src/main/java/org/apache/struts2/components/Script.java
+++ b/core/src/main/java/org/apache/struts2/components/Script.java
@@ -168,11 +168,6 @@
if (crossorigin != null) {
addParameter("crossorigin", findString(crossorigin));
}
-
- if (stack.getActionContext().getSession().containsKey("nonce")) {
- String nonceValue = stack.getActionContext().getSession().get("nonce").toString();
- addParameter("nonce", nonceValue);
- }
}
}
diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java
index 0e44a3b..f584f97 100644
--- a/core/src/main/java/org/apache/struts2/components/UIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/UIBean.java
@@ -881,6 +881,15 @@
}
}
+ // to be used with the CSP interceptor - adds the nonce value as a parameter to be accessed from ftl files
+ Map<String, Object> session = stack.getActionContext().getSession();
+ if (session != null) {
+ if (session.containsKey("nonce")) {
+ String nonceValue = session.get("nonce").toString();
+ addParameter("nonce", nonceValue);
+ }
+ }
+
evaluateExtraParams();
}
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java
new file mode 100644
index 0000000..f3fa7f5
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/LinkModel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.struts2.views.freemarker.tags;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.components.Component;
+import org.apache.struts2.components.Link;
+
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * @see Link
+ */
+public class LinkModel extends TagModel {
+ public LinkModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
+ super(stack, req, res);
+ }
+
+ protected Component getBean() {
+ return new Link(stack, req, res);
+ }
+}
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java
new file mode 100644
index 0000000..c2a84f3
--- /dev/null
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/ScriptModel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.struts2.views.freemarker.tags;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.struts2.components.Component;
+import org.apache.struts2.components.Script;
+
+import com.opensymphony.xwork2.util.ValueStack;
+
+/**
+ * @see Script
+ */
+public class ScriptModel extends TagModel {
+ public ScriptModel(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
+ super(stack, req, res);
+ }
+
+ protected Component getBean() {
+ return new Script(stack, req, res);
+ }
+}
diff --git a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
index 99c4686..819ba95 100644
--- a/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
+++ b/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java
@@ -22,6 +22,7 @@
import javax.servlet.http.HttpServletResponse;
import com.opensymphony.xwork2.util.ValueStack;
+import org.apache.struts2.components.Script;
/**
* Provides @s.tag access for various tags.
@@ -73,6 +74,8 @@
protected ElseModel elseModel;
protected ElseIfModel elseIfModel;
protected InputTransferSelectModel inputtransferselect;
+ protected ScriptModel script;
+ protected LinkModel link;
public StrutsModels(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
@@ -160,6 +163,14 @@
return label;
}
+ public LinkModel getLink() {
+ if (link == null) {
+ link = new LinkModel(stack, req, res);
+ }
+
+ return link;
+ }
+
public PasswordModel getPassword() {
if (password == null) {
password = new PasswordModel(stack, req, res);
@@ -176,6 +187,14 @@
return radio;
}
+ public ScriptModel getScript() {
+ if (script == null) {
+ script = new ScriptModel(stack, req, res);
+ }
+
+ return script;
+ }
+
public SelectModel getSelect() {
if (select == null) {
select = new SelectModel(stack, req, res);
diff --git a/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl b/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
index 22a251b..91b0339 100644
--- a/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
+++ b/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl
@@ -21,7 +21,9 @@
<!DOCTYPE html>
<html>
<head>
- <script type="text/javascript">
+ <script type="text/javascript" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ >
var baseUrl = "<@s.url value="/struts" includeParams="none"/>";
window.open(baseUrl+"/webconsole.html", 'OGNL Console','width=500,height=450,status=no,toolbar=no,menubar=no');
</script>
diff --git a/core/src/main/resources/template/css_xhtml/head.ftl b/core/src/main/resources/template/css_xhtml/head.ftl
index d6c6d7f..df9916c 100644
--- a/core/src/main/resources/template/css_xhtml/head.ftl
+++ b/core/src/main/resources/template/css_xhtml/head.ftl
@@ -18,5 +18,7 @@
* under the License.
*/
-->
-<link rel="stylesheet" href="<@s.url value='/struts/css_xhtml/styles.css' includeParams='none' encode='false' />" type="text/css" />
+<link
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ rel="stylesheet" href="<@s.url value='/struts/css_xhtml/styles.css' includeParams='none' encode='false' />" type="text/css" />
<#include "/${parameters.templateDir}/simple/head.ftl" />
diff --git a/core/src/main/resources/template/simple/combobox.ftl b/core/src/main/resources/template/simple/combobox.ftl
index 1a6d805..2f6f4a9 100644
--- a/core/src/main/resources/template/simple/combobox.ftl
+++ b/core/src/main/resources/template/simple/combobox.ftl
@@ -18,7 +18,9 @@
* under the License.
*/
-->
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
function autoPopulate_${parameters.escapedId}(targetElement) {
<#if parameters.headerKey?? && parameters.headerValue??>
if (targetElement.options[targetElement.selectedIndex].value == '${parameters.headerKey}') {
diff --git a/core/src/main/resources/template/simple/debug.ftl b/core/src/main/resources/template/simple/debug.ftl
index 7f007a7..145e5dd 100644
--- a/core/src/main/resources/template/simple/debug.ftl
+++ b/core/src/main/resources/template/simple/debug.ftl
@@ -18,7 +18,9 @@
* under the License.
*/
-->
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
<!--
function toggleDebug(debugId) {
var debugDiv = document.getElementById(debugId);
diff --git a/core/src/main/resources/template/simple/doubleselect.ftl b/core/src/main/resources/template/simple/doubleselect.ftl
index 7e5bd41..3c913b6 100644
--- a/core/src/main/resources/template/simple/doubleselect.ftl
+++ b/core/src/main/resources/template/simple/doubleselect.ftl
@@ -70,7 +70,9 @@
</#if>
/>
</#if>
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
<#assign itemCount = startCount/>
var ${parameters.id}Group = new Array(${parameters.listSize} + ${startCount});
for (var i = 0; i < (${parameters.listSize} + ${startCount}); i++) {
diff --git a/core/src/main/resources/template/simple/form-close-tooltips.ftl b/core/src/main/resources/template/simple/form-close-tooltips.ftl
index a84eb24..b5a5d30 100644
--- a/core/src/main/resources/template/simple/form-close-tooltips.ftl
+++ b/core/src/main/resources/template/simple/form-close-tooltips.ftl
@@ -24,7 +24,11 @@
--><#t/>
<#if (parameters.hasTooltip!false)><#t/>
<#lt/><!-- javascript that is needed for tooltips -->
- <#lt/><script type="text/javascript" src='<@s.url value="/struts/domTT.js" includeParams="none" encode="false" />'></script>
- <#lt/><link rel="stylesheet" type="text/css" href="<@s.url value="/struts/domTT.css" includeParams="none" encode="false" />"/>
+ <#lt/><script type="text/javascript" src='<@s.url value="/struts/domTT.js" includeParams="none" encode="false" />'<#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ ></script>
+ <#lt/><link rel="stylesheet" type="text/css" href="<@s.url value="/struts/domTT.css" includeParams="none" encode="false" />" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ />
</#if><#t/>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/form-close.ftl b/core/src/main/resources/template/simple/form-close.ftl
index 0efea0c..469df76 100644
--- a/core/src/main/resources/template/simple/form-close.ftl
+++ b/core/src/main/resources/template/simple/form-close.ftl
@@ -21,16 +21,18 @@
</form>
<#if (parameters.customOnsubmitEnabled??)>
-<script type="text/javascript">
-<#--
- Enable auto-select of optiontransferselect tag's entries upon containing form's
+<script type="text/javascript" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
+<#--
+ Enable auto-select of optiontransferselect tag's entries upon containing form's
submission.
-->
<#if (parameters.optiontransferselectIds!?size > 0)>
var containingForm = document.getElementById("${parameters.id}");
<#assign selectObjIds = parameters.optiontransferselectIds.keySet() />
<#list selectObjIds as selectObjectId>
- StrutsUtils.addEventListener(containingForm, "submit",
+ StrutsUtils.addEventListener(containingForm, "submit",
function(evt) {
var selectObj = document.getElementById("${selectObjectId}");
<#if parameters.optiontransferselectIds.get(selectObjectId)??>
@@ -62,7 +64,7 @@
var containingForm = document.getElementById("${parameters.id}");
<#assign selectDoubleObjIds = parameters.optiontransferselectDoubleIds.keySet() />
<#list selectDoubleObjIds as selectObjId>
- StrutsUtils.addEventListener(containingForm, "submit",
+ StrutsUtils.addEventListener(containingForm, "submit",
function(evt) {
var selectObj = document.getElementById("${selectObjId}");
<#if parameters.optiontransferselectDoubleIds.get(selectObjId)??>
@@ -84,7 +86,7 @@
var containingForm = document.getElementById("${parameters.id}");
<#assign tmpIds = parameters.updownselectIds.keySet() />
<#list tmpIds as tmpId>
- StrutsUtils.addEventListener(containingForm, "submit",
+ StrutsUtils.addEventListener(containingForm, "submit",
function(evt) {
var updownselectObj = document.getElementById("${tmpId}");
<#if parameters.updownselectIds.get(tmpId)??>
@@ -99,4 +101,4 @@
</script>
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-tooltips.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-tooltips.ftl" />
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/head.ftl b/core/src/main/resources/template/simple/head.ftl
index 2c5484a..15d12f9 100644
--- a/core/src/main/resources/template/simple/head.ftl
+++ b/core/src/main/resources/template/simple/head.ftl
@@ -18,4 +18,6 @@
* under the License.
*/
-->
-<script src="${base}/struts/utils.js" type="text/javascript"></script>
\ No newline at end of file
+<script src="${base}/struts/utils.js" type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+></script>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/inputtransferselect.ftl b/core/src/main/resources/template/simple/inputtransferselect.ftl
index 7428e05..4eacbbd 100644
--- a/core/src/main/resources/template/simple/inputtransferselect.ftl
+++ b/core/src/main/resources/template/simple/inputtransferselect.ftl
@@ -19,7 +19,9 @@
*/
-->
<#if !stack.findValue("#inputtransferselect_js_included")??><#t/>
- <script type="text/javascript" src="<@s.url value="/struts/inputtransferselect.js" encode='false' includeParams='none'/>"></script>
+ <script type="text/javascript" src="<@s.url value="/struts/inputtransferselect.js" encode='false' includeParams='none'/>" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ ></script>
<#assign temporaryVariable = stack.setValue("#inputtransferselect_js_included", "true") /><#t/>
</#if><#t/>
<table>
diff --git a/core/src/main/resources/template/simple/link.ftl b/core/src/main/resources/template/simple/link.ftl
index 6bb0944..31821e0 100644
--- a/core/src/main/resources/template/simple/link.ftl
+++ b/core/src/main/resources/template/simple/link.ftl
@@ -20,7 +20,8 @@
-->
<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-<link nonce="${parameters.nonce}"<#rt/>
+<link <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
<#if parameters.href?has_content>
href="${parameters.href}"<#rt/>
</#if>
diff --git a/core/src/main/resources/template/simple/nonce.ftl b/core/src/main/resources/template/simple/nonce.ftl
new file mode 100644
index 0000000..a124cf6
--- /dev/null
+++ b/core/src/main/resources/template/simple/nonce.ftl
@@ -0,0 +1,23 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#if parameters.nonce?has_content>
+ nonce="${parameters.nonce}"<#rt/>
+</#if>
\ No newline at end of file
diff --git a/core/src/main/resources/template/simple/optiontransferselect.ftl b/core/src/main/resources/template/simple/optiontransferselect.ftl
index 40b03c9..d0b328b 100644
--- a/core/src/main/resources/template/simple/optiontransferselect.ftl
+++ b/core/src/main/resources/template/simple/optiontransferselect.ftl
@@ -19,7 +19,9 @@
*/
-->
<#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
- <script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"></script>
+ <script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"<#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ ></script>
<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
</#if><#t/>
<table>
diff --git a/core/src/main/resources/template/simple/script.ftl b/core/src/main/resources/template/simple/script.ftl
index f166532..5afb30d 100644
--- a/core/src/main/resources/template/simple/script.ftl
+++ b/core/src/main/resources/template/simple/script.ftl
@@ -18,12 +18,10 @@
* under the License.
*/
-->
+<script <#rt/>
<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-<script <#rt/>
-<#if parameters.nonce?has_content>
- nonce="${parameters.nonce}"<#rt/>
-</#if>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
<#if parameters.async?has_content>
<#if parameters.async=="true">
async<#rt/>
@@ -43,9 +41,6 @@
<#if parameters.type?has_content>
type="${parameters.type}"<#rt/>
</#if>
-<#if parameters.name?has_content>
- name="${parameters.name}"<#rt/>
-</#if>
<#if parameters.referrerpolicy?has_content>
referrerpolicy="${parameters.referrerpolicy}"<#rt/>
</#if>
diff --git a/core/src/main/resources/template/simple/updownselect.ftl b/core/src/main/resources/template/simple/updownselect.ftl
index ad0a8ae..e8683fc 100644
--- a/core/src/main/resources/template/simple/updownselect.ftl
+++ b/core/src/main/resources/template/simple/updownselect.ftl
@@ -19,7 +19,9 @@
*/
-->
<#if !stack.findValue("#optiontransferselect_js_included")??><#t/>
- <script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>"></script>
+ <script type="text/javascript" src="<@s.url value="/struts/optiontransferselect.js" encode='false' includeParams='none'/>" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ ></script>
<#assign temporaryVariable = stack.setValue("#optiontransferselect_js_included", "true") /><#t/>
</#if><#t/>
<table>
diff --git a/core/src/main/resources/template/xhtml/form-close-validate.ftl b/core/src/main/resources/template/xhtml/form-close-validate.ftl
index 2cbb174..7fc1510 100644
--- a/core/src/main/resources/template/xhtml/form-close-validate.ftl
+++ b/core/src/main/resources/template/xhtml/form-close-validate.ftl
@@ -32,7 +32,9 @@
END SNIPPET: supported-validators
-->
<#if ((parameters.validate!false == true) && (parameters.performValidation!false == true))>
-<script type="text/javascript">
+<script type="text/javascript"<#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
function validateForm_${parameters.id?replace('[^a-zA-Z0-9_]', '_', 'r')}() {
<#--
In case of multiselect fields return only the first value.
diff --git a/core/src/main/resources/template/xhtml/form-close.ftl b/core/src/main/resources/template/xhtml/form-close.ftl
index 9b4d7ae..a220511 100644
--- a/core/src/main/resources/template/xhtml/form-close.ftl
+++ b/core/src/main/resources/template/xhtml/form-close.ftl
@@ -22,7 +22,9 @@
<#include "/${parameters.templateDir}/simple/form-close.ftl" />
<#include "/${parameters.templateDir}/${parameters.expandTheme}/form-close-validate.ftl" />
<#if parameters.focusElement??>
-<script type="text/javascript">
+<script type="text/javascript" <#rt/>
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+>
StrutsUtils.addOnLoad(function() {
var element = document.getElementById("${parameters.focusElement}");
if(element) {
diff --git a/core/src/main/resources/template/xhtml/form-validate.ftl b/core/src/main/resources/template/xhtml/form-validate.ftl
index 5a65e0c..4e4cd6e 100644
--- a/core/src/main/resources/template/xhtml/form-validate.ftl
+++ b/core/src/main/resources/template/xhtml/form-validate.ftl
@@ -19,7 +19,9 @@
*/
-->
<#if parameters.validate!false == true>
- <script type="text/javascript" src="${base}/struts/xhtml/validation.js"></script>
+ <script type="text/javascript" src="${base}/struts/xhtml/validation.js" <#rt/>
+ <#include "/${parameters.templateDir}/simple/nonce.ftl" />
+ ></script>
<#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 8bd9f55..61a7783 100644
--- a/core/src/main/resources/template/xhtml/head.ftl
+++ b/core/src/main/resources/template/xhtml/head.ftl
@@ -18,5 +18,7 @@
* under the License.
*/
-->
-<link rel="stylesheet" href="<@s.url value='/struts/xhtml/styles.css' includeParams='none' encode='false' />" type="text/css"/>
+<link rel="stylesheet" href="<@s.url value='/struts/xhtml/styles.css' includeParams='none' encode='false'/>" type="text/css"
+<#include "/${parameters.templateDir}/simple/nonce.ftl" />
+/>
<#include "/${parameters.templateDir}/simple/head.ftl" />
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 9317397..3e8547e 100644
--- a/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
+++ b/core/src/test/java/org/apache/struts2/components/UIBeanTest.java
@@ -30,6 +30,7 @@
import java.util.Collections;
+import java.util.HashMap;
import java.util.Map;
public class UIBeanTest extends StrutsInternalTestCase {
@@ -305,4 +306,20 @@
assertEquals(cssStyle, txtFld.getParameters().get("cssStyle"));
}
+
+ public void testNonce() {
+ String nonceVal = "r4nd0m";
+ ValueStack stack = ActionContext.getContext().getValueStack();
+ MockHttpServletRequest req = new MockHttpServletRequest();
+ MockHttpServletResponse res = new MockHttpServletResponse();
+ ActionContext actionContext = stack.getActionContext();
+ Map<String, Object> session = new HashMap<>();
+ session.put("nonce", nonceVal);
+ actionContext.withSession(session);
+
+ DoubleSelect dblSelect = new DoubleSelect(stack, req, res);
+ dblSelect.evaluateParams();
+
+ assertEquals(nonceVal, dblSelect.getParameters().get("nonce"));
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
index f7ef72a..a3f5027 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
@@ -73,6 +73,8 @@
tag.setId("cb");
tag.setList("collection");
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
index bbee23b..fa47295 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DebugTagTest.java
@@ -48,10 +48,13 @@
public void testDevModeEnabled() throws Exception {
setDevMode(true);
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
tag.doStartTag();
tag.doEndTag();
String result = writer.toString();
+
+ assertTrue("Nonce value not included", result.contains("nonce=\"r4nd0m\""));
assertTrue(StringUtils.isNotEmpty(result));
assertTrue("Property 'checkStackProperty' should be in Debug Tag output", StringUtils.contains(result, "<td>checkStackProperty</td>"));
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
index ff1a7d7..536a5d9 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java
@@ -87,13 +87,15 @@
tag.setCssStyle("s1");
tag.setDoubleCssClass("c2");
tag.setDoubleCssStyle("s2");
-
+
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
verify(SelectTag.class.getResource("DoubleSelect-1.txt"));
}
-
+
public void testOnchange() throws Exception {
TestAction testAction = (TestAction) action;
@@ -151,7 +153,7 @@
tag.setCssStyle("s1");
tag.setDoubleCssClass("c2");
tag.setDoubleCssStyle("s2");
-
+
tag.doStartTag();
tag.doEndTag();
@@ -221,7 +223,7 @@
}
-
+
public void testDoubleWithDotName() throws Exception {
TestAction testAction = (TestAction) action;
@@ -377,4 +379,4 @@
return key;
}
}
-}
+}
\ No newline at end of file
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
index 535e42f..1ccbb89 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java
@@ -61,6 +61,9 @@
tag.setEnctype("myEncType");
tag.setTitle("mytitle");
tag.setOnsubmit("submitMe()");
+
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
index a290f50..a0c0ff2 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java
@@ -32,7 +32,9 @@
public void testHead1() throws Exception {
HeadTag tag = new HeadTag();
tag.setPageContext(pageContext);
-
+
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
index f2de3c0..ee60cd8 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java
@@ -42,6 +42,7 @@
tag.setName("collection");
tag.setList("collection");
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
index 56b7b78..d7e8bb1 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java
@@ -85,6 +85,8 @@
tag.setDoubleHeaderKey("Double Header Key");
tag.setDoubleHeaderValue("Double Header Value");
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
index e020372..f35fa18 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java
@@ -60,6 +60,8 @@
tag.setValue("mySelectedMapIds");
tag.setEmptyOption("false");
+ stack.getActionContext().getSession().put("nonce", "r4nd0m");
+
tag.doStartTag();
tag.doEndTag();
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
index fc3c1c0..0121ef4 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt
@@ -1,7 +1,7 @@
<tr>
<td class="tdLabel"><label for="cb" class="label">mylabel:</label></td>
<td class="tdInput">
-<script type="text/javascript">
+<script type="text/javascript" nonce="r4nd0m">
function autoPopulate_cb(targetElement) {
targetElement.form.elements['foo'].value=targetElement.options[targetElement.selectedIndex].value;
}
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
index a641703..f5219cf 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt
@@ -8,7 +8,7 @@
<br/>
<select name="region" id="region" class="c2" style="s2">
</select>
-<script type="text/javascript">
+<script type="text/javascript" nonce="r4nd0m">
var fooGroup = new Array(2 + 0);
for (var i = 0; i < (2 + 0); i++) {
fooGroup[i] = [];
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
index 9e30a79..d9c6359 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt
@@ -1,2 +1,2 @@
-<link rel="stylesheet" href="/struts/xhtml/styles.css" type="text/css"/>
-<script src="/struts/utils.js" type="text/javascript"></script>
\ No newline at end of file
+<link rel="stylesheet" href="/struts/xhtml/styles.css" type="text/css" nonce="r4nd0m"/>
+<script src="/struts/utils.js" type="text/javascript" nonce="r4nd0m"></script>
\ No newline at end of file
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
index 22062bf..a73b85a 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt
@@ -1,7 +1,7 @@
<tr>
<td class="tdLabel"></td>
<td class="tdInput">
- <script type="text/javascript" src="/struts/inputtransferselect.js"></script>
+ <script type="text/javascript" src="/struts/inputtransferselect.js" nonce="r4nd0m"></script>
<table>
<tr><td><input type="text" name="collection_input" id="collection_input"/></td>
<td class="tdTransferSelect"><inputtype="button"value="->"onclick="addOption(document.getElementById('collection_input'),document.getElementById('collection'))"/>
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
index d423b3a..2ee3705 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt
@@ -1,7 +1,7 @@
<tr>
<td class="tdLabel"></td>
<td class="tdInput">
-<script type="text/javascript" src="/struts/optiontransferselect.js"></script>
+<script type="text/javascript" src="/struts/optiontransferselect.js" nonce="r4nd0m"></script>
<table>
<tr>
<td>
diff --git a/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt b/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
index a00d294..0f8944b 100644
--- a/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
+++ b/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt
@@ -1,5 +1,5 @@
<tr> <td class="tdLabel"></td> <td class="tdInput">
-<script type="text/javascript" src="/struts/optiontransferselect.js"></script>
+<script type="text/javascript" src="/struts/optiontransferselect.js" nonce="r4nd0m"></script>
<table>
<tr><td>
<select name="myName" size="5" id="myId" multiple="multiple">
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
index 4146592..55a7d35 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/LinkHandler.java
@@ -31,8 +31,7 @@
Map<String, Object> params = context.getParameters();
Attributes attrs = new Attributes();
- attrs.add("nonce", (String) params.get("nonce"))
- .addIfExists("href", params.get(("href")))
+ attrs.addIfExists("href", params.get(("href")))
.addIfExists("hreflang", params.get("hreflang"))
.addIfExists("rel", params.get("rel"))
.addIfExists("media", params.get("media"))
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java
new file mode 100644
index 0000000..aa75c2d
--- /dev/null
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/NonceHandler.java
@@ -0,0 +1,31 @@
+/*
+ * 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.struts2.views.java.simple;
+
+import org.apache.struts2.views.java.Attributes;
+import java.io.IOException;
+
+public class NonceHandler extends AbstractTagHandler {
+
+ @Override
+ public void start(String name, Attributes a) throws IOException {
+ a.addIfExists("nonce", context.getParameters().get("nonce"));
+ super.start(name, a);
+ }
+}
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
index ec62941..34acef0 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/ScriptHandler.java
@@ -33,13 +33,11 @@
Map<String, Object> params = context.getParameters();
Attributes attrs = new Attributes();
- attrs.add("nonce", (String) params.get("nonce"))
- .addIfExists("async", params.get("async"))
+ attrs.addIfExists("async", params.get("async"))
.addIfExists("charset", params.get("charset"))
.addIfExists("defer", params.get("defer"))
.addIfExists("src", params.get("src"))
.addIfExists("type", params.get("type"))
- .addIfExists("name", params.get("name"))
.addIfExists("referrerpolicy", params.get("referrerpolicy"))
.addIfExists("nomodule", params.get("nomodule"))
.addIfExists("integrity", params.get("integrity"))
diff --git a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
index 0e89630..adfc7f9 100644
--- a/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
+++ b/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java
@@ -37,7 +37,7 @@
put("datetextfield", new FactoryList(DateTextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class));
put("select", new FactoryList(SelectHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
put("form", new FactoryList(FormHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
- put("form-close", new FactoryList(FormHandler.CloseHandler.class));
+ put("form-close", new FactoryList(FormHandler.CloseHandler.class, ScriptHandler.class, NonceHandler.class));
put("a", new FactoryList(AnchorHandler.class));
put("a-close", new FactoryList(AnchorHandler.CloseHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
put("checkbox", new FactoryList(CheckboxHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
@@ -50,13 +50,13 @@
put("textarea", new FactoryList(TextAreaHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
put("radiomap", new FactoryList(RadioHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
put("checkboxlist", new FactoryList(CheckboxListHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
- put("script", new FactoryList(ScriptHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
+ put("script", new FactoryList(ScriptHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class, NonceHandler.class));
put("script-close", new FactoryList(ScriptHandler.CloseHandler.class));
- put("link", new FactoryList(LinkHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class));
+ put("link", new FactoryList(LinkHandler.class, CommonAttributesHandler.class, DynamicAttributesHandler.class, NonceHandler.class));
put("actionerror", new FactoryList(ActionErrorHandler.class));
put("token", new FactoryList(TokenHandler.class));
put("actionmessage", new FactoryList(ActionMessageHandler.class));
- put("head", new FactoryList(HeadHandler.class));
+ put("head", new FactoryList(HeadHandler.class, NonceHandler.class));
put("hidden", new FactoryList(HiddenHandler.class));
put("fielderror", new FactoryList(FieldErrorHandler.class));
put("empty", new FactoryList(EmptyHandler.class));