timkokes / svgweb

Automatically exported from code.google.com/p/svgweb
0 stars 0 forks source link

var __svgHandler wrongly assigned when in deeply nested frames in IE (sorry can't test other browsers right now) #611

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.Have a page using svbWeb with an external SVG file, that is deeply nested 
(2+) in framesets and iframes
2.Load the outer most page
3.

What is the expected output? What do you see instead?
No error.
Instead I get an error one the first line of this piece of code :-

<script>var __svgHandler = 
top.document.getElementById("SVM2_2").contentWindow.svgweb.handlers["svgLogs"];
window.svgns = "http://www.w3.org/2000/svg";
window.xlinkns = "http://www.w3.org/1999/xlink";
window._timeoutIDs = [];
window._setTimeout = window.setTimeout;
window.setTimeout = 
       (function() {
          return function(f, ms) {
            var timeID = window._setTimeout(f, ms);
            window._timeoutIDs.push(timeID);
            return timeID;
          };
        })();
window._intervalIDs = [];
window._setInterval = window.setInterval;
window.setInterval = 
       (function() {
          return function(f, ms) {
            var timeID = window._setInterval(f, ms);
            window._intervalIDs.push(timeID);
            return timeID;
          };
        })();

;if (__svgHandler) __svgHandler.sandbox_eval = window.eval;</script>

In my specific instance the first line should read :-
<script>var __svgHandler = 
top.document.getElementById("listframe").contentWindow.document.getElementById("
VM2").contentWindow.document.getElementById("fChartSVM").contentWindow.document.
getElementById("SVM2_2").contentWindow.svgweb.handlers["svgLogs"];

What version of the product are you using? On what operating system,
browser, and version of Flash?
Lurker_Above r1332M
Windows XP Pro Version 2002 SP3
IE 6
Flash 10,1,102,64 

Please provide any additional information below. Reduced test cases are
always appreciated!

The following replacement function for svg.js seems to have fixed the problem 
for now

  _sandboxedScript: function(script) {
    // expose the handler as a global object at the top of the script; 
    // expose the svgns and xlinkns variables; and override the setTimeout
    // and setInterval functions for the iframe where we will execute things
    // so we can clear out all timing functions if the SVG OBJECT is later
    // removed with a call to svgweb.removeChild
    var svgwebObject = 'top.svgweb';
    if (!top.svgweb && self.frameElement) {
        var a = self;
        var i = 10;
        svgwebObject = '';
        while (a.window != top && i > 0) {
            if(!a.frameElement.id) {
                a.frameElement.id = svgweb._generateID('__svg__random__', '__iframe');
            }
//          svgwebObject = 
'document.getElementById("'+a.frameElement.id+'").contentWindow' + 
((svgwebObject != '') ? '.' : '') + svgwebObject;
            svgwebObject = 'top.document.getElementById("'+self.frameElement.id+'").contentWindow.svgweb';
            a = a.parent;
            i--;
        }
        svgwebObject = 'top.' + svgwebObject + '.svgweb';
    }
    var addToTop = 'var __svgHandler = '+svgwebObject+'.handlers["' 
                  + this._handler.id + '"];\n'
                  + 'window.svgns = "' + svgns + '";\n'
                  + 'window.xlinkns = "' + xlinkns + '";\n';

    var timeoutOverride = 
                    'window._timeoutIDs = [];\n'
                  + 'window._setTimeout = window.setTimeout;\n'
                  + 'window.setTimeout = \n'
                  + '       (function() {\n'
                  + '          return function(f, ms) {\n'
                  + '            var timeID = window._setTimeout(f, ms);\n'
                  + '            window._timeoutIDs.push(timeID);\n'
                  + '            return timeID;\n'
                  + '          };\n'
                  + '        })();\n'; 

    var intervalOverride = 
                    'window._intervalIDs = [];\n'
                  + 'window._setInterval = window.setInterval;\n'
                  + 'window.setInterval = \n'
                  + '       (function() {\n'
                  + '          return function(f, ms) {\n'
                  + '            var timeID = window._setInterval(f, ms);\n'
                  + '            window._intervalIDs.push(timeID);\n'
                  + '            return timeID;\n'
                  + '          };\n'
                  + '        })();\n';

    script = timeoutOverride + intervalOverride  + '\n\n' + script;
//    script = addToTop + timeoutOverride + intervalOverride  + '\n\n' + script;

    // change any calls to top.document or top.window, to a temporary different 
    // string to avoid collisions when we transform next
    script = script.replace(/top\.document/g, 'top.DOCUMENT');
    script = script.replace(/top\.window/g, 'top.WINDOW');
    addToTop = addToTop.replace(/top\.document/g, 'top.DOCUMENT');
    addToTop = addToTop.replace(/top\.window/g, 'top.WINDOW');

    // intercept any calls to 'document.' or 'window.' inside of a string;
    // transform to this to a different temporary token so we can handle
    // it differently (i.e. we will put backslashes around certain portions:
    // top.svgweb.handlers[\"svg2\"].document for example)

    // change any calls to the document object to point to our Flash Handler
    // instead; avoid variable names that have the word document in them,
    // and pick up document* used with different endings
    script = script.replace(/(^|[^A-Za-z0-9_])document(\.|'|"|\,| |\))/g, 
                            '$1__svgHandler.document$2');
    script = addToTop + script;

    // change some calls to the window object to point to our fake window
    // object instead
    script = script.replace(/window\.(location|addEventListener|onload|frameElement)/g, 
                            '__svgHandler.window.$1');

    // change back any of our top.document or top.window calls to be
    // their original lower case (we uppercased them earlier so that we
    // wouldn't incorrectly transform them)
    script = script.replace(/top\.DOCUMENT/g, 'top.document');
    script = script.replace(/top\.WINDOW/g, 'top.window');

    return script;
  },

Many thanks for an excellent piece of work, I look forward to working with it 
as it develops and matures.
Jeremy

Original issue reported on code.google.com by goo...@jeremy42.co.uk on 7 Apr 2011 at 10:35

GoogleCodeExporter commented 9 years ago
Oops copied the wrong version of the fix sorry.

I posted
...
        svgwebObject = '';
        while (a.window != top && i > 0) {
            if(!a.frameElement.id) {
                a.frameElement.id = svgweb._generateID('__svg__random__', '__iframe');
            }
//          svgwebObject = 
'document.getElementById("'+a.frameElement.id+'").contentWindow' + 
((svgwebObject != '') ? '.' : '') + svgwebObject;
            svgwebObject = 'top.document.getElementById("'+self.frameElement.id+'").contentWindow.svgweb';
            a = a.parent;
            i--;
        }
        svgwebObject = 'top.' + svgwebObject + '.svgweb';
...

it should read

...
        svgwebObject = '';
        while (a.window != top && i > 0) {
            if(!a.frameElement.id) {
                a.frameElement.id = svgweb._generateID('__svg__random__', '__iframe');
            }
            svgwebObject = 'document.getElementById("'+a.frameElement.id+'").contentWindow' + ((svgwebObject != '') ? '.' : '') + svgwebObject;
//          svgwebObject = 
'top.document.getElementById("'+self.frameElement.id+'").contentWindow.svgweb';
            a = a.parent;
            i--;
        }
        svgwebObject = 'top.' + svgwebObject + '.svgweb';
...

Really sorry

Original comment by goo...@jeremy42.co.uk on 7 Apr 2011 at 10:40

GoogleCodeExporter commented 9 years ago
'top' should perhaps be replaced with 'parent'

Original comment by joao.ei...@gmail.com on 2 Jun 2011 at 11:41