1 /* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to you under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /** 18 * @namespace 19 * @name window 20 * @description Eval routines, depending on the browser. 21 * <p/> 22 * The problem solved in this class is the problem on how to perform 23 * a global eval on multiple browsers. Some browsers auto eval themselves 24 * they do not need to be called 25 * <li>Some work with a window.eval.call(window,... </li> 26 * <li>Others use simply execScript <li> 27 * <li>Some others work only with the head appendix method 28 * head.appendChild(<script...., head.removeChild(<script </li> 29 * <p/> 30 * Note: The code here already is precompressed because the compressor 31 * fails on it, the deficits in readability will be covered by more comments 32 * 33 */ 34 35 36 if (!window.myfaces) { 37 /** 38 * @namespace 39 * @name myfaces 40 */ 41 var myfaces = new function() { 42 }; 43 window.myfaces = myfaces; 44 } 45 46 /** 47 * @memberOf myfaces 48 * @namespace 49 * @name _impl 50 */ 51 myfaces._impl = (myfaces._impl) ? myfaces._impl : {}; 52 /** 53 * @memberOf myfaces._impl 54 * @namespace 55 * @name core 56 */ 57 myfaces._impl.core = (myfaces._impl.core) ? myfaces._impl.core :{}; 58 59 if (!myfaces._impl.core._EvalHandlers) { 60 /** 61 * @memberOf myfaces._impl.core 62 * @namespace 63 * @name _EvalHandlers 64 */ 65 myfaces._impl.core._EvalHandlers = new function() { 66 //the rest of the namespaces can be handled by our namespace feature 67 //helper to avoid unneeded hitches 68 /** 69 * @borrows myfaces._impl.core._Runtime as _T 70 */ 71 var _T = this; 72 73 // note it is safe to remove the cascaded global eval 74 // the head appendix method is the standard method and has been 75 // for over a decade even on ie6 (see file history) 76 /** 77 * an implementation of eval which drops legacy support 78 * and allows nonce 79 * @param code 80 * @param cspMeta optional csp metadata, only allowed key atm nonce 81 */ 82 _T.globalEval = function(code, cspMeta) { 83 //check for jsf nonce 84 var nonce = cspMeta ? cspMeta.nonce : this._currentScriptNonce(); 85 86 var element = document.createElement("script"); 87 element.setAttribute("type", "text/javascript"); 88 element.innerHTML = code; 89 if(nonce) { 90 element.setAttribute("nonce", nonce); 91 } 92 //head appendix method, modern browsers use this method savely to eval scripts 93 //we did not use it up until now because there were really old legacy browsers where 94 //it did not work 95 var htmlScriptElement = document.head.appendChild(element); 96 document.head.removeChild(htmlScriptElement); 97 }; 98 99 _T.resolveNonce = function(item) { 100 var nonce = null; 101 if(!!(item && item.nonce)) { 102 nonce = item.nonce; 103 } else if(!!item && item.getAttribute) { 104 nonce = item.getAttribute("nonce"); 105 } 106 //empty nonce means no nonce, the rest 107 //of the code treats it like null 108 return (!nonce) ? null : nonce; 109 } 110 /* 111 * determines the jsfjs nonce and adds them to the namespace 112 * this is done once and only lazily 113 */ 114 _T._currentScriptNonce = function() { 115 //already processed 116 if(myfaces.config && myfaces.config.cspMeta) { 117 return myfaces.config.cspMeta.nonce; 118 } 119 120 //since our baseline atm is ie11 we cannot use document.currentScript globally 121 if(_T.resolveNonce(document.currentScript)) { 122 // fastpath for modern browsers 123 return _T.resolveNonce(document.currentScript); 124 } 125 126 var _Lang = myfaces._impl._util._Lang; 127 var scripts = _Lang.objToArray(document.getElementsByTagName("script")) 128 .concat(_Lang.objToArray(document.getElementsByTagName("link"))); 129 130 var jsf_js = null; 131 132 //we search all scripts 133 for(var cnt = 0; scripts && cnt < scripts.length; cnt++) { 134 var scriptNode = scripts[cnt]; 135 if(!_T.resolveNonce(scriptNode)) { 136 continue; 137 } 138 var src = scriptNode.getAttribute("src") || ""; 139 if(src && !src.match(/jsf\.js\?ln\=javax\.faces/gi)) { 140 jsf_js = scriptNode; 141 //the first one is the one we have our code in 142 //subsequent ones do not overwrite our code 143 break; 144 } 145 } 146 //found 147 myfaces.config = myfaces.config || {}; 148 myfaces.config.cspMeta = myfaces.config.cspMeta || { 149 nonce: null 150 }; 151 if(jsf_js) { 152 myfaces.config.cspMeta.nonce = _T.resolveNonce(jsf_js); 153 } 154 return myfaces.config.cspMeta.nonce; 155 }; 156 157 }; 158 }