Skip navigation.

miscoded

the web is a hack

Posts tagged with "braindead"

Most expensive javascript ever?

, , ,

I've wanted to tell this story for a while, and I don't think I'm spilling any beans or disclosing any sensitive information at this point.

So, a while ago Opera Software needed more servers. Not just a few servers either - we were planning Opera Mini's growth, implementing Opera Link, and My Opera was also growing quickly. We predicted crazy server load increases for the foreseeable future (and man, were we right!)

Clearly we needed to make a massive investment on the server capacity front (basically buying these shiny things and then some.)

Management put a hefty check on the table - I'm sure our beloved sysadmins felt like kids before Christmas - and salivating sales people from major hardware vendors grabbed our requirements spec, dived into their CRMs and crunched their spreadsheets. They emerged with offers and sample servers shipped all the way to Oslo for our testing pleasure.

However, one of the world's biggest hardware vendors - whose name every single reader will be familiar with, and whose hardware a good share of you will be using right now - apparently didn't do their homework. When Opera's sysadmin booted up the server to test its web-based administration interface, they came across a single JavaScript statement that managed to piss off everyone up to and including the CTO.

This single statement, apparently written by some sub-contractor they had outsourced admin interface programming to, cost them millions of NOK in lost sales.

And the code they sent all the way to Oslo for testing? Here's an extract:

if (is.opera)
{
window.location.href="config/error.htm";
}

'ESPN FLASH detection system' meets Flash 0

, , , ...

Even in the classy company of bad version detection scripts we've met since we started testing Opera 10, this Flash detection approach stands out. That script goes to great effort to require an update every.single.time Adobe releases another Flash version.

It starts with a bold claim to be the ESPN "Flash detection system", no less:

// Author: Danny Mavromatis
// Version: 2.07.0
// Created: 10/29/2001
// Updated: 3/6/2006
// ESPN.com FLASH detection system
var f2 = false;
var f3 = false;
var f4 = false;
var f5 = false;
var f6 = false;
var f7 = false;
var f8 = false;
var f9 = false;

Look at all those variables. What might they be used for? Read on:

var fD = navigator.plugins["Shockwave Flash" + isVersion2].description;
var fV = parseInt(fD.charAt(fD.indexOf(".") - 1));

So, first it extracts one single letter that precedes a dot in the plugin's description of itself. This is presumably the plugin's major version number, you know the 8 in "8.0", the 9 in "9.0", and, um, the 0 in "10.0". Then:
f2 = fV == 2;
f3 = fV == 3;
f4 = fV == 4;
f5 = fV == 5;
f6 = fV == 6;
f7 = fV == 7;
f8 = fV == 8;
f9 = fV == 9;


..it just sets the corresponding "f"-variable to true. If the major version was 8, f8 will be true and so on. A great way to make sure the code will require maintenance - new variables for each new version. And then comes the real gem:

for (var i = 2; i <= mV; i++) {
if (eval("f" + i) == true) aV = i;
}
// alert("version detected: " + aV);



Let's see, we just had a variable fV which contained Flash's major version number (or at least its least significant digit) - but this script has severe amnesia. What was that number again? Better use a loop and 8 eval() calls to check the value of that variable. You never know, do you?

Now, dear readers - Mr. Mavromatis clearly needs some help with this code. Obviously, complexity and maintenance requirements are among his design goals. The natural question is whether there are good, non-obvious ways this script could be improved to be more complex and require even more maintenance? Suggestions welcome in comments.

Update: Danny Mavromatis responded in comments and - though he no longer works on the ESPN site - has made sure that the page where we found this problem has been updated. Kudos to Mr. Mavromatis for his quick response and sense of responsibility. I wish more web developers would act this way!

No more personal attacks, please!

X-Talisman-Compatible: messup

, , ,

Yikes.

I'm seeing X-UA-Compatible abuse everywhere these days. It seems most of the big sites I look at have decided not to give the IE8 team half a chance to iron out their bugs, they've all simply decided to close their eyes and slap on a "behave like IE7" instruction instead. Guess if this is going to cause compat problems down the road when all non-IE browsers are forced to look at the META tags and figure out if they should be bug-compatible with IE7, 8 or 9 for any given site.. :-(

Here's a funny offender: adobe.com insists that if I'm going to show their "flashAbout_info_small.swf" animation correctly, then ..

GET /swf/software/flash/about/flashAbout_info_small.swf HTTP/1.0
Host: www.adobe.com
Referer: http://www.adobe.com/products/flash/about/

HTTP/1.1 200 OK
X-UA-Compatible: IE=7
Content-Type: application/x-shockwave-flash

Date: Sat, 21 Feb 2009 23:39:33 GMT
Content-Length: 594

... I have to render the .swf like IE7 would.

No problems, Adobe. Since I work for a browser vendor the server's wish should be my command. Here's your about Flash SWF rendered by IE in IE7 compat mode:



Beautifully compatible, no? Thanks for the X-UA-Compatible hint, I would never have figured that out on my own!

Taleo - The Leader in On Demand Unbalanced Quotes

, , ,

Load getacooljob.com in Opera, see error page (http://aac.taleo.net/servlets/CareerSection?art_ip_action=FlowDispatcher&flowTypeNo=13&pageSeq=1&art_servlet_language=en&csNo=2'%3E%3C/head%3E%3Cbody%20bgcolor=). At first sight it might look like a standard browser sniffer saying "go away and don't dare becoming our customer until you've found a browser we like"... until you look a bit closer at that address. See the junk at the end?

&csNo=2'%3E%3C/head%3E%3Cbody%20bgcolor= decodes to
&csNo=2'></head><body bgcolor=
and it's caused by the lack of a closing quote for the META tag's content attribute on the previous page:

<META HTTP-EQUIV="refresh" content="01; url='http://aac.recruitsoft.com/servlets/CareerSection?art_ip_action=FlowDispatcher&amp;flowTypeNo=13&amp;pageSeq=1&amp;art_servlet_language=en&amp;csNo=2'>


The site apparently belongs to Taleo which is the "Leader in On Demand Talent Management". As they aren't talented enough to balance their quotes or use a validator to spot markup mistakes, the level of hype obviously exceeds their technical competence..

See also statements like "this Career Section does not allow the use of the BACK or FORWARD browser buttons during the application process" (source), the hideous sniffing here
function stopEvent() {
var userAgent = window.navigator.userAgent;
var appName = window.navigator.appName;
if ((appName.indexOf("Explorer") >= 0) && (userAgent.indexOf("Mozilla/3") >= 0) && (userAgent.indexOf("Mac") >= 0)) {
return (true);
} else {
return (false);
}
}

and their "anti-multiple-tabs" JavaScript
//---------------------------------------------------------------------
// This method increments the count of browser using the career section
// on the current session in the document's cookie.
// This code is inserted only when IE browser is used
//---------------------------------------------------------------------
function setMultiBrowserDetection()
{
if (window.navigator.cookieEnabled)
{
// The multibrowser problem doesn't occur where cookies are not available
var cs_cnt = -1;
var index = document.cookie.indexOf("cs_cnt");
var countbegin = -1;
var countend = -1;
if (index == -1)
{
cs_cnt = 1;
}
else
{
countbegin = (document.cookie.indexOf("=", index) + 1);
countend = document.cookie.indexOf(";", index);
if (countend == -1)
{
countend = document.cookie.length;
cs_cnt = eval(document.cookie.substring(countbegin, countend));
}
else
{
if (countend < countbegin)
{
cs_cnt = 0;
}
else
{
cs_cnt = eval(document.cookie.substring(countbegin, countend));
}
}
if (cs_cnt < 1)
{
cs_cnt = 1;
}
else
{
cs_cnt = cs_cnt + 1;
}
}
document.cookie = "cs_cnt="+cs_cnt;
if (cs_cnt > 1)
{
// More than one browser is using the current session
window.document.location = "http://aac.taleo.net/servlets/CareerSection?art_ip_action=MultipleBrowserConflict";
}
}
}
complete with eval() instead of parseInt() (meaning that anyone who can get a cookie set on this site can XSS them).. When you stop shaking your head, I'd like you to opine on how much less talented a web site could possibly get..

How to cook tag soup with XSLT

,

Working for Opera Software's QA department gives you in-depth perspectives on the web's wild and varied coding practises. I still wasn't prepared for the curious solutions that power the menu on the new Israeli rail website.

The XSLT markup/programming language is widely used to transform one sort of DOM into another - for example turning the DOM of a generic XML file into valid XHTML. Much of the benefit is that you're working on DOM trees - making it hard or impossible to create syntactically invalid pages.

Diving into the source code shows that the JavaScript coders working on the Rail site were asleep during their education's "what's the point of XSLT" lesson. The coding is unbelievable. It's more like an XML parser/serializer stress test than a production site. Now, I don't really know XSLT and trying to debug this confirms my impression that it must be one of the worse programming languages mankind has invented - but the point of this script is to generate HTML with XSLT *string concatenation*?!?? Look at this:

<xsl:value-of select="$attribute-name"/>="<xsl:call-template name="inner-attribute-text-value"><xsl:with-param name="attribute-value" select="$attribute-value"/></xsl:call-template>"

or

<xsl:template name="inner-text-tag-open"><xsl:text disable-output-escaping="yes"><</xsl:text></xsl:template>
<xsl:template name="inner-text-element-close">
<xsl:param name="element-name"/><xsl:call-template name="inner-text-tag-open"/>/<xsl:value-of select="$element-name"/><xsl:call-template name="inner-text-tag-close"/></xsl:template>
<xsl:template name="inner-text-tag-close"><xsl:text disable-output-escaping="yes">></xsl:text></xsl:template>


Yes, all that to create a text node containing e.g.
</div>
in a DOM they will serialize only to parse it again by setting innerHTML on some poor element..

When they in their wisdom chose to generate markup inside text nodes with their XSLT they run into the familiar problem: when is < going to start a tag and when is it going to live in a text node? Hence, < is sometimes escaped as an 'lt' entity to create proper text nodes with HTML source-as-text in them (see for example the instance of
&lt;
in the code above). Now, of course when they set innerHTML they do not want this entity to appear as a literal < so they do some pre-processing: all entities they want to change into proper < and > before setting innerHTML have a comment node next to them:

<!--nwlt-->&lt;TR class="nw-2r"&gt;<!--nwgt--><!--nwlt-->&lt;TD class="nw-2c"&gt;<!--nwgt-->


and their pre-processing is a simple string replace:

sHtml = sHtml.replace(/\<!--nwlt--\>&lt;/g,"<").replace(/&gt;\<!--nwgt--\>/g,">").replace(/\<[\/]?tbody\>/gi,"");


(Why they hate the poor TBODY so much they must strip it from the markup even though the browser will re-generate them in the DOM as soon as innerHTML is parsed I can't even begin to imagine.)

If you thought XML-based toolchains and processes were going to make the Web a saner place, think again. We have now seen that in the right hands, XSLT is just another recipe for tag soup.

Rabobank trusts only Rabokeys

, , ,

The Rabobank site in the Netherlands has a peculiar problem caused by an even weirder script. The forum discussion explains what the problem is: the site's search box doesn't allow you to type the letter T!

This is caused by a keypress handling JavaScript - it's all on one line so I made a re-formatted copy. If you thought the bug was weird, wait till you try figuring out what the point of the script is..

The basic logic that causes the problem is: "any browser that supports addEventListener() will support charCode but not keyCode in the keypress event". As it happens, Opera does support addEventListener() but not charCode. The site blocks keypress events with keyCode 116 which is the correct keyCode for a "t" keypress. (If we didn't support addEventListener they would listen for keyDown events with keyCode 116 instead - which is what they basically intended to do.)

With the problem analysis out of the way: I simply don't get what this site is trying to do. They set one handler for keypress events to cancel them if it's the F5 key, and another handler for keyup events to call location.reload() if it's the F5 key!? See here:

function F5DownEventHandler(evt){
this.target=evt.target||evt.srcElement;
this.keyCode=evt.keyCode||evt.which;
this.altKey=evt.altKey;
this.ctrlKey=evt.ctrlKey;
var targtype=this.target.type;
if(this.keyCode==116&&(evt.charCode==null||evt.charCode==0)){
return cancelKey(evt,this.keyCode,this.target)
}
if(this.keyCode==13&&(this.target.id=='z01'||this.target.id=='z02'||this.target.name=='z5'||this.target.id=='ra_searchfield2'||this.target.name=='z81')){
return cancelKey(evt,this.keyCode,this.target)
}
}
function F5UpEventHandler(evt){
this.target=evt.target||evt.srcElement;
this.keyCode=evt.keyCode||evt.which;
this.altKey=evt.altKey;
this.ctrlKey=evt.ctrlKey;
var targtype=this.target.type;
if(this.keyCode==116&&(evt.charCode==null||evt.charCode==0)){
window.location.reload(this.ctrlKey)
}
if(this.keyCode==13&&(this.target.id=='z01'||this.target.id=='z02'||this.target.name=='z5'||this.target.id=='ra_searchfield2'||this.target.name=='z81')){
this.target.parentNode.parentNode.submit()
}
}


So: "we don't mind that [F5] reloads the page and [enter] submits forms as long as we re-implement the browser's functionality in JavaScript".

Or: Rabobank trusts only Rabo-programmed keys?

I guess the browser's OWN implementation of [F5] and [enter] just wasn't buggy enough. :wink:

NOSCRIPT for nerds. Stuff that disappears.

,

So, this is what a random Slashdot page looks like in Opera. That peaceful, white space in the centre sure isn't in the spirit of /. - or what? And why is there some odd overlapping box in the top left navigation area?



Sure enough, some text is missing, as re-loading with JavaScript disabled will show. The disappearing content occurs right after an ad script (URL will not unlikely die soon. Ads aren't exactly Cool URIs, but we already knew that..). Read this closely:

document.write('<script src=\"http://bs.serving-sys.com/BurstingPipe/adServer.bs?cn=rb&c=22&pli=319831&pi=0&w=336&h=280&ncu=$$http://ad.doubleclick.net/click%3Bh=v8/3682/3/0/%2a/b%3B155329471%3B0-0%3B3%3B13358361%3B255-0/0%3B24413359/24431212/1%3B%3B%7Esscs%3D%3f$$&ord=4781511\"><\/script>');document.write('\n<noscript>\n<a href=\"http://ad.doubleclick.net/click%3Bh=v8/3682/3/0/%2a/b%3B155329471%3B0-0%3B3%3B13358361%3B255-0/0%3B24413359/24431212/1%3B%3B%7Esscs%3D%3fhttp%3A//bs.serving-sys.com/BurstingPipe/BannerRedirect.asp%3FFlightID%3D319831%26Page%3D%26PluID%3D0%26Pos%3D4723\" target=\"_blank\"><img src=\"http://bs.serving-sys.com/BurstingPipe/BannerSource.asp?FlightID=319831&Page=&PluID=0&Pos=4723\" border=0 width=336 height=280></a>');


First time I saw an ad script do
document.write('<noscript><img src="..."></noscript>')
I laughed. Certainly a remarkably braindead way to include your fallback contents. But Slashdot's ads take it a step further: they use document.write to insert a NOSCRIPT tag but do not close it, hence hiding random amounts of content until the next NOSCRIPT close tag appears in the source! And it's not an Opera problem, it occurs randomly when you get the ads that come with the broken script, and happens in all browsers. In other words, Slashdot has finally proven that GUI browsers are unreliable and that everyone simply should telnet to port 80. Great news for nerds.

BestBuy, worst JS

,

Something tells me that BestBuy redesigned their home page last week and replaced the old OpenCube script with something more modern - looks exactly the same as the old menu but now it's a simple unordered list in the markup itself, hover effects provided by CSS. So far so good!

Looking around a bit, there is plenty of other code that could do with some modernising. Here's a snippet of the function handleEnterKeyPress (one of many enter-key related functions):
if(navigator.appName == "Netscape")
{
if(arguments.callee.caller.arguments[0].which == 13)

Wow, using arguments.callee.caller and the arguments property on function objects to look up the pressed key - would be more than a little cleaner to pass the event object to the function as an argument.. And the sniffing is ugly.

It seems somebody needs to learn about JavaScript's bracket syntax -
if (tabnumber==1)
{
document.tab1.src = imgServer + locale + "/images/global/misc/pdptabs/tab_prodspecs_over.gif";
}
if (tabnumber==2)
{
document.tab2.src = imgServer + locale + "/images/global/misc/pdptabs/tab_accessories_over.gif";
and the 5 other if clauses would be much nicer as document['tab'+tabnumber].src='...'.

Having good names for functions can be a good idea too:
/**
* test for https:
* return true for secure
* false for standard http
* jm 2006/10/24
*/

function getProtocol(){
var isSecure = (window.location.protocol == "https:") ? true: false;
return isSecure;
}
Source

They have one of those addEventListener/addEvent/set event handler directly kludges.. but with a twist:
/**
* takes function call 
* delays execution until full page load
* dwl 2006/09/28
*/
function addOnloadEvent(fnc){
  if ( typeof window.addEventListener != "undefined" )
    window.addEventListener( "load", fnc, false );
  else if ( typeof window.attachEvent != "undefined" ) {
    window.attachEvent( "onload", fnc );
  }
  else {
    if ( window.onload != null ) {
      var oldOnload = window.onload;
      window.onload = function ( e ) {
        oldOnload( e );
        window[fnc]();
      };
    }
    else
      window.onload = fnc;
  }
}


Is it just me, or is the window[fnc](); statement completely broken? The fnc argument to this function is supposedly a function object, not a string. So doing window[fnc] will decompile the function and look for window['function (){ ..code here.. }'] which is not likely to return anything. Somebody *still* needs to learn about JavaScript bracket notation (well, mr. dwl in this case).

Finally, looking at this scares me a bit:
function getSnum(){var WshShell=new ActiveXObject("WScript.Shell");var sName=WshShell.ExpandEnvironmentStrings("%LOCATIONNUM%");return sName;}

I don't know much ActiveX but it looks like they use it for in-store information kiosks. If you find an XSS issue in their kiosk site or can use DNS poisoning to serve some JS that shouldn't be running there it looks like you can take over the machines completely with shell scripting from your JS! Wow..