Hacking CSS

I’m having a quieter-than-usual week at work this week (which is just as well considering that I spent 90 minutes of today with no internet connection thanks to a ghost in my machine/router..). So it was a bit of a shock to the system to have to swing into action mid-afternoon to tackle a bug that was crashing IE6 when it attempted to load a previously-tested-and-working web page that was supposed to go live the very next day.

My first thought was that maybe an automatic Windows Update had somehow adversely affected my install of IE6. That’s not usually my first thought, but for a previously tested and working HTML page to suddenly start crashing all by itself? Nup, no way was it my CSS. To be honest it was just as unlikely that it was a Windows Update that was at fault either, but it was worth a shot.

So I went into my XP Control Panel (“Add or Remove Programs”) and Googled the last couple of Windows updates.

Security Update for Windows XP (KB937143), installed on 15/08/2007 turned up some worrying info – apparently some guy in Germany had noticed that IE6 had started to crash “while accessing at least one site”, after installing the GDR version of the update. Maybe I was on the right track?

After a bit more Googling, I arrived at the MS support page for MS07-045: Cumulative Security Update for Internet Explorer.

Completely missing the ‘IT professionals‘ link at the top of the page (maybe that says something) and finding nothing useful anywhere else, I ended up Googling the update name and got to a page about Microsoft IE Crafted CSS Unspecified Memory Corruption, which told me of
“a flaw that may allow a malicious user to gain the same user rights as the logged in user. The issue is triggered when IE parses certain strings in CSS. It is possible for a malacious person to construct a specially crafted website which could remotely execute code on the visitor’s computer.”

I wondered who these ‘malacious’ people were? And why didn’t they just stick to the accepted label of ‘malicious’? Clearly they were social outcasts, determined to make my life harder by forcing me to rewrite my CSS so that it didn’t look like it was attempting to trick people into giving up their Facebook passwords.

A bit more Googling and a bit more info from this page which explained that “The specific vulnerability exists due to improper parsing of HTML CSS ‘float’ properties. By ordering specially crafted ‘div’ tags in a web page, memory corruption can occur leading to remote code execution.”

To cut a long story short, the page in question was debugged after I followed up the notion of improperly parsed ‘float’ properties and ended up at an old post on Eric Meyer’s site. This kicked my brain into revisiting the CSS, and after some playing around, I resolved the issue by adding a couple of lines of otherwise unnecessary CSS, to prevent a floated list from bringing the house down in IE6.

I still don’t know whether Microsoft or KB937143 were at fault, or whether the bug was always there and just waiting for the slightest encouragement, but the afternoon’s debugging has made me feel that much less secure about developing CSS for Internet Explorer.

But, you’re BLIND…

As a conscientious web developer, I build web pages that endeavour to be accessible to as wide a range people as possible.

Inevitably, this means that every now and then I have to pull a project manager, client, or designer up on inaccessible content or a poorly thought out design.

So, I might say things like, “is there an HTML alternative to this Flash content?” or, “the Web Guidelines Web Standards* say that you can’t use colour alone as an indicator of x (*the Web Guidelines Web Standards are great for enforcing personal beliefs and they’re pretty much the main reason why I code the way I do today).

It never ceases to amaze me that nine times out of ten their default response is something along the lines of ‘But blind people can’t do that’.

It’s not even a question (‘But blind people can’t do that, can they?’), it’s just an automatic statement – one that the speaker feels totally justified in sharing with the world.

Because ‘blind people can’t do that’, there is thus no need to implement my suggestion, and another piece of partially (or totally) inaccessible content joins its friends in the matrix.

The thing that bugs me, is that we’re supposed to be living in some kind of über information age. Why then, are otherwise well-meaning people, with the power to make a difference in the lives of others, so ignorant of the needs of their fellow citizens?

In the case of today’s ‘stand-off’, a couple of quick and fruitful visits to Google gave me the virtual ammo I needed to prove that ‘yes’, blind people could indeed partake in the activity in question. Armed with this I managed to bug the project manager in question enough that he bugged the client in question into finally accepting my recommendation (smile). So, all’s well that ends well, this time..

EXTREME Animation

Checking my Gmail inbox this afternoon, I noticed one of those newsletters for an airline whose air miles scheme I don’t actually belong to, but that I signed up for in expectation, last time I went somewhere exciting..

They had a feature on India, and because my partner rates India I thought I’d check it out. Well whatever else I found faded into nothingness when I discovered this gem of a webpage, for the

.o:O:o. Delhi Tourism and Transportation Development Corporation .o:O:o.

Yes, those wonderful circles were already in the page title (I wonder how they help their Google ranking?) Now, we all know that most clients like a bit of animation and movement on their otherwise corporate homepage, but come ON, isn’t seven counts going a bit far? Or does the average Indian web surfer have an even shorter attention span than that of his over stimulated Western counterpart?

If it ain’t broke…

Or, “The eighteen steps of stupidity.”

You know what they say about fixing things that ain’t broke?

Well, I spent most of today chasing an elusive Safari 2 bug (I thought it was a bug anyway). My text resizer tool setup scripts were failing and taking the rest of my onload scripts with them. It was the final day of testing and I really wasn’t happy to have an otherwise compatible site breaking in such a common browser.

Of course, my install of Safari 2 was the default version that came with OSX 10.4. I’d recently had to reinstall OSX, as the previous install was doing some funky things which I didn’t like, such as randomly resetting the password used to access the login account every now and then.

So Step 1 was to try my page out in some slightly newer versions of Safari. I downloaded Michel Fortin’s self contained versions of Safari 2.02, 2.03 and 2.04 from his Multi-Safari page, and loaded ‘em up .. but was still having issues. Plus, I couldn’t launch 2.04 because my version of OSX was too old.

By a stroke of luck, the Mac’s updater box burst into life, informing me that there was an OS upgrade available. I upgraded from 10.4 to 10.4.10 (Step 2), and after a restart Safari 2.04 launched fine. But, I was still having issues.

After a bit of cursing, I headed on over to Apple’s site to download the beta of Safari 3. Interestingly this is now also available for Windows, but, as someone wise commented: “Do we really need another browser [for Windows]?”

I know the answer to that question, and if you don’t then I’d suggest that you head on down to evolt.org and check out the plethora of browser wannabes sometime.

Now, hate is such a strong word, so I’ll simply say that I dislike beta browser releases, just as I dislike the people who download beta browser releases and then visit sites that I build and expect them to work flawlessly in their version x beta browser release. If it has the tag ‘beta‘ officially appended to its title, then that should tell us that it’s not a final release, and it’s probably in beta for a reason.

But, I was stuck – if it was a version issue, and my code was going to work in a newer version, there was only one way to find out. So I did the deed, and after a restart, and with Safari 3 beta installed, I was still having the same trouble.

Now, to be honest, at this point, I really didn’t have any idea what was going on, so Step 3 was to enlist the help of Safari’s helpfully hidden Javascript debugger tool, the ‘Debug’ menu. Thanks Apple.

Once I got that up and running, I knew right away what the problem was. It was a case of the ol’ DOM Exception 8. Hang on. The what? I turned to Google for help (Step 4), but all Google gave me was links to forum posts containing knowledgeable comments like: “..a wonderfully usless error message..” and “..try not to raise DOM Exception 8, whatever the f**k that is.”

Having nearly exhausted all three pages of results for the (exact) search phrase “dom exception 8″ I finally found a link to blech’s del.icio.us ‘error’ bookmark (Step 5) for Webkist (Step 6), only that link was broken, so back to Google (Step 7), then via the ErrorZilla add-on (Steps 8 and 9), and shortly thereafter to the wayback machine (Step 10).

As a side note, I love it how the current AJAX craze hit NZ in 2006/2007 but this old, deleted, forgotten post, was from way back in ’05…

Anyway, after congratulating myself on my small search victory, I quickly realised that the Webkist post, while helpful, really wasn’t all that helpful as it wasn’t actually the same issue as I was having after all. But, it was a lead of sorts.

And then, at some point, a light went on and I discovered that Safari’s ‘DOM Exception 8′ was one and the same thing as Firefox’s Node was not found” code: “8 (Step 11). Given the importance of this discovery it’s a real shame that I can’t actually remember exactly where I got this from. Perhaps my brain started working at this point, but it’s unlikely. Anyway, although it seemed like the-key-to-everything at the time, it later eventuated that it was actually the-key-to-nothing. Well, not quite, but read on for more stupidity..

So, armed with my newfound knowledge, I set up a local test page (Step 12), to test appendChild() and removeChild(). My theory was that my text resizer node couldn’t be removed because I was trying to remove it from its DOM grandparent rather than its immediate parent {insert wisecrack about grandparents and grandkids..}.

My grandparent vs parent tests worked as I had hoped, and I validated my findings after reading this helpful post here which lead me to the relevant docs here and here (Steps 13, 14, and 15). In due course I resolved the bug by using removeChild() to remove my text resizer element from its immediate parent, div#tools (Step 16).

And then I realised.. that my removeChild() issue was just a red herring. Lo and behold, the script proceeded to fail at line 146. Woo hoo.

Line 146 was the cookie test. Now, in the past I have had problems with this particular cookie script, in particular it has appeared to fail in my Safari and IE5 test browsers, and I often wondered if the reason was that said test browsers were perhaps somehow somewhat less than fully functional. But this time I looked to the code for salvation.

Now, I didn’t write the particular cookie script in question, rather I did what any good developer worth his salt would do – I ripped it off Quirksmode. Unlike me, the author of Quirksmode, ‘PPK’, is a proper Javascript developer, and he capably writes his own scripts from the ground up, rather than chopping together others’ snippets with snippets of his own. On the other hand, like me, PPK likes to test very throughly. And I respect a man that takes the time to test his assumptions. Believe me, not everyone does..

I doubted very much that the trustworthy PPK was to blame. And so, in Step 17, I compared PPK’s scripts with my own scripts, aka PPK’s scripts. Now, even though I am an evil guy, in that I take more scripts than I make for others to take, I still like to understand how the scripts I am taking actually work. And, once these scripts are integrated into my scripts, I like them to look the same, ie they have the same formatting, the same style of commenting, etc. This way everything is readable, or not, depending on whether you like a(n) (un)healthy amount of white space in your javascript, like me, or not.

So, back to Step 17, and comparing the code. At a glance everything seemed in order. But, I did notice a little extra whitespace in my cookie script, aka PPK’s reformatted cookie script. Surely this could not be the culprit?

I removed the whitespace, and uploaded the script to test in Safari, (Step 18).

Problem solved, Safari happy, Dan happy, Project Manager probably happy, and I’m pretty sure this will resolve my IE5 cookie issues too.

Lesson learned.

CSS: Position

It’s true, I *am* a mental patient =P. For some unknown reason my lobotomised brain thought that once you set position:relative; on an element you couldn’t override it. Overuse of position:relative can create tricky aneurysm-causing IE5 and 6 bugs, but now, thanks to my new found knowledge (courtesy of css-discuss and w3 schools) that in fact position actually has a possible, nay default value of ‘static’, I can finally override position:relative when I need to :)

View source

I often use View Source in Firefox to view the page source after all Javascripts have run: CONTROL+A → Right-Click → View Selection Source.

As I work remotely and my two testing computers aren’t set up to do the VPN connection, I often use this technique to save out a copy of a page for viewing and debugging in IE7 and Safari.

Something to be aware of is that this generated source omits the page Doctype, which can mean funky rendering in IE7. Replacing the Doctype after pasting the generated code fixes this problem and creates one less diversion when developing cross-browser scripting and styling.

Update 11.08.2007: It also looks like source code viewed in this way is also converted to HTML markup, regardless or whether it was authored as XHTML or not.