.. and the wait is over!
If you’ve not already seen this, go see it now!
You are currently browsing the archive for the Programming category.
.. and the wait is over!
If you’ve not already seen this, go see it now!

I spent the greater half of last week tearing out clumps of hair in sheer frustration over an annoying bug in Safari.
It wasn’t the kind of bug that you could really code around. I can’t get into specifics but it was to do with iFrames and javascript. The bug caused a significant problem with how the application I’m working on functions.
This was the beginning of four days of javascript hell. The end result of which is a lot of recoding and a fair amount of patching to get it sort of working. A search on the ‘net revealed that it was a known bug in Apple’s WebKit which has been fixed already in the next version which isn’t due out until the next version of OS X ships.
It transpires that this abomination of a web browser is now being inflicted on Windows users now. I can’t wait to see which bugs show up in Windows that don’t show up in OS X.
I love Apple. I really do. But Safari is a constant thorn in my side and I wish it would go away. I’d love for Apple to stop dicking around with their WebKit and use Gecko instead.
What finished me off is that I’ve had zero problems with IE 7 and my javascript code.
Safari: The Web’s Best Browser? I’ll allow my SVN commit messages tell you what I think:

This follows up from my previous entry where I found a very easy way to set HttpOnly cookies for Internet Explorer 6 (SP1+) without requiring PHP 5.2 or hand-rolling set-cookie routines.
Due to reasons too long to explain here Firefox doesn’t have support for these cookies yet. However, there is a Firefox (well, Gecko) only solution.
The solution requires you to add this simple line of javascript as near to the top of your document as you can.
HTMLDocument.prototype.__defineGetter__("cookie",function (){return null;});
This overwrites the default cookie “getter” function and simply returns “null” when document.cookie is requested.
Unfortunately, it suffers from two major problems.
Firstly, it prevents any cookies from being read by javascript. This is a problem if you have javascript set and get cookies on the fly for dynamic web applications (read Web 2.0). and more fatally it can be undone simply by using:
delete HTMLDocument.prototype.cookie.
For example, if you managed to craft a link like so:
<a href='javascript:alert(document.cookie)'>Click me!</a>
Then you’d get an alert box with “null” thanks to the overridden cookie getter - however, crafting this link:
<a href='javascript:delete HTMLDocument.prototype.cookie; alert(document.cookie)'>Click me!</a>
Then you’d get access to the document.cookie as we’ve just deleted our custom getter.
The first problem is quite easy to overcome. You can set up an array of cookies that you want to ‘hide’ then parse up document.cookie storing the cookie values into an array and simply return the value of the array key when you would otherwise request a cookie.
The second problem is a little more difficult. After toying with it for a little while, I took a rather crude approach. I simply add an onload function that examines the document’s innerHTML and just replace “HTMLDocument.prototype” with a safer version (note, you can’t convert to hex or ascii entities as Firefox runs it just the same). There are two cavaets however.
Firstly, this will only stop “passive” attacks - that is scripting in URLs and images. It won’t stop a <script>..</script> block of code as the script code is executed before the onload function is called. Secondly, as the document’s innerHTML is replaced, all subsequent javascript on the page will stop working. I don’t consider that a major stumbling block as there aren’t many legitimate cases where you’d want someone to post “HTMLDocument.prototype”. If it is a problem, then I suggest you add a line of code in your PHP script to convert this string into something safer before javascript has a chance to see it.
Of course, this isn’t an excuse to stop checking for javascript in URLs and images - but it does provide another barrier a determined hacker must overcome before accessing your cookie information. It’s also not fool proof. There are hundreds of ways to obfuscate javascript code and it’s almost impossible to catch them all. Hopefully when Firefox 2 is out of BETA it’ll support HttpOnly cookies and deprecate this rather crude solution.
Here’s the complete code.
if ( _tmp.length )
{
for( i = 0 ; i < _tmp.length ; i++ )
{
var _data = _tmp[i].split('=');
var _key = php_trim( _data[0] );
var _value = unescape( php_trim( _data[1] ) );
if ( _key && ( ! php_in_array( _key, ignore_cookies ) ) )
{
COOKIES[ _key ] = _value;
}
}
}
_tmp = null;
if ( is_moz )
{
HTMLDocument.prototype.__defineGetter__( "cookie", function () { return null; } );
window.addEventListener( 'load', function() {
var _a = document.body;
var _x = _a.innerHTML;
var _y = new RegExp( "HTMLDocument\.prototype", 'ig' );
if ( _x.match( _y ) )
{
_x = _x.replace( _y, 'HTMLDocument_prototype' );
_a.innerHTML = _x;
}
}, false );
}
/**
* Emulate PHPs trim function
*/
function php_trim( text )
{
text = text.replace(/^\s+/, '');
return text.replace(/\s+$/, '');
};
/**
* Emulate PHPs in_array function
*/
function php_in_array( needle, haystack )
{
if ( ! haystack.length )
{
return false;
}
for ( var i = 0 ; i < haystack.length ; i++)
{
if ( haystack[i] === needle )
{
return true;
}
}
return false;
};
function get_cookie( name )
{
return COOKIES[ name ];
}
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.
Recent Comments