123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- // wrapped by build app
- define("dojox/secure/sandbox", ["dijit","dojo","dojox","dojo/require!dojox/secure/DOM,dojox/secure/capability,dojo/NodeList-fx,dojo/_base/url"], function(dijit,dojo,dojox){
- dojo.provide("dojox.secure.sandbox");
- dojo.require("dojox.secure.DOM");
- dojo.require("dojox.secure.capability");
- dojo.require("dojo.NodeList-fx");
- dojo.require("dojo._base.url");
- (function() {
- var oldTimeout = setTimeout;
- var oldInterval = setInterval;
- if({}.__proto__){
- // mozilla has unsafe methods on array
- var fixMozArrayFunction = function (name) {
- var method = Array.prototype[name];
- if(method && !method.fixed){
- (Array.prototype[name] = function () {
- if (this == window) {
- throw new TypeError("Called with wrong this");
- }
- return method.apply(this, arguments);
- }).fixed = true;
- }
- };
- // these are not safe in mozilla
- fixMozArrayFunction('concat');
- fixMozArrayFunction('reverse');
- fixMozArrayFunction('sort');
- fixMozArrayFunction("slice");
- fixMozArrayFunction("forEach");
- fixMozArrayFunction("filter");
- fixMozArrayFunction("reduce");
- fixMozArrayFunction("reduceRight");
- fixMozArrayFunction("every");
- fixMozArrayFunction("map");
- fixMozArrayFunction("some");
- }
- var xhrGet = function(){
- return dojo.xhrGet.apply(dojo,arguments);
- };
- dojox.secure.sandbox = function(element) {
- // summary:
- // Creates a secure sandbox from which scripts and HTML can be loaded that
- // will only be able to access the provided element and it's descendants, the
- // rest of the DOM and JS environment will not be accessible to the sandboxed
- // scripts and HTML.
- //
- // element:
- // The DOM element to use as the container for the sandbox
- //
- // description:
- // This function will create and return a sandbox object (see dojox.secure.__Sandbox)
- // for the provided element.
- var wrap = dojox.secure.DOM(element);
- element = wrap(element);
- var document = element.ownerDocument;
- var mixin, dojo = dojox.secure._safeDojoFunctions(element,wrap);
- var imports= [];
- var safeCalls = ["isNaN","isFinite","parseInt","parseFloat","escape","unescape",
- "encodeURI","encodeURIComponent","decodeURI","decodeURIComponent",
- "alert","confirm","prompt", // some people may not want to allow these to be called, but they don't break capability-limiting
- "Error","EvalError","RangeError","ReferenceError","SyntaxError","TypeError",
- "Date","RegExp","Number","Object","Array","String","Math",
- //"ADSAFE", // not using ADSAFE runtime for the time being
- "setTimeout","setInterval","clearTimeout","clearInterval", // we make these safe below
- "dojo","get","set","forEach","load","evaluate"];
- for(var i in dojo){
- safeCalls.push(i); // add the safe dojo functions to as available global top level functions
- imports.push("var " + i + "=dojo." + i); // add to the list of imports
- }
- // open the dojo namespace (namespaces are pretty silly in an environment where you can't set globals)
- eval(imports.join(";"));
- function get(obj,prop) {
- // basic access by index function
- prop = '' + prop;
- if(dojox.secure.badProps.test(prop)) {
- throw new Error("bad property access");
- }
- if(obj.__get__) {
- return obj.__get__(prop);
- }
- return obj[prop];
- }
- function set(obj,prop,value) {
- // basic set by index function
- prop = '' + prop;
- get(obj,prop); // test it
- if(obj.__set) {
- return obj.__set(prop);
- }
- obj[prop] = value;
- return value;
- }
- function forEach(obj,fun) {
- // short syntax iterator function
- if(typeof fun != "function"){
- throw new TypeError();
- }
- if("length" in obj) {
- // do arrays the fast way
- if(obj.__get__) {
- // use the catch getter
- var len = obj.__get__('length');
- for (var i = 0; i < len; i++) {
- if(i in obj) {
- fun.call(obj, obj.__get__(i), i, obj);
- }
- }
- }
- else {
- // fast
- len = obj.length;
- for (i = 0; i < len; i++) {
- if(i in obj) {
- fun.call(obj, obj[i], i, obj);
- }
- }
- }
- }
- else {
- // for each an object
- for (i in obj) {
- fun.call(obj, get(obj,i), i, obj);
- }
- }
- }
- function Class(/*Function*/superclass, /*Object*/properties, /*Object*/classProperties) {
- // summary:
- // A safe class constructor
- //
- // superclass:
- // There may be zero or more superclass arguments. The constructed class
- // will inherit from any provided superclasses, protypically from the first,
- // via mixin for the subsequent. Later arguments
- // will override properties/methods from earlier arguments
- //
- // properties:
- // The constructed
- // "class" will also have the methods/properties defined in this argument.
- // These methods may utilize the <em>this</em> operator, and they
- // are only the code that has access to <em>this</em>. Inner functions
- // are also prohibited from using <em>this</em>.
- //
- // If no superclasses are provided, this object will be the prototype of the
- // constructed class (no copying
- // will be done). Consequently you can "beget" by calling new (Class(obj)).
- // All methods are "bound", each call results in |this| safety checking call.
- //
- // classProperties:
- // This properties will be copied to the new class function.
- //
- // Note that neither dojo.declare nor dojo.extend are acceptable class constructors as
- // they are completely unsecure. This class constructor is conceptually based on declare
- // but also somewhat influenced by base2, prototype, YUI, resig's patterns, etc.
- //
- // example:
- // | var Car = Class({drive:function(speed) { ... } ); // create a Car class with a "drive" method
- // | var FastCar = Class(Car,{driveFast: function(speed) { return this.drive(2 * speed); } }); // create a FastCar that extends Car
- // | var fastCar = new FastCar; // instantiate
- // | fastCar.driveFast(50); // call a method
- // | var driveFast = fastCar.driveFast;
- // | var driveFast(50); // this will throw an error, the method can be used with an object that is not an instance of FastCar
- var proto,superConstructor,ourConstructor;
- var arg;
- for (var i = 0, l = arguments.length; typeof (arg = arguments[i]) == 'function' && i < l; i++) {
- // go through each superclass argument
- if(proto) { // we have a prototype now, we must mixin now
- mixin(proto,arg.prototype);
- }
- else {
- // this is the first argument, so we can define the prototype ourselves
- // link up the prototype chain to the superclass's prototype, so we are a subtype
- superConstructor = arg;
- var F = function() {};
- F.prototype = arg.prototype;
- proto = new F;
- }
- }
- if(arg) { // the next object should be the properties
- // apply binding checking on all the functions
- for (var j in arg) {
- // TODO: check on non-enumerables?
- var value = arg[j];
- if(typeof value == 'function') {
- arg[j] = function() {
- if(this instanceof Class){
- return arguments.callee.__rawMethod__.apply(this,arguments);
- }
- throw new Error("Method called on wrong object");
- };
- arg[j].__rawMethod__ = value; // may want to use this for reconstruction and toString,valueOf
- }
- }
- if(arg.hasOwnProperty('constructor')) {
- ourConstructor = arg.constructor;
- }
- }
- proto = proto ? mixin(proto,arg) : arg; // if there is no proto yet, we can use the provided object
- function Class() {
- // the super class may not have been constructed using the same technique, we will just call the constructor
- if(superConstructor){
- superConstructor.apply(this,arguments);
- }
- if(ourConstructor){
- ourConstructor.apply(this,arguments);
- }
- }
- mixin(Class,arguments[i]); // the optional second object adds properties to the class
- proto.constructor = Class;
- Class.prototype = proto;
- return Class;
- }
- function checkString(func){
- if(typeof func != 'function') {
- throw new Error("String is not allowed in setTimeout/setInterval");
- }
- }
- function setTimeout(func,time) {
- // sandboxed setTimeout
- checkString(func);
- return oldTimeout(func,time);
- }
- function setInterval(func,time) {
- // sandboxed setInterval
- checkString(func);
- return oldInterval(func,time);
- }
- function evaluate(script){
- // sandboxed eval
- return wrap.evaluate(script);
- }
- var load = wrap.load = function(url){
- // provides a loader function for the sandbox
- if (url.match(/^[\w\s]*:/)){
- throw new Error("Access denied to cross-site requests");
- }
- return xhrGet({url:(new dojo._Url(wrap.rootUrl,url))+'',secure:true});
- }
- wrap.evaluate = function(script){
- //if(!alreadyValidated) {
- dojox.secure.capability.validate(script,safeCalls, // the safe dojo library and standard operators
- {document:1,element:1}); // these are secured DOM starting points
- //}
- if(script.match(/^\s*[\[\{]/)) {
- var result = eval('(' + script + ')');
- // TODO: call render on result?
- }
- else {
- eval(script);
- }
- //eval('wrap.evaluate=('+arguments.callee.toString()+')'); // yeah, recursive scoping;
- };
- return /*===== dojo.declare("dojox.secure.__Sandbox", null, =====*/ { // dojox.secure.__Sandbox
- loadJS : function(url){
- // summary:
- // Loads the script from the given URL using XHR (assuming
- // a plugin system is in place for cross-site requests) within the sandbox
- //
- // url:
- // The url of the script to load
- wrap.rootUrl = url;
- return xhrGet({url:url,secure:true}).addCallback(function(result) {
- evaluate(result,element /*If we get the results with a secure proxy, we would call put true here */);
- });
- },
- loadHTML : function(url){
- // summary:
- // Loads the web page from the provided URL using XHR (assuming the
- // plugin system is in place) within the sandbox. All scripts within the web
- // page will also be sandboxed.
- //
- // url:
- // The url of the web page to load
- wrap.rootUrl = url;
- return xhrGet({url:url,secure:true}).addCallback(function(result){
- element.innerHTML = result;
- });
- },
- evaluate : function(script){
- // summary:
- // Evaluates the given script within the sandbox
- //
- // script:
- // The JavaScript text to evaluate
- return wrap.evaluate(script);
- }
- // TODO: could add something for pre-validated scripts
- }/*===== ) =====*/;
- };
- })();
- dojox.secure._safeDojoFunctions = function(element,wrap) {
- // Creates a safe subset of Dojo core library
- var safeFunctions = ["mixin","require","isString","isArray","isFunction","isObject","isArrayLike","isAlien",
- "hitch","delegate","partial","trim","disconnect","subscribe","unsubscribe","Deferred","toJson","style","attr"];
- //var domFunctions = ["clone","byId"];
- var doc = element.ownerDocument;
- var unwrap = dojox.secure.unwrap;
- dojo.NodeList.prototype.addContent.safetyCheck = function(content){
- wrap.safeHTML(content);
- };
- dojo.NodeList.prototype.style.safetyCheck = function(name,value){
- if(name=='behavior'){
- throw new Error("Can not set behavior");
- }
- wrap.safeCSS(value);
- };
- dojo.NodeList.prototype.attr.safetyCheck = function(name,value){
- if (value && (name == 'src' || name == 'href' || name=='style')){
- throw new Error("Illegal to set " + name);
- }
- };
- var safe = {
- query : function(query,root) {
- return wrap(dojo.query(query,unwrap(root || element))); // wrap the NodeList
- },
- connect: function(el,event) {
- var obj = el;
- arguments[0] = unwrap(el);
- if(obj!=arguments[0] && event.substring(0,2) != 'on'){
- // it is probably an element, and it doesn't look like an event handler, probably not safe
- throw new Error("Invalid event name for element");
- }
- return dojo.connect.apply(dojo,arguments);
- },
- body : function() {
- return element;
- },
- byId : function(id) {
- return element.ownerDocument.getElementById(id); // use the safe document
- },
- fromJson : function(str) {
- // make sure it is safe before passing it to the unsafe dojo.fromJson
- dojox.secure.capability.validate(str,[],{});
- return dojo.fromJson(str);
- }
- };
- for (var i = 0; i < safeFunctions.length; i++) {
- safe[safeFunctions[i]] = dojo[safeFunctions[i]];
- }
- return safe;
- };
- });
|