views:

88

answers:

2

I have a WordPress plugin that loads pages with AJAX and to ensure compatibility with other plugins and "widgets."

As of right now I use the following code to evaluate all inline JS that is inside the content blocks to be updated:

  function do_JS(e){
        var Reg = '(?:<script.*?>)((\n|.)*?)(?:</script>)';
        var match    = new RegExp(Reg, 'img');
        var scripts  = e.innerHTML.match(match);
        var doc = document.write;
        document.write = function(p){ e.innerHTML = e.innerHTML.replace(scripts[s],p)};
        if(scripts) {
            for(var s = 0; s < scripts.length; s++) {
                var js = '';
                var match = new RegExp(Reg, 'im');
                js = scripts[s].match(match)[1];
                js = js.replace('<!--','');
                js = js.replace('-->','');
                eval('try{'+js+'}catch(e){}');
            }
        }
        document.write = doc;
    }

I'd like to be able to sandbox the JS a bit better so that the risk of conflicts are minimized. One idea I had was to dynamically create an <iframe> and run the JS inside of it, but I was hoping there was a bit better method to both ensure compatibility and increase security.

+2  A: 

You could try recompiling the javascript with caja: http://en.wikipedia.org/wiki/Caja_project

Joeri Sebrechts
Unfortunately, this plugin runs on hundreds of sites that I don't control at all, so I can't run JS snippets through Caja like a site like myspace. The solution needs to be redistributable.
Aaron Harun
+1  A: 

Chances are this won't give you exactly what you need, but how about wrapping your script text inside a function or self-executing function literal (function(){/*...*/})().

var strEval =  'try{';
strEval += 'widget[' + intWidgetNumber + '] = (function(){';
strEval += js;
strEval += '})();';
strEval += '}catch(e){}';

This provides more protection than straight evaluation and keeps the code in the same document. The downside is that if the code you are importing is messy about global variables (which is probably why you are asking this exact question), you could still have their code stomping on other code. And if they use the this keyword, their code likely won't work as intended. But this at least will keep properly declared variables and function declarations in an encapsulated scope.

I've worked with third-party code a lot (mostly horribly, horribly written ad code) and I've found the best solution is to keep your site code wrapped in a lengthy and unique namespace (mySiteUtils, mySiteGames, etc. or com.mysite.utils, com.mysite.games, etc.). If an ad agency decides to drop in code that matches your exact namespace they will destroy your page, but so far that's never happened.

Andrew