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 2019/07/19 08:59:59 UTC
[myfaces] branch master updated:
https://issues.apache.org/jira/browse/MYFACES-4265,
https://issues.apache.org/jira/browse/MYFACES-4280:
This is an automated email from the ASF dual-hosted git repository.
werpu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces.git
The following commit(s) were added to refs/heads/master by this push:
new 5d12578 https://issues.apache.org/jira/browse/MYFACES-4265, https://issues.apache.org/jira/browse/MYFACES-4280:
5d12578 is described below
commit 5d125782cd9ec28f531a93cdf674584f155e2d46
Author: Werner Punz <we...@gmail.com>
AuthorDate: Fri Jul 19 10:59:51 2019 +0200
https://issues.apache.org/jira/browse/MYFACES-4265,
https://issues.apache.org/jira/browse/MYFACES-4280:
adding nonce support
Dropping additional legacy code in the eval area and removing the
now unused runtimequirks file
---
.../META-INF/resources/myfaces/_impl/_util/_Dom.js | 24 +++-
.../resources/myfaces/_impl/core/_EvalHandlers.js | 150 ++++++++-------------
.../resources/myfaces/_impl/core/_Runtime.js | 16 ++-
.../resources/myfaces/_impl/core/_RuntimeQuirks.js | 51 -------
.../myfaces/_impl/xhrCore/_AjaxResponse.js | 2 +
5 files changed, 86 insertions(+), 157 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 4521e59..f3cd731 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
@@ -63,6 +63,10 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
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"));
+ }
+
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;
@@ -132,6 +136,8 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
_Lang.equalsIgnoreCase(type,"text/ecmascript") ||
_Lang.equalsIgnoreCase(type,"ecmascript"))) {
+ var nonce = item.getAttribute("nonce") || null;
+
var src = item.getAttribute('src');
if ('undefined' != typeof src
&& null != src
@@ -142,14 +148,17 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
//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)) {
+
if (finalScripts.length) {
//script source means we have to eval the existing
//scripts before running the include
- _RT.globalEval(finalScripts.join("\n"));
+ for(var cnt = 0; cnt < finalScripts.length; cnt++) {
+ _RT.globalEval(finalScripts[cnt].text, finalScripts[cnt]["cspMeta"] || null);
+ }
finalScripts = [];
}
- _RT.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8", false);
+ _RT.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8", false, nonce ? {nonce: nonce} : null );
}
} else {
@@ -173,7 +182,12 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
}
// we have to run the script under a global context
//we store the script for less calls to eval
- finalScripts.push(test);
+ finalScripts.push(nonce ? {
+ cspMeta: {nonce: nonce},
+ text: test
+ }: {
+ text: test
+ });
}
}
@@ -185,7 +199,9 @@ _MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prot
execScrpt(scriptElements[cnt]);
}
if (finalScripts.length) {
- _RT.globalEval(finalScripts.join("\n"));
+ for(var cnt = 0; cnt < finalScripts.length; cnt++) {
+ _RT.globalEval(finalScripts[cnt].text, finalScripts[cnt]["cspMeta"] || null);
+ }
}
} catch (e) {
//we are now in accordance with the rest of the system of showing errors only in development mode
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 e0b9984..f986bf0 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
@@ -70,114 +70,72 @@ if (!myfaces._impl.core._EvalHandlers) {
*/
var _T = this;
- /*cascaded eval methods depending upon the browser*/
/**
- * @function
+ * an implementation of eval which drops legacy support
+ * and allows nonce
* @param code
-
- *
- * evals a script globally using exec script (ie6 fallback)
- * @param {String} code the code which has to be evaluated
- * @borrows myfaces._impl.core._Runtime as _T
- *
- * TODO eval if we cannot replace this method with the head appendix
- * method which is faster for ie this also would reduce our code
- * by a few bytes
+ * @param cspMeta optional csp metadata, only allowed key atm nonce
*/
- _T._evalExecScript = function(code) {
- //execScript definitely only for IE otherwise we might have a custom
- //window extension with undefined behavior on our necks
- //window.execScript does not return anything
- //on htmlunit it return "null object"
- //_r == ret
- var _r = window.execScript(code);
- if ('undefined' != typeof _r && _r == "null" /*htmlunit bug*/) {
- return null;
- }
- return _r;
- };
+ _T.globalEval = function(code, cspMeta) {
+ //check for jsf nonce
+ var nonce = cspMeta ? cspMeta.nonce : this._currentScriptNonce();
- /**
- * flakey head appendix method which does not work in the correct
- * order or at all for all modern browsers
- * but seems to be the only method which works on blackberry correctly
- * hence we are going to use it as fallback
- *
- * @param {String} code the code part to be evaled
- * @borrows myfaces._impl.core._Runtime as _T
- */
- _T._evalHeadAppendix = function(code) {
- //_l == location
- var _l = document.getElementsByTagName("head")[0] || document.documentElement;
- //_p == placeHolder
- var _p = document.createElement("script");
- _p.type = "text/javascript";
- _p.text = code;
- _l.insertBefore(_p, _l.firstChild);
- _l.removeChild(_p);
- return null;
+ var element = document.createElement("script");
+ element.setAttribute("type", "text/javascript");
+ element.innerHTML = code;
+ if(nonce) {
+ element.setAttribute("nonce", nonce);
+ }
+ //head appendix method, modern browsers use this method savely to eval scripts
+ //we did not use it up until now because there were really old legacy browsers where
+ //it did not work
+ var htmlScriptElement = document.head.appendChild(element);
+ document.head.removeChild(htmlScriptElement);
};
- /**
- * @name myfaces._impl.core._Runtime._standardGlobalEval
- * @private
- * @param {String} code
- */
- _T._standardGlobalEval = function(code) {
- //fix which works in a cross browser way
- //we used to scope an anonymous function
- //but I think this is better
- //the reason is some Firefox versions
- // apply a wrong scope
- //if we call eval by not scoping
- //_U == "undefined"
- var _U = "undefined";
- var gEval = function () {
- //_r == retVal;
- var _r = window.eval.call(window, code);
- if (_U == typeof _r) return null;
- return _r;
- };
- var _r = gEval();
- if (_U == typeof _r) return null;
- return _r;
- };
+ /*
+ * determines the jsfjs nonce and adds them to the namespace
+ * this is done once and only lazily
+ */
+ _T._currentScriptNonce = function() {
+ //already processed
+ if(myfaces.config && myfaces.config.cspMeta) {
+ return myfaces.config.cspMeta.nonce;
+ }
- /**
- * global eval on scripts
- * @param {String} c (code abbreviated since the compression does not work here)
- * @name myfaces._impl.core._Runtime.globalEval
- * @function
- */
- _T.globalEval = function(c) {
- //TODO add a config param which allows to evaluate global scripts even if the call
- //is embedded in an iframe
- //We lazy init the eval type upon the browsers
- //capabilities
- var _e = "_evalType";
- var _w = window;
- var _b = myfaces._impl.core._Runtime.browser;
- //central routine to determine the eval method
- if (!_T[_e]) {
- //execScript supported
- _T[_e] = _w.execScript ? "_evalExecScript" : null;
+ //since our baseline atm is ie11 we cannot use document.currentScript globally
+ if(document.currentScript && document.currentScript.getAttribute("nonce")) {
+ //fastpath for modern browsers
+ return document.currentScript.getAttribute("nonce") || null;
+ }
- //in case of no support we go to the standard global eval window.eval.call(window,
- // with Firefox fixes for scoping
- _T[_e] = _T[_e] ||(( _w.eval && (!_b.isBlackBerry ||_b.isBlackBerry >= 6)) ? "_standardGlobalEval" : null);
+ var scripts = document.querySelectorAll("script[src], link[src]");
+ var jsf_js = null;
- //this one routes into the hed appendix method
- _T[_e] = _T[_e] ||((_w.eval ) ? "_evalHeadAppendix" : null);
+ //we search all scripts
+ for(var cnt = 0; scripts && cnt < scripts.length; cnt++) {
+ var scriptNode = scripts[cnt];
+ if(!scriptNode.getAttribute("nonce")) {
+ continue;
+ }
+ var src = scriptNode.getAttribute("src") || "";
+ if(src && !src.match(/jsf\.js\?ln\=javax\.faces/gi)) {
+ jsf_js = scriptNode;
+ //the first one is the one we have our code in
+ //subsequent ones do not overwrite our code
+ break;
+ }
}
- if (_T[_e]) {
- //we now execute the eval method
- return _T[_T[_e]](c);
+ //found
+ myfaces.config = myfaces.config || {};
+ myfaces.config.cspMeta = myfaces.config.cspMeta || {
+ nonce: null
+ };
+ if(jsf_js) {
+ myfaces.config.cspMeta.nonce = jsf_js.getAttribute("nonce") || null;
}
- //we probably have covered all browsers, but this is a safety net which might be triggered
- //by some foreign browser which is not covered by the above cases
- eval.call(window, c);
- return null;
+ 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 6b4cf1e..5e859d8 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
@@ -73,8 +73,8 @@ if (!myfaces._impl.core._Runtime) {
* @name myfaces._impl.core._Runtime.globalEval
* @function
*/
- _T.globalEval = function(code) {
- return myfaces._impl.core._EvalHandlers.globalEval(code);
+ _T.globalEval = function(code, cspMeta) {
+ return myfaces._impl.core._EvalHandlers.globalEval(code, cspMeta);
};
/**
@@ -391,9 +391,10 @@ if (!myfaces._impl.core._Runtime) {
* @param {Boolean} defer defer true or false, same as the javascript tag defer param
* @param {String} charSet the charset under which the script has to be loaded
* @param {Boolean} async tells whether the script can be asynchronously loaded or not, currently
+ * @param cspMetas csp meta data to be processed by globalEval
* not used
*/
- this.loadScriptEval = function(src, type, defer, charSet, async) {
+ this.loadScriptEval = function(src, type, defer, charSet, async, cspMeta) {
var xhr = _T.getXHRObject();
xhr.open("GET", src, false);
@@ -415,12 +416,12 @@ if (!myfaces._impl.core._Runtime) {
//we moved the sourceurl notation to # instead of @ because ie does not cover it correctly
//newer browsers understand # including ie since windows 8.1
//see http://updates.html5rocks.com/2013/06/sourceMappingURL-and-sourceURL-syntax-changed
- _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src);
+ _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src, cspMeta);
} else {
//TODO not ideal we maybe ought to move to something else here
//but since it is not in use yet, it is ok
setTimeout(function() {
- _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src);
+ _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src, cspMeta);
}, 1);
}
} else {
@@ -441,7 +442,7 @@ if (!myfaces._impl.core._Runtime) {
* @param {Boolean} defer defer true or false, same as the javascript tag defer param
* @param {String} charSet the charset under which the script has to be loaded
*/
- this.loadScriptByBrowser = function(src, type, defer, charSet, async) {
+ this.loadScriptByBrowser = function(src, type, defer, charSet, async, cspMeta) {
//if a head is already present then it is safer to simply
//use the body, some browsers prevent head alterations
//after the first initial rendering
@@ -461,6 +462,9 @@ if (!myfaces._impl.core._Runtime) {
script.type = type || "text/javascript";
script.src = src;
+ if(cspMeta && cspMeta.nonce) {
+ script.setAttribute("nonce", cspMeta.nonce);
+ }
if (charSet) {
script.charset = charSet;
}
diff --git a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_RuntimeQuirks.js b/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_RuntimeQuirks.js
deleted file mode 100644
index b5bdb3d..0000000
--- a/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_RuntimeQuirks.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 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 (!document.querySelectorAll || !window.XMLHttpRequest) {
-
- //initial browser detection, we encapsule it in a closure
- //to drop all temporary variables from ram as soon as possible
- //we run into the quirks fallback if XMLHttpRequest is not enabled
- (function() {
- var _T = myfaces._impl.core._Runtime;
-
- _T.getXHRObject = function() {
- //since this is a global object ie hates it if we do not check for undefined
- if (window.XMLHttpRequest) {
- var _ret = new XMLHttpRequest();
- //we now check the xhr level
- //sendAsBinary = 1.5 which means mozilla only
- //upload attribute present == level2
-
- if (!_T.XHR_LEVEL) {
- var _e = _T.exists;
- _T.XHR_LEVEL = (_e(_ret, "sendAsBinary")) ? 1.5 : 1;
- _T.XHR_LEVEL = (_e(_ret, "upload") && 'undefined' != typeof FormData) ? 2 : _T.XHR_LEVEL;
- }
- return _ret;
- }
- //IE
- try {
- _T.XHR_LEVEL = 1;
- return new ActiveXObject("Msxml2.XMLHTTP");
- } catch (e) {
-
- }
- return new ActiveXObject('Microsoft.XMLHTTP');
- };
-
-
- })();
-}
\ No newline at end of file
diff --git a/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js b/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
index 6e2285d..2fb3bc7 100644
--- a/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
+++ b/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
@@ -456,6 +456,8 @@ _MF_SINGLTN(_PFX_XHR + "_AjaxResponse", _MF_OBJECT, /** @lends myfaces._impl.xhr
case this.CMD_UPDATE:
this.processUpdate(request, context, changes[i]);
break;
+ //this one needs a csp spec extension for the global eval
+ //for now we recycle the csp for this case from the jsf.js file
case this.CMD_EVAL:
_Lang.globalEval(changes[i].firstChild.data);
break;