So I had a fun hour this morning.
If you’re unaware, any javascript that’s returned via ajax (XMLHttpRequest) which is embedded in the returned text isn’t executed which is a bit of a problem.
To ‘fix’ this, I wrote a little function in the ajax class that takes the returned text, finds any javascript blocks and eval()s them. The problem is the regex. My first instinct was to write this:
source_code.match( new RegExp( “<script\\s+?type=['\"]text/javascript['\"]>(.+?)</script>”, “i” ) )
However that didn’t work. After some tweaking it seemed that ( .+?) wasn’t matching across newlines. A quick search on the internet informed that RegExp’s dot character doesn’t match across newlines and I should use ([^]+?) instead ([^] being match every character except (none)).
I made the changes and everything snapped into place, so I figured I’d quickly blog about it so that I won’t forget in the future.


15 comments
Comments feed for this article
August 3, 2006 at 3:32 pm
Peter Goodman
In the past I’ve had problems with the eval. For me, it worked on all modern browsers, where IE was the problem. Are you having any of these problems?
August 3, 2006 at 3:33 pm
Peter Goodman
I commented but I don’t see it. Do you have comment moderation on? (if so, delete this)
August 3, 2006 at 7:11 pm
Don Wilson
Very nice move. I did the exact same method with template files and conditional blocks.
August 4, 2006 at 12:15 am
Sinan Gürbüzer
Hi,
This is not a spam, but sorry for the attention! I have friends for transleting to turkish, kurdish, nederlandish and also what you need. Maybe to chinesish?
Mahir Semsur
My future firm: Ecologic Anarchos Media Managements
I’m a Kurdish Online Learn Faculty Foundation Planner
I Have Php, Html, Flash, Mysql, many Web Applications also allround Broadcaster (kamera, sound, editing, visual effects, 2D and 3D Graphicer), but have not enough money to life. I have a girlfriend that has epilepsy. In otherwise say the people also for this: falling sickness. She has hepatit B and I not. We smoke to much to kill we self, and make hopes for a better life. Some have this not, I hope for everyone for that chance. If you have to much and find a good aid organisation and help them. But not to much; because you must also have a good life… Thanks for your time,
Best Regards
August 4, 2006 at 6:14 am
Kennedy
lol… I wouldn’t want him translating anything of mine
.
August 4, 2006 at 8:25 pm
Philip Withnall
I don’t know if it’s the same in JS, but there’s a regexp modifier to match across newlines.
I can’t quite remember which one it is, but looking briefly at some of my code tells me it’s either “s” or “m”.
August 4, 2006 at 11:58 pm
James
I hate regular expressions, they’re just so messy and easy to break
August 5, 2006 at 12:04 am
Peter
Philip,
You are correct, there is a multiline modifier which is “m”
Not sure if my other comment got through, I keep getting an error “No entry_id”.
August 5, 2006 at 12:25 pm
Chris Boulton
Peter/Matt:
The “s” modifier will treat the string as a single line and thus matches new line characters when using “.” too.
August 5, 2006 at 10:36 pm
Matt Tavares
one word, prototype (http://prototype.conio.net/)
August 6, 2006 at 12:42 am
Jack Chapple
Prototype is for cheating script kiddies
August 7, 2006 at 12:13 pm
Le Phantom
My initial thought: NO! PLEASE DON’T DO THAT!
Because even though your focus is on the javascript regexp,
I can’t but notice that you’re XHR-ing a document with a
script tag, and parse it to extract and execute the javascript.
I’m using your forum software for a (pretty big gaming) hobby
site, but I’m also doing (core) quality assurance for a browser
company, and one of my responsibilities is javascript.
And so my second thought was: NO! PLEASE DON’T DO THAT!
- If you want to **load pages** into your webpage, use iframes.
- If you want to include scripts, then include the script.
I can’t really see any good use cases where you’d want to XHR
a document, and have it’s javascript execute. XHR is for loading
new data, not new business logic.
And was it Rasmus that said about php “when eval() is the answer,
you’re asking the wrong question”? Anyway, it pretty much holds
for javascript as well.
If you load a page from your own server, then you should be able
to split the data into nicely separated entities, and serve them
to your XHR script using xml (and CDATA).
If you’re loading a page from a server you’r not controlling, you’re
open wide to a wide range of XSS attacks, which is really, really bad.
*** Slightly off topic ***
And come to think of it, that’s just as bad as allowing html, xml and
css uploads to IPB by default. You really should not! Most forum admins
have noe idea what XSS is, and will not think of disabling html attachments.
But allowing them is that same as giving any user with upload rights the
ability to highjack any other users’ accounts, by having them viewing the
attachment.
It’s also good practice to store your uploads on a different domain than
the one serving the content. Luckily IPB supports that with it’s “Upload URL”
setting. But again, most people don’t know anything about XSS, and why
they should do this. And most people don’t have full control of multiple domains
to play around with either. So uploading anything that is executed by the
browser, that may contain javascript, is a bad thing to have as an “opt out”.
It should be an “opt in”.
This should also have been properly explained in ACP by my taste.
*** Back on topic ***
Anyway, if you really want to load scripts using XHR, and eval them,
the least thing you should do, is to serve them as XML, so you don’t
need to parse the document for script tags.
This is a small example of how to import a script during runtime:
test.html:
<!DOCTYPE html>
<html>
<head>
<script type=”text/javascript”>
document.onload = function() {
var s = document.createElement(’script’);
s.setAttribute(‘type’,'text/javascript’);
s.setAttribute(’src’, ’imported.js’);
document.body.appendChild(s);
helloWorld();
}
</script>
</head>
<body>
</body>
</html>
imported.js:
/* Run automatically at import: */
(function() {
var div = document.createElement(‘div’);
div.appendChild(document.createTextNode(‘External javascript imported.’));
document.body.appendChild(div);
})()
/* Run when called: */
function helloWorld() {
var div = document.createElement(‘div’);
div.appendChild(document.createTextNode(‘Function in imported javascript ran.’));
document.body.appendChild(div);
}
The script “imported.js” could of course be dynamically generated based
on a query string, so you could use just one javascript serving script
to generate all your “run time imported” javascript code.
Wow, this became much longer than anticipated. Oh well, hard drives and bandwidth are cheap these days
August 8, 2006 at 10:32 pm
Rikki
Le Phantom,
If I remember correctly, IE will not execute a script that is ‘imported’ by using the DOM to create it
August 19, 2006 at 9:28 pm
a
Post something new, for once…
August 23, 2006 at 9:57 am
Matt
Er. Ok.