%PDF- %PDF-
Direktori : /home/riacommer/public_html/admin/vendor/wysihtml5/src/dom/ |
Current File : /home/riacommer/public_html/admin/vendor/wysihtml5/src/dom/sandbox.js |
/** * Sandbox for executing javascript, parsing css styles and doing dom operations in a secure way * * Browser Compatibility: * - Secure in MSIE 6+, but only when the user hasn't made changes to his security level "restricted" * - Partially secure in other browsers (Firefox, Opera, Safari, Chrome, ...) * * Please note that this class can't benefit from the HTML5 sandbox attribute for the following reasons: * - sandboxing doesn't work correctly with inlined content (src="javascript:'<html>...</html>'") * - sandboxing of physical documents causes that the dom isn't accessible anymore from the outside (iframe.contentWindow, ...) * - setting the "allow-same-origin" flag would fix that, but then still javascript and dom events refuse to fire * - therefore the "allow-scripts" flag is needed, which then would deactivate any security, as the js executed inside the iframe * can do anything as if the sandbox attribute wasn't set * * @param {Function} [readyCallback] Method that gets invoked when the sandbox is ready * @param {Object} [config] Optional parameters * * @example * new wysihtml5.dom.Sandbox(function(sandbox) { * sandbox.getWindow().document.body.innerHTML = '<img src=foo.gif onerror="alert(document.cookie)">'; * }); */ (function(wysihtml5) { var /** * Default configuration */ doc = document, /** * Properties to unset/protect on the window object */ windowProperties = [ "parent", "top", "opener", "frameElement", "frames", "localStorage", "globalStorage", "sessionStorage", "indexedDB" ], /** * Properties on the window object which are set to an empty function */ windowProperties2 = [ "open", "close", "openDialog", "showModalDialog", "alert", "confirm", "prompt", "openDatabase", "postMessage", "XMLHttpRequest", "XDomainRequest" ], /** * Properties to unset/protect on the document object */ documentProperties = [ "referrer", "write", "open", "close" ]; wysihtml5.dom.Sandbox = Base.extend( /** @scope wysihtml5.dom.Sandbox.prototype */ { constructor: function(readyCallback, config) { this.callback = readyCallback || wysihtml5.EMPTY_FUNCTION; this.config = wysihtml5.lang.object({}).merge(config).get(); this.iframe = this._createIframe(); }, insertInto: function(element) { if (typeof(element) === "string") { element = doc.getElementById(element); } element.appendChild(this.iframe); }, getIframe: function() { return this.iframe; }, getWindow: function() { this._readyError(); }, getDocument: function() { this._readyError(); }, destroy: function() { var iframe = this.getIframe(); iframe.parentNode.removeChild(iframe); }, _readyError: function() { throw new Error("wysihtml5.Sandbox: Sandbox iframe isn't loaded yet"); }, /** * Creates the sandbox iframe * * Some important notes: * - We can't use HTML5 sandbox for now: * setting it causes that the iframe's dom can't be accessed from the outside * Therefore we need to set the "allow-same-origin" flag which enables accessing the iframe's dom * But then there's another problem, DOM events (focus, blur, change, keypress, ...) aren't fired. * In order to make this happen we need to set the "allow-scripts" flag. * A combination of allow-scripts and allow-same-origin is almost the same as setting no sandbox attribute at all. * - Chrome & Safari, doesn't seem to support sandboxing correctly when the iframe's html is inlined (no physical document) * - IE needs to have the security="restricted" attribute set before the iframe is * inserted into the dom tree * - Believe it or not but in IE "security" in document.createElement("iframe") is false, even * though it supports it * - When an iframe has security="restricted", in IE eval() & execScript() don't work anymore * - IE doesn't fire the onload event when the content is inlined in the src attribute, therefore we rely * on the onreadystatechange event */ _createIframe: function() { var that = this, iframe = doc.createElement("iframe"); iframe.className = "wysihtml5-sandbox"; wysihtml5.dom.setAttributes({ "security": "restricted", "allowtransparency": "true", "frameborder": 0, "width": 0, "height": 0, "marginwidth": 0, "marginheight": 0 }).on(iframe); // Setting the src like this prevents ssl warnings in IE6 if (wysihtml5.browser.throwsMixedContentWarningWhenIframeSrcIsEmpty()) { iframe.src = "javascript:'<html></html>'"; } iframe.onload = function() { iframe.onreadystatechange = iframe.onload = null; that._onLoadIframe(iframe); }; iframe.onreadystatechange = function() { if (/loaded|complete/.test(iframe.readyState)) { iframe.onreadystatechange = iframe.onload = null; that._onLoadIframe(iframe); } }; return iframe; }, /** * Callback for when the iframe has finished loading */ _onLoadIframe: function(iframe) { // don't resume when the iframe got unloaded (eg. by removing it from the dom) if (!wysihtml5.dom.contains(doc.documentElement, iframe)) { return; } var that = this, iframeWindow = iframe.contentWindow, iframeDocument = iframe.contentWindow.document, charset = doc.characterSet || doc.charset || "utf-8", sandboxHtml = this._getHtml({ charset: charset, stylesheets: this.config.stylesheets }); // Create the basic dom tree including proper DOCTYPE and charset iframeDocument.open("text/html", "replace"); iframeDocument.write(sandboxHtml); iframeDocument.close(); this.getWindow = function() { return iframe.contentWindow; }; this.getDocument = function() { return iframe.contentWindow.document; }; // Catch js errors and pass them to the parent's onerror event // addEventListener("error") doesn't work properly in some browsers // TODO: apparently this doesn't work in IE9! iframeWindow.onerror = function(errorMessage, fileName, lineNumber) { throw new Error("wysihtml5.Sandbox: " + errorMessage, fileName, lineNumber); }; if (!wysihtml5.browser.supportsSandboxedIframes()) { // Unset a bunch of sensitive variables // Please note: This isn't hack safe! // It more or less just takes care of basic attacks and prevents accidental theft of sensitive information // IE is secure though, which is the most important thing, since IE is the only browser, who // takes over scripts & styles into contentEditable elements when copied from external websites // or applications (Microsoft Word, ...) var i, length; for (i=0, length=windowProperties.length; i<length; i++) { this._unset(iframeWindow, windowProperties[i]); } for (i=0, length=windowProperties2.length; i<length; i++) { this._unset(iframeWindow, windowProperties2[i], wysihtml5.EMPTY_FUNCTION); } for (i=0, length=documentProperties.length; i<length; i++) { this._unset(iframeDocument, documentProperties[i]); } // This doesn't work in Safari 5 // See http://stackoverflow.com/questions/992461/is-it-possible-to-override-document-cookie-in-webkit this._unset(iframeDocument, "cookie", "", true); } this.loaded = true; // Trigger the callback setTimeout(function() { that.callback(that); }, 0); }, _getHtml: function(templateVars) { var stylesheets = templateVars.stylesheets, html = "", i = 0, length; stylesheets = typeof(stylesheets) === "string" ? [stylesheets] : stylesheets; if (stylesheets) { length = stylesheets.length; for (; i<length; i++) { html += '<link rel="stylesheet" href="' + stylesheets[i] + '">'; } } templateVars.stylesheets = html; return wysihtml5.lang.string( '<!DOCTYPE html><html><head>' + '<meta charset="#{charset}">#{stylesheets}</head>' + '<body></body></html>' ).interpolate(templateVars); }, /** * Method to unset/override existing variables * @example * // Make cookie unreadable and unwritable * this._unset(document, "cookie", "", true); */ _unset: function(object, property, value, setter) { try { object[property] = value; } catch(e) {} try { object.__defineGetter__(property, function() { return value; }); } catch(e) {} if (setter) { try { object.__defineSetter__(property, function() {}); } catch(e) {} } if (!wysihtml5.browser.crashesWhenDefineProperty(property)) { try { var config = { get: function() { return value; } }; if (setter) { config.set = function() {}; } Object.defineProperty(object, property, config); } catch(e) {} } } }); })(wysihtml5);