Вход Регистрация
Файл: library/wysihtml5/src/dom/sandbox.js
Строк: 399
<?php
/**
 * 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(readyCallbackconfig) {
      
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.documentElementiframe)) {
        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(errorMessagefileNamelineNumber) {
        throw new 
Error("wysihtml5.Sandbox: " errorMessagefileNamelineNumber);
      };

      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 ilength;
        for (
i=0length=windowProperties.lengthi<lengthi++) {
          
this._unset(iframeWindowwindowProperties[i]);
        }
        for (
i=0length=windowProperties2.lengthi<lengthi++) {
          
this._unset(iframeWindowwindowProperties2[i], wysihtml5.EMPTY_FUNCTION);
        }
        for (
i=0length=documentProperties.lengthi<lengthi++) {
          
this._unset(iframeDocumentdocumentProperties[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<lengthi++) {
          
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(objectpropertyvaluesetter) {
      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(objectpropertyconfig);
        } catch(
e) {}
      }
    }
  });
})(
wysihtml5);
?>
Онлайн: 2
Реклама