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 74 /** 75 * an implementation of eval which drops legacy support 76 * and allows nonce 77 * @param code 78 * @param cspMeta optional csp metadata, only allowed key atm nonce 79 */ 80 _T.globalEval = function(code, cspMeta) { 81 //check for faces nonce 82 var nonce = cspMeta ? cspMeta.nonce : this._currentScriptNonce(); 83 84 var element = document.createElement("script"); 85 element.setAttribute("type", "text/javascript"); 86 element.innerHTML = code; 87 if(nonce) { 88 element.setAttribute("nonce", nonce); 89 } 90 //head appendix method, modern browsers use this method savely to eval scripts 91 //we did not use it up until now because there were really old legacy browsers where 92 //it did not work 93 var htmlScriptElement = document.head.appendChild(element); 94 document.head.removeChild(htmlScriptElement); 95 }; 96 97 _T.resolveNonce = function(item) { 98 var nonce = null; 99 if(!!(item && item.nonce)) { 100 nonce = item.nonce; 101 } else if(!!item) { 102 nonce = item.getAttribute("nonce"); 103 } 104 //empty nonce means no nonce, the rest 105 //of the code treats it like null 106 return (!nonce) ? null : nonce; 107 } 108 /* 109 * determines the facesjs nonce and adds them to the namespace 110 * this is done once and only lazily 111 */ 112 _T._currentScriptNonce = function() { 113 //already processed 114 if(myfaces.config && myfaces.config.cspMeta) { 115 return myfaces.config.cspMeta.nonce; 116 } 117 118 //since our baseline atm is ie11 we cannot use document.currentScript globally 119 if(_T.resolveNonce(document.currentScript)) { 120 //fastpath for modern browsers 121 return _T.resolveNonce(document.currentScript); 122 } 123 124 var scripts = document.querySelectorAll("script[src], link[src]"); 125 var faces_js = null; 126 127 //we search all scripts 128 for(var cnt = 0; scripts && cnt < scripts.length; cnt++) { 129 var scriptNode = scripts[cnt]; 130 if(!_T.resolveNonce(scriptNode)) { 131 continue; 132 } 133 var src = scriptNode.getAttribute("src") || ""; 134 if(src && !src.match(/faces\.js\?ln\=jakarta\.faces/gi)) { 135 faces_js = scriptNode; 136 //the first one is the one we have our code in 137 //subsequent ones do not overwrite our code 138 break; 139 } 140 } 141 //found 142 myfaces.config = myfaces.config || {}; 143 myfaces.config.cspMeta = myfaces.config.cspMeta || { 144 nonce: null 145 }; 146 if(faces_js) { 147 myfaces.config.cspMeta.nonce = _T.resolveNonce(faces_js); 148 } 149 return myfaces.config.cspMeta.nonce; 150 }; 151 152 }; 153 }