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 /* 98 * determines the facesjs nonce and adds them to the namespace 99 * this is done once and only lazily 100 */ 101 _T._currentScriptNonce = function() { 102 //already processed 103 if(myfaces.config && myfaces.config.cspMeta) { 104 return myfaces.config.cspMeta.nonce; 105 } 106 107 //since our baseline atm is ie11 we cannot use document.currentScript globally 108 if(document.currentScript && document.currentScript.getAttribute("nonce")) { 109 //fastpath for modern browsers 110 return document.currentScript.getAttribute("nonce") || null; 111 } 112 113 var scripts = document.querySelectorAll("script[src], link[src]"); 114 var faces_js = null; 115 116 //we search all scripts 117 for(var cnt = 0; scripts && cnt < scripts.length; cnt++) { 118 var scriptNode = scripts[cnt]; 119 if(!scriptNode.getAttribute("nonce")) { 120 continue; 121 } 122 var src = scriptNode.getAttribute("src") || ""; 123 if(src && !src.match(/faces\.js\?ln\=jakarta\.faces/gi)) { 124 faces_js = scriptNode; 125 //the first one is the one we have our code in 126 //subsequent ones do not overwrite our code 127 break; 128 } 129 } 130 //found 131 myfaces.config = myfaces.config || {}; 132 myfaces.config.cspMeta = myfaces.config.cspMeta || { 133 nonce: null 134 }; 135 if(faces_js) { 136 myfaces.config.cspMeta.nonce = faces_js.getAttribute("nonce") || null; 137 } 138 return myfaces.config.cspMeta.nonce; 139 }; 140 141 }; 142 }