You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2022/10/14 12:25:38 UTC
[myfaces] branch main updated: https://issues.apache.org/jira/browse/MYFACES-4479: nonce handling ported over from 2.3-next branch
This is an automated email from the ASF dual-hosted git repository.
werpu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/main by this push:
new cf2acb55a https://issues.apache.org/jira/browse/MYFACES-4479: nonce handling ported over from 2.3-next branch
new c62a8f57b Merge pull request #344 from werpu/main
cf2acb55a is described below
commit cf2acb55aee516c2e7a29516e0c71d66a969b802
Author: Werner Punz <we...@gmail.com>
AuthorDate: Fri Oct 14 14:18:43 2022 +0200
https://issues.apache.org/jira/browse/MYFACES-4479:
nonce handling ported over from 2.3-next branch
---
.../META-INF/resources/myfaces/_impl/_util/_Dom.js | 161 ++++++++++++---------
.../resources/myfaces/_impl/core/_EvalHandlers.js | 19 ++-
.../resources/myfaces/_impl/core/_Runtime.js | 4 +
3 files changed, 113 insertions(+), 71 deletions(-)
diff --git a/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js b/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
index 27c8ba66b..e70f14b2b 100644
--- a/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
+++ b/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
@@ -56,45 +56,54 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
runCss: function(item/*, xmlData*/) {
var UDEF = "undefined",
- _RT = this._RT,
- _Lang = this._Lang,
- applyStyle = function(item, style) {
- var newSS = document.createElement("style");
-
- newSS.setAttribute("rel", item.getAttribute("rel") || "stylesheet");
- newSS.setAttribute("type", item.getAttribute("type") || "text/css");
- if(item.getAttribute("nonce")) {
- newSS.setAttribute("nonce", item.getAttribute("nonce"));
+ _T = this;
+ _RT = this._RT,
+ _Lang = this._Lang;
+ var applyStyle = function(item, style) {
+ var newSS = document.createElement("style");
+
+ newSS.setAttribute("rel", item.getAttribute("rel") || "stylesheet");
+ newSS.setAttribute("type", item.getAttribute("type") || "text/css");
+ const nonceValue = _RT.resolveNonce(item);
+ if(nonceValue) {
+ if('undefined' != typeof newSS.nonce) {
+ newSS['nonce'] = nonceValue;
+ } else {
+ newSS.setAttribute("nonce", nonceValue);
}
+ }
- document.getElementsByTagName("head")[0].appendChild(newSS);
- //ie merrily again goes its own way
- if (window.attachEvent && !_RT.isOpera && UDEF != typeof newSS.styleSheet && UDEF != newSS.styleSheet.cssText) newSS.styleSheet.cssText = style;
- else newSS.appendChild(document.createTextNode(style));
- },
-
- execCss = function(item) {
- var equalsIgnoreCase = _Lang.equalsIgnoreCase;
- var tagName = item.tagName;
- if (tagName && equalsIgnoreCase(tagName, "link") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
- applyStyle(item, "@import url('" + item.getAttribute("href") + "');");
- } else if (tagName && equalsIgnoreCase(tagName, "style") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
- var innerText = [];
- //compliant browsers know child nodes
- var childNodes = item.childNodes;
- if (childNodes) {
- var len = childNodes.length;
- for (var cnt = 0; cnt < len; cnt++) {
- innerText.push(childNodes[cnt].innerHTML || childNodes[cnt].data);
- }
- //non compliant ones innerHTML
- } else if (item.innerHTML) {
- innerText.push(item.innerHTML);
- }
+ document.getElementsByTagName("head")[0].appendChild(newSS);
+ //ie merrily again goes its own way
+ if (window.attachEvent && !_RT.isOpera && UDEF != typeof newSS.styleSheet && UDEF != newSS.styleSheet.cssText) newSS.styleSheet.cssText = style;
+ else newSS.appendChild(document.createTextNode(style));
+ },
- applyStyle(item, innerText.join(""));
+ execCss = function(item) {
+ var equalsIgnoreCase = _Lang.equalsIgnoreCase;
+ var tagName = item.tagName;
+ if (tagName && equalsIgnoreCase(tagName, "link") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
+ applyStyle(item, "@import url('" + item.getAttribute("href") + "');");
+ } else if (tagName && equalsIgnoreCase(tagName, "style") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
+ // we do not handle css items blockwise like we do scripts
+ // but we do have to deal with the child elements instead of the markup
+ // nonce can be handled on tag level though
+ var innerText = [];
+ //compliant browsers know child nodes
+ var childNodes = item.childNodes;
+ if (childNodes) {
+ var len = childNodes.length;
+ for (var cnt = 0; cnt < len; cnt++) {
+ innerText.push(childNodes[cnt].innerHTML || childNodes[cnt].data);
+ }
+ //non compliant ones innerHTML
+ } else if (item.innerHTML) {
+ innerText.push(item.innerHTML);
}
- };
+
+ applyStyle(item, innerText.join(""));
+ }
+ };
try {
var scriptElements = this.findByTagNames(item, {"link":1,"style":1}, true);
@@ -121,43 +130,66 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
* @param {Node} item
*/
runScripts: function(item, xmlData) {
+ var _T = this;
+ var finalScripts = [];
+ var _RT = this._RT;
+
+ var evalCollectedScripts = function (scriptsToProcess) {
+ if (scriptsToProcess && scriptsToProcess.length) {
+ //script source means we have to eval the existing
+ //scripts before running the include
+ var joinedScripts = [];
+ for(var scrptCnt = 0; scrptCnt < scriptsToProcess.length; scrptCnt++) {
+ var item = scriptsToProcess[scrptCnt];
+ if (!item.cspMeta) {
+ joinedScripts.push(item.text)
+ } else {
+ if (joinedScripts.length) {
+ _RT.globalEval(joinedScripts.join("\n"));
+ joinedScripts.length = 0;
+ }
+ _RT.globalEval(item.text, item.cspMeta);
+ }
+ }
+
+ if (joinedScripts.length) {
+ _RT.globalEval(joinedScripts.join("\n"));
+ joinedScripts.length = 0;
+ }
+ }
+ return [];
+ }
+
+
var _Lang = this._Lang,
- _RT = this._RT,
- finalScripts = [],
execScrpt = function(item) {
var tagName = item.tagName;
var type = item.type || "";
//script type javascript has to be handled by eval, other types
//must be handled by the browser
if (tagName && _Lang.equalsIgnoreCase(tagName, "script") &&
- (type === "" ||
+ (type === "" ||
_Lang.equalsIgnoreCase(type,"text/javascript") ||
_Lang.equalsIgnoreCase(type,"javascript") ||
_Lang.equalsIgnoreCase(type,"text/ecmascript") ||
_Lang.equalsIgnoreCase(type,"ecmascript"))) {
- var nonce = item.getAttribute("nonce") || null;
+ //now given that scripts can embed nonce
+ //we cannoit
+ var nonce = _RT.resolveNonce(item);
var src = item.getAttribute('src');
if ('undefined' != typeof src
- && null != src
- && src.length > 0
- ) {
+ && null != src
+ && src.length > 0
+ ) {
//we have to move this into an inner if because chrome otherwise chokes
//due to changing the and order instead of relying on left to right
- //if faces.js is already registered we do not replace it anymore
- if ((src.indexOf("ln=scripts") == -1 && src.indexOf("ln=jakarta.faces") == -1) || (src.indexOf("/faces.js") == -1
- && src.indexOf("/faces-uncompressed.js") == -1)) {
-
- if (finalScripts.length) {
- //script source means we have to eval the existing
- //scripts before running the include
- for(var cnt = 0; cnt < finalScripts.length; cnt++) {
- _RT.globalEval(finalScripts[cnt].text, finalScripts[cnt]["cspMeta"] || null);
- }
-
- finalScripts = [];
- }
+ //if jsf.js is already registered we do not replace it anymore
+ if ((src.indexOf("ln=scripts") == -1 && src.indexOf("ln=javax.faces") == -1) || (src.indexOf("/jsf.js") == -1
+ && src.indexOf("/jsf-uncompressed.js") == -1)) {
+
+ finalScripts = evalCollectedScripts(finalScripts);
_RT.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8", false, nonce ? {nonce: nonce} : null );
}
@@ -188,7 +220,6 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
}: {
text: test
});
-
}
}
};
@@ -198,11 +229,7 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
for (var cnt = 0; cnt < scriptElements.length; cnt++) {
execScrpt(scriptElements[cnt]);
}
- if (finalScripts.length) {
- for(var cnt = 0; cnt < finalScripts.length; cnt++) {
- _RT.globalEval(finalScripts[cnt].text, finalScripts[cnt]["cspMeta"] || null);
- }
- }
+ evalCollectedScripts(finalScripts);
} catch (e) {
//we are now in accordance with the rest of the system of showing errors only in development mode
//the default error output is alert we always can override it with
@@ -348,9 +375,9 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
if (markup === "") return null;
var evalNodes = this._buildEvalNodes(item, markup),
- currentRef = item,
- parentNode = item.parentNode,
- ret = [];
+ currentRef = item,
+ parentNode = item.parentNode,
+ ret = [];
for (var cnt = evalNodes.length - 1; cnt >= 0; cnt--) {
currentRef = parentNode.insertBefore(evalNodes[cnt], currentRef);
ret.push(currentRef);
@@ -372,9 +399,9 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
if (markup === "") return null;
var evalNodes = this._buildEvalNodes(item, markup),
- currentRef = item,
- parentNode = item.parentNode,
- ret = [];
+ currentRef = item,
+ parentNode = item.parentNode,
+ ret = [];
for (var cnt = 0; cnt < evalNodes.length; cnt++) {
if (currentRef.nextSibling) {
diff --git a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_EvalHandlers.js b/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_EvalHandlers.js
index 43f78f4cb..6921f47e8 100644
--- a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_EvalHandlers.js
+++ b/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_EvalHandlers.js
@@ -94,6 +94,17 @@ if (!myfaces._impl.core._EvalHandlers) {
document.head.removeChild(htmlScriptElement);
};
+ _T.resolveNonce = function(item) {
+ var nonce = null;
+ if(!!(item && item.nonce)) {
+ nonce = item.nonce;
+ } else if(!!item) {
+ nonce = item.getAttribute("nonce");
+ }
+ //empty nonce means no nonce, the rest
+ //of the code treats it like null
+ return (!nonce) ? null : nonce;
+ }
/*
* determines the facesjs nonce and adds them to the namespace
* this is done once and only lazily
@@ -105,9 +116,9 @@ if (!myfaces._impl.core._EvalHandlers) {
}
//since our baseline atm is ie11 we cannot use document.currentScript globally
- if(document.currentScript && document.currentScript.getAttribute("nonce")) {
+ if(_T.resolveNonce(document.currentScript)) {
//fastpath for modern browsers
- return document.currentScript.getAttribute("nonce") || null;
+ return _T.resolveNonce(document.currentScript);
}
var scripts = document.querySelectorAll("script[src], link[src]");
@@ -116,7 +127,7 @@ if (!myfaces._impl.core._EvalHandlers) {
//we search all scripts
for(var cnt = 0; scripts && cnt < scripts.length; cnt++) {
var scriptNode = scripts[cnt];
- if(!scriptNode.getAttribute("nonce")) {
+ if(!_T.resolveNonce(scriptNode)) {
continue;
}
var src = scriptNode.getAttribute("src") || "";
@@ -133,7 +144,7 @@ if (!myfaces._impl.core._EvalHandlers) {
nonce: null
};
if(faces_js) {
- myfaces.config.cspMeta.nonce = faces_js.getAttribute("nonce") || null;
+ myfaces.config.cspMeta.nonce = _T.resolveNonce(faces_js);
}
return myfaces.config.cspMeta.nonce;
};
diff --git a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js b/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
index 51196b7ef..90ce05d3d 100644
--- a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
+++ b/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
@@ -77,6 +77,10 @@ if (!myfaces._impl.core._Runtime) {
return myfaces._impl.core._EvalHandlers.globalEval(code, cspMeta);
};
+ _T.resolveNonce = function(item) {
+ return myfaces._impl.core._EvalHandlers.resolveNonce(item);
+ };
+
/**
* applies an object to a namespace
* basically does what bla.my.name.space = obj does