Codebitch : Click to return to MacEdition homepage
 

Exhausted by sniffing

September 9, 2002

Feedback Farm

Have something to say about this article? Let us know below and your post might be the Post of the Month! Please read our Official Rules and Sponsor List.

Forums

Want to dig even deeper? Post to the new MacEdition Forums!

Every so often, you encounter a Web site that is completely, utterly broken. Oh, it works in Internet Explorer for Windows, of course. Of course! But in the browser you use – be it Mozilla, Opera, iCab, OmniWeb or Internet Explorer for Mac OS – you can't get it to work. Perhaps the links don’t work, or the drop-down menus, or maybe you just get a blank page or a crashing browser.

I’m here to tell you that the problem is often not bad HTML, or broken JavaScript, or proprietary extensions to CSS. More often than not, it seems, the problem is stupid assumptions by the site designer. In an attempt to get around browser bugs or differences in browsers’ support for Web standards, they’ve put in a browser sniffer to send appropriate content to each browser. Unfortunately, not all Web authors have done this sensibly. Some make overly restrictive assumptions about their audience, and so they end up locking out anyone outside their narrow view of the browser world. Their ham-fisted attempts at sniffing out your browser are based on enumerating the browsers they’ve heard of, instead of using an exhaustive approach that accommodates browsers that they haven’t heard of or that don’t yet exist.

As you’d probably guess, I think that non-exhaustive sniffer scripts are idiotic. Non-exhaustive sniffing scripts shut out search engines (and unless you’re completely totalitarian and autocratic, I bet you don’t really want to do that). They also shut out many less common browsers like Opera, iCab, OmniWeb, not to mention users of non-standard devices like PDAs, phones, and WebTV units.

Of course, it’s not always the fault of the Web author. Many people do not write their own browser sniffer from scratch, they use somebody else’s. There’s no sense duplicating effort. Unfortunately, even scripts available from reputable sources don’t always handle unusual browsers, and in some cases they identify unusual browsers incorrectly. For example, the sniffer script suggested by About.com lists itself as being compatible with Internet Explorer and Netscape Versions 3.0 and above, for Windows and Mac. The sad thing is, the script works in Opera, iCab, Mozilla and who knows what else, it just doesn’t do much in them. It can tell if you’re using a Mac, but not much else unless you’ve set the browser to pretend to be something else. And oh yes, it will identify Netscape 6 but not Mozilla. Good one, folks.

Other sniffers do a lot better. WebReference’s offering does a pretty good job of detecting things like Opera. As would be expected from a script that’s closely related to the (outdated) one on mozilla.org, it also correctly identifies all Mozilla/Gecko-based browsers as such, including Chimera, Galeon and Netscape 6+, as well as Mozilla itself. About.com’s script doesn’t do this. Unfortunately, most sniffer scripts don’t handle Mac-specific browsers like OmniWeb or iCab very well, so Web authors with large Mac-using audiences need to take extra care if they want to use JavaScript to serve different content to different browsers.

Do it right and ELSE

I’m not suggesting you should try to work out ways to identify every browser individually. Many browsers don’t send sensible information in the identification properties like navigator.appName. Many others allow you to set them up to pretend to be something else. As regular readers would know, while I understand the rationale for browser spoofing, I also think it can be counterproductive. If your browser has different bugs to the one it is spoofing, you might find that you are being served vastly inappropriate content. And if minor browsers don’t identify themselves correctly, lazy Web developers will just assume they are dealing with two platforms, two browsers, two versions. That’s no way to get Web standards working.

No, the right way involves three things. First, don’t rely on what the browser says it is; use information about what it does. For example, don’t ask for the appName property, check for functionality. If the browser supports document.layers, that means it’s Netscape 4.x or OmniWeb. If it supports document.all, it’s a version of Internet Explorer (or iCab, as far as I can tell). If it supports GetElementById, it could be any number of browsers with good DOM support. If an iCab user is spoofing as Netscape 4, that doesn’t mean that it supports document.layers, and you’ll get ugly results if you assume that it does support it. Don’t take the browser identification properties as gospel.

Second, don’t assume that support of one property (say, getElementById) implies the support of another feature – especially if that other feature involves a whole other set of standards like CSS or XML support. This is one of the reasons that Tantek’s high-pass filter appears to fail in iCab. iCab passes the high-pass filter, but doesn’t support many of the Web standards that people might expect of a browser that passes it, like CSS1 floats, or just about anything specific to CSS2, including positioning.

Third, make sure you have a catch-all case for all the browser that you haven’t thought of or have never heard of. I really shouldn’t have to tell you this – it’s Computer Programming Concepts 101. Alas, it seems too many Web programmers haven’t thought through the basic logic. I know that big Web designers have made this very mistake, including the bright sparks who built bmwusa.com. Alerted by an email from a sharp-eyed reader, I discovered the following JavaScript code included as part of bmwusa.com’s sniffer script:

if (navigator.appVersion.indexOf("Macintosh") == -1) {
document.domain = "bmwusa.com"; }
function reStore() {if (document.layers){top.location = "http://bmwusa.com/welcome.cfm"; }}
function handleResize() {if (!document.all) { location.reload(); return true;}}

This code sends non-Mac users to bmwusa.com, instead of www.bmwusa.com. It then sets up functions that makes Netscape 4 (document.layers) and any browser that emulates it (mainly OmniWeb) reload the page. It also has a handleResize function that reloads the page if document.all is not true – that is, any browser other than IE and browsers that emulate it (mainly iCab). I’m not quite sure what they are trying to achieve, but they have succeeded in locking out Mozilla users and crashing Opera. To think people get paid for this sort of tripe. And while I’m not in the market for a BMW, especially not one in the US, I can see that this might turn off a few potential buyers.

What’s particularly sad is that they probably don’t perceive it as a problem. After all, all the traffic in their logs will be from the browsers they do support. They probably think that everyone uses IE or Netscape 4, because that’s all that can get into the site.

The problem with bmwusa.com is that they didn’t have an “everyone else” category. Their script just didn’t allow for browsers outside their narrow view of the Web. They needed a true “else” statement, just as is shown in the mozilla.org script.

KISS and markup

Having told you how to sniff the right way, I should point out that I question whether sniffing is necessary in many of the situations that it is used. Is your content really so complex that you need to sniff browsers to serve correct content? Would you be better off using a server-side sniffer instead of relying on JavaScript features to determine support for non-JavaScript features? Is the browser sniffer only there because GoLive or FrontPage or whatever package you are using puts it in by default? Are you sniffing out the different browsers only because they have different font size interpretations? Give over, the world won’t end if different browsers have subtly different linespacing or font rendering.

Sniff if you must, but it’s nicer to use a tissue, isn’t it?

— CodeBitch (codebitch@macedition.com) is the grumpy cow who does the HTML production for MacEdition. Read other articles by CodeBitch

E-mail this story to a friend

Talkback on this story!