How to make injected js execute?

J

Jon Maz

Hi,

I've got a simple bit of code that successfully injects a javascript alert
into the DOM (confirmed by View Generated Source in Firefox), yet that alert
is not executed.

QUESTION: Why doesn't it execute?
QUESTION: Can I make it execute?

<html>
<body>

<div id="myDiv"></div>

<script>
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "\<script\>alert('foo');\</script\>";
</script>

</body>
</html>

Thanks in advance,

JON
 
P

Peter Michaux

Hi,

I've got a simple bit of code that successfully injects a javascript alert
into the DOM (confirmed by View Generated Source in Firefox), yet that alert
is not executed.

QUESTION: Why doesn't it execute?
QUESTION: Can I make it execute?

<html>
<body>

<div id="myDiv"></div>

<script>
var myDiv = document.getElementById("myDiv");
myDiv.innerHTML = "\<script\>alert('foo');\</script\>";
</script>

</body>
</html>

Thanks in advance,

JON

This issue isn't as easy as it seems it should be. Randy Webb has
looked into this in great detail. There was a recent thread...

<URL:
http://groups.google.com/group/comp...t+insertion+revisited&rnum=1#9adffa2527da0f51>

Peter
 
J

Jon Maz

Hi Peter,

Thanks for that - I had no idea this would be a complex issue. A couple of
observations:

1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

.... I think only the .innerHTML one is an option for me.

2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.

My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...

Cheers,

JON
 
P

Peter Michaux

1. for (possibly demented) reasons of my own it's actually an arbitrary mix
of js and html that I want to inject into the page, so of the 5 methods
offered in the other thread:

* Change Source- attempts to change the .src property of a script element.
* Change innerHMTL - inserts a script string via innerHTML.
* createElement - uses createElement to create a script block with a .src
attribute.
* Change .text - changes the .text property of a script element.
* createTextNode - creates the text part of a script element using
createTextNode

... I think only the .innerHTML one is an option for me.

2. A lot of the thread you referred me to is about IE, whereas my observed
issue affects Firefox too.

My fingers are still crossed that there's an answer to this for me, but hope
is ebbing away fast...


I wrote a library that does what you want to do...sort of.

<URL: http://forkjavascript.org/mutate/docs>

What my script does it scan through the HTML that is about to be
inserted and pluck out all the script bits. It inserts the other HTML
and then process the JavaScript bits. Instead of dynamic script
insertion, as Randy has investigated, I just eval() the script bits.
This is more cross-browser but has scope implications.

If you are in control of writing the JavaScript bits then you can just
write the JavaScript bits so there are no problems with using eval().
There is only one little complication and it is with naming global
variables explicitly as global properties instead. Here is the
pertinent part of the above page regarding this issue.

<blockquote>
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

window.foo = 2; // instead of var foo = 2
</blockquote>

If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.

Peter
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
oglegroups.com>, Mon, 20 Aug 2007 15:55:50, Peter Michaux
If you are in control of writing the JavaScript bits then you can just
write the JavaScript bits so there are no problems with using eval().
There is only one little complication and it is with naming global
variables explicitly as global properties instead. Here is the
pertinent part of the above page regarding this issue.

Do you see any future problem in
<URL:http://www.merlyn.demon.co.uk/estrdate.htm#TT>?

One enters code in the blue bit just above heading "Testing and Timing"
(the textarea is preloaded with a function body, but Javascript does not
know that on loading, so use DEFINE & UNDEFINE), and executes it (check
the checkbox) in the next blue bit.

It's OK in IE6, FF2, Opera9 (though FF has a visible layout flaw).
 
T

Thomas M. Farrelly

<blockquote>
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

if window is the root scope ( do not remember if it is, but I recall there
beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope. This should fix your scope. In tin-tags, I do:

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply(
{ tag:THE_ACTUAL_TAG, ... }, []
) ;

Something like that, anyways. Because it's is a good thing to not effect
global scope by everything you do.

If you want to look at it, it is at tin-tags.org ( beta, FF only ) :)
window.foo = 2; // instead of var foo = 2
</blockquote>

If you are not in charge of the script bits and want to use script
insertion you could combine my library and one of the solutions posted
in the other c.l.j thread about script insertion.

Peter

cheers Thomas
 
P

Peter Michaux

<blockquote>
The main issue is the scope of entities (eg. variables or functions)
defined in the evaluated script. Because the call to eval() occurs
inside a JavaScript function, entities defined in the evaluated script
may not persist after eval() returns. If you do want to define global
entities you may look at writing something like the following snip
inside the code block.

if window is the root scope ( do not remember if it is, but I recall there
beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope.

A function's apply() will set the scope the "this" keyword when the
function runs. There is more to the script insertion problem then just
resolving "this". Here is an example where the script to be inserted
is "var foo=1;"

var foo=4;
eval( "function() {var foo=1;}" ).apply( window, [] ) ;
alert(foo);

In this case the alert says "4" but successful script insertion, as
has been defined and discussed, would result in an alert of "1". The
goal is to have the script run in the global scope completely.

Peter
 
R

Richard Cornford

Thomas said:
]
<blockquote>
The main issue is the scope of entities (eg. variables or
functions) defined in the evaluated script. Because the
call to eval() occurs inside a JavaScript function, entities
defined in the evaluated script may not persist after eval()
returns.

This statement is, of course, false. Because the eval execution context
uses the variable object from the execution context in which it is
executed any functions or variables it declares must persist after it
finishes executing. They persist for precisely as long as that Variable
object persists.
If you do want to define global entities you may look at
writing something like the following snip inside the
code block.

if window is the root scope ( do not remember if it is, but
I recall there beeing a way to reference it. ) I would write

eval( "function() {"
+ THE_CODE_FROM_THE_SCRIPT_TAG +
"}" ).apply( window, [] ) ;

to get correct scope.

I take it then that you have no idea what scope is in javascript or how
it works.

But why use - Function.prototype.apply - and create a new Array each
time to pass a zero length arguments list when you could use -
Function.prototype.call - and leave the arguments to the function call
out entirely?
This should fix your scope.
<snip>

It will not, as it does not even come close to addressing the issue.

Richard.
 
P

Peter Michaux

Thomas said:
]
<blockquote>
The main issue is the scope of entities (eg. variables or
functions) defined in the evaluated script. Because the
call to eval() occurs inside a JavaScript function, entities
defined in the evaluated script may not persist after eval()
returns.

This statement is, of course, false. Because the eval execution context
uses the variable object from the execution context in which it is
executed any functions or variables it declares must persist after it
finishes executing. They persist for precisely as long as that Variable
object persists.

I meant to write "may not persist after the function containing the
eval() returns"

Peter
 
P

Peter Michaux

Peter Michaux said the following on 8/20/2007 11:55 AM:


I have a script somewhere that lets you simply insert it via innerHTML
and then reads the script blocks back out and executes them. Is that
what yours does? (I haven't looked at it).

I extract the scripts from the HTML before inserting the HTML into the
page. That way if some browser starts to automatically evaluate
scripts when they are inserted by innerHTML I'm not screwed. There
already is one old browser out there that does this: NN6? Then after
inserting the HTML, I eval() the script bits in order. There are pros
and cons for just about every decisions in dealing with this stuff. I
find the system I built easy to use.

There is a bit more too it then that. My script takes into account
problems with inserting table rows or tbody elements by "parsing" the
html first in the appropriate surrounding element. There are
assumptions about a well formed html fragment. blah blah blah. That
script was actually a fun project.

I have yet to see a solution that handles document.write but I have an
idea in mind for it.

You are obsessed! Just curious but when is it that you are wanting to
do script insertion with totally random scripts you haven't written
yourself or written by a coworker? Just academic interest?

Peter
 
T

Thomas M. Farrelly

A function's apply() will set the scope the "this" keyword when the
function runs. There is more to the script insertion problem then just
resolving "this". Here is an example where the script to be inserted
is "var foo=1;"

Realizing that :)

[...]
 
J

Jon Maz

<quote>
You are obsessed! Just curious but when is it that you are wanting to
do script insertion with totally random scripts you haven't written
yourself or written by a coworker? Just academic interest?
</quote>

For myself I am trying to write code that asynchronously injects adverts
into a web page. You'll notice across the web millions of sites whose pages
might be quite fast-loading in themselves, but with 3 or 4 massive delays as
the page goes to ads.domain.com to fetch the ad code, which
characteristically is a mix of javascript and html, and is generated by 3rd
party software.

I want this external data injected in the background, after the main page
has finished rendering, for an improved user experience. Make sense?

JON
 
P

Peter Michaux

Hi Peter,

Currentlyhttp://forkjavascript.org/mutate/docsis down. A temporary issue?

Unfortunately it is down. I'm trying to get my hosting company to tell
me what's up. Hopefully it will be back up today.

Peter
 
P

Peter Michaux

<quote>
You are obsessed! Just curious but when is it that you are wanting to
do script insertion with totally random scripts you haven't written
yourself or written by a coworker? Just academic interest?
</quote>

For myself I am trying to write code that asynchronously injects adverts
into a web page. You'll notice across the web millions of sites whose pages
might be quite fast-loading in themselves, but with 3 or 4 massive delays as
the page goes to ads.domain.com to fetch the ad code, which
characteristically is a mix of javascript and html, and is generated by 3rd
party software.

I want this external data injected in the background, after the main page
has finished rendering, for an improved user experience. Make sense?

What about just inserting an iframe into the page and setting the src
attribute to a URL that produces the ads? Because of iframes, it isn't
a valid approach for HTML strict pages but is on HTML transitional.

Peter
 
J

Jon Maz

Hi Peter,

<quote>
What about just inserting an iframe into the page and setting the src
attribute to a URL that produces the ads? Because of iframes, it isn't
a valid approach for HTML strict pages but is on HTML transitional.
</quote>

That's probably where I'll end up. For reasons I can't remember now I
started trying to do this the .js way, and I'm stupidly determined to try to
get it to work.

Though in fact I am going for HTML strict too <sigh>.

JON
 
P

Peter Michaux

Hi Peter,

<quote>
What about just inserting an iframe into the page and setting the src
attribute to a URL that produces the ads? Because of iframes, it isn't
a valid approach for HTML strict pages but is on HTML transitional.
</quote>

That's probably where I'll end up. For reasons I can't remember now I
started trying to do this the .js way, and I'm stupidly determined to try to
get it to work.

Though in fact I am going for HTML strict too <sigh>.

I tried that for a while. Now I think HTML transitional is the only
useful doctype. For IE6 if you want to do overlays you need the
"iframe shim hack". If you want to do background file uploads that
look like XMLHttpRequest to the user then you need hidden iframes.

If you will be allowing arbitrary people to inject arbitrary HTML in
your page there is a better chance things will work out well if you
are using the more forgiving transitional doctype.

Peter
 
D

Dr J R Stockton

Tue said:
For myself I am trying to write code that asynchronously injects adverts
into a web page. You'll notice across the web millions of sites whose pages
might be quite fast-loading in themselves, but with 3 or 4 massive delays as
the page goes to ads.domain.com to fetch the ad code, which
characteristically is a mix of javascript and html, and is generated by 3rd
party software.

I want this external data injected in the background, after the main page
has finished rendering, for an improved user experience. Make sense?

No. That's only what the readers want.

Those who pay for the site want the users to have nothing better to do
while waiting for the wanted part than to read the adverts.

But I use small windows, so that the adverts tend not to show and I can
use another window while waiting for good stuff to appear.
 
P

pl

Put an IFrame on the page that has a secondary page in it that loads the
ad. It will make your life simpler and save you a lot of sleepless nights.

Agreed, use an iframe and save yourself from a "world of pain." Some
browsers will let you write the ads normally/directly into the bottom
of the html as the page loads and then move the resulting DOM nodes to
the correct location after the JS has executed. This isn't really
reliable though, particularly given that some ads do their own DOM
manipulation as they load. Whilst Firefox seems to literally move
things with appendChild, IE's implementation seems to be a bit quirky
- some rough testing indicates that it will leave some objects behind.
 
P

Peter Michaux

In comp.lang.javascript message <[email protected]
oglegroups.com>, Mon, 20 Aug 2007 15:55:50, Peter Michaux


Do you see any future problem in
<URL:http://www.merlyn.demon.co.uk/estrdate.htm#TT>?

One enters code in the blue bit just above heading "Testing and Timing"
(the textarea is preloaded with a function body, but Javascript does not
know that on loading, so use DEFINE & UNDEFINE), and executes it (check
the checkbox) in the next blue bit.

It's OK in IE6, FF2, Opera9 (though FF has a visible layout flaw).

It may have been a joke but Thomas appeared to take offense. Did you
apologize for this?

<URL: http://groups.google.com/group/comp.lang.javascript/msg/76e12383ad15a88b?dmode=source>

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top