Duncan’s blog

March 25, 2009

Custom 404 page with ColdFusion and IIS

Filed under: Coldfusion — duncan @ 8:51 pm
Tags: , , , , , ,

This is one of those techniques that I’ve been using for years, and only just discovered a simple mistake in it. However, I think this mistake might be quite common, so decided to blog about it.

If you’re using ColdFusion and IIS as the webserver, you can either use IIS’s default page for handling 404 (page not found) errors (and any other error type). Or you can specify a page of your own. By specifying your own page it makes it easy for you to have a 404 page that matches the design and functionality of your website.

To do this is simple. In IIS, go to the Properties screen for your website. Go to the Custom Errors tab. There you will see a list of all different types of errors you might generate. Scroll down the list until you find the 404 error.
Custom Errors tab in IIS
Select it and click Edit. Change the type to URL, then put in the relative path to your own 404 page.

Simple, right? You’ll see the above method in many ColdFusion articles, and I’ve done it like this for years. However, there’s one vital step being missed out. I only discovered this when trying to register my site for Google Webmaster Tools. You have to verify your site by uploading an HTML file or adding a custom meta tag to an existing page. However it seems the Google bot also checks your 404 page at the same time. I got the following error message:
We’ve detected that your 404 (file not found) error page returns a status of 200 (Success) in the header.

?! To check this, I went to mysite.com/blah, then using the Web Developer Toolbar in Firefox, checked View Response Headers. Which gave me the following information:

Connection: close
Date: Wed, 25 Mar 2009 20:41:55 GMT
Server: Microsoft-IIS/6.0
Content-Type: text/html
Page-Completion-Status: Normal, Normal

200 OK

Oops, that should say 404 not 200! It doesn’t take much to fix it. At the very top of the custom 404 page (before any <doctype> or <html> tag) just add in:

<cfheader statusCode="404" statusText="Not Found">

Checking the Response Header Information again following that change then correctly returns:

Connection: close
Date: Wed, 25 Mar 2009 20:41:30 GMT
Server: Microsoft-IIS/6.0
Content-Type: text/html
Page-Completion-Status: Normal, Normal

404 Not Found

and Google then successfully verifies the website.

March 22, 2009

We’re intimidating benefit ‘thieves’, with graffiti

We're closing in on benefit thieves

I saw the above recently on Broughton Street in Edinburgh. This is known as “clean graffiti” or “reverse graffiti”, and involves using a power washer to clean off grime and dirt, leaving behind clean patches that reveal some graffiti. In this case, a stencil would have been used. The main proponent of this form of graffiti in the UK is Paul Curtis, aka Moose, and his commercial clients include Big Brother, Xbox, the Metropolitan Police and Greenpeace.

The example above is also one of his designs, and is part of a campaign against benefit cheats by the Department of Work and Pensions (DWP).

It’s quite controversial for two reasons:

  1. It’s using a form of graffiti, which is always going to attract criticism from certain sectors, despite in this case actually cleaning away dirt rather than using paint
  2. It’s directly targeting groups of people, in the places they live, work and shop.

There was an article in the Scotsman last October complaining that this campaign was wrongly targeting residential property in Inverleith. Apparently the DWP had pre-agreed all sites with the council, and none should have been outside residential property.

After I saw this one on Broughton Street, quite clearly in front of the entrance to some flats, I put in a Freedom of Information request through the WhatDoTheyKnow.com site, to find out what other sites in Edinburgh had been hit by this campaign.

The Scotsman article quotes a DWP spokeswoman stating that 30 sites were agreed, but the response from Edinburgh City Council confirms it was really 36.

  1. Waverley Steps – Waverley Station
  2. Waverley Steps – Princes Mall
  3. North Bridge / Waterloo Place – Waverley Gate Building -
  4. Broughton Street – Baroque Bar
  5. Broughton Street – Real Food Store
  6. Broughton Street – Ladbrokes
  7. Broughton Street – Chip Shop
  8. Broughton Lane – Mathers Bar
  9. Eyre Place – Pavement near Esso Station
  10. Inverleith Row – Bookmakers
  11. Inverleith Row – Goldenacre Mini Market
  12. Inverleith Row – Victoria Wine
  13. Ferry Road / Pilton Drive – Morrisons Supermarket
  14. Dalry Road – Lidl Car Park
  15. Haymarket Station – Outside Starbucks
  16. Clifton Terrace – Outside Social Security Office
  17. Richmond Terrace – Dalry Road – next to many charity shops
  18. Caledonian Road / Dalry Road – Apple Pharmacy
  19. West Tollcross – Ignite Club
  20. West Tollcross – Wall outside of Ignite
  21. Dundee Terrace – outside newsagent and post office
  22. Dundee Street – Fountain Park Cinema Complex
  23. Gorgie Road – Opposite Station Tavern under rail bridge
  24. Gorgie Road – William Hill
  25. Stewart Terrace / Gorgie Road – Blockbuster Video
  26. Tynecastle – Heart of Midlothian Football Stadium
  27. Montague Street – The Malthurst Pub
  28. Clerk Street / Rankeillor Street – Chapman Chemist
  29. Rankeillor Street – Thresher Wine
  30. George IV Bridge – Pizza Shop
  31. Merchant Street – Under the Stairs Bar
  32. Cowgate – Three Sisters
  33. Tron Square
  34. Blair Street – City Café
  35. South Bridge – Flight Centre
  36. Stairs from South Bridge to train station – past the Scotsman Newspaper building

The photo above must be the Broughton Street – Real Food Store site; Real Foods is next door to number 35. How many of the other locations also target private residential properties? The council has since removed the DWP adverts at the Goldenacre Mini Market on Inverleith Row and the Malthurst Pub on Montague Street, but how many still remain visible, wrongly intimidating law-abiding residents?

March 20, 2009

2009 goal review – spring equinox

Filed under: Uncategorized — duncan @ 12:00 am
Tags: ,

At the start of the year I published my goals for 2009. Rather than just treat it like a new year’s resolution and ignore it until the following year, I decided to review those goals quarterly.

Complete 25 of the Project Euler problems.
I decided to start using Python to tackle some of these, and managed to get a few more done, taking my total to 33. Haven’t done anything on this for a while. The next Project Euler milestone is when you complete 50. I’m not sure I’ll manage that, but maybe I’ll revise this goal to try and complete 40.

Get a Master ranking in Experts Exchange for at least one other zone.
I’ve now got Master ranking in Coldfusion Markup Language, ColdFusion Application Server and ColdFusion Studio. I’m almost at the ‘Guru’ level for the Coldfusion Markup Language.
New goal: get one more Master ranking, and improve both Coldfusion Markup Language and ColdFusion Application Server to Guru level.

Join the gym.
No progress.

Blog at least once a week on average. I’d also like to do more Coldfusion-related blog posts.
I’ve made 36 posts this year, five of which are about ColdFusion.

Get involved in something open source.
I submitted a few minor issues to a handful of projects on RIAForge.org, and submitted a suggestion for the VarScoper tool to its author.

Start using some kind of source control.
No progress.

Install and start using Railo.
No progress.

Start using MySQL.
No progress.

March 16, 2009

The importance of var scoping – part 2

Filed under: Coldfusion — duncan @ 12:02 am
Tags: , , , ,

As a follow-up to my previous article on var scoping, I wanted to give another example.

Someone once mentioned to me that he knew you had to var scope, but he didn’t think it applied to queries. Here’s an example to disprove that.

I’m using the same information as before (a selection of actual dishes from the Fat Duck’s tasting menu), but this time instead of storing the data in an array, I’m using a query. I then loop through the query, and call a function at each iteration, to find out the scores given to each meal by Alice, Bob and Eve.

<cfset getData = QueryNew("ID,Name")>
<cfset QueryAddRow(getData, 5)>

<cfset QuerySetCell(getData, "ID", 1, 1)>
<cfset QuerySetCell(getData, "Name", "nitro-green tea and lime mousse", 1)>

<cfset QuerySetCell(getData, "ID", 2, 2)>
<cfset QuerySetCell(getData, "Name", "snail porridge", 2)>

<cfset QuerySetCell(getData, "ID", 3, 3)>
<cfset QuerySetCell(getData, "Name", "roast foie gras ""benzaldehyde""", 3)>

<cfset QuerySetCell(getData, "ID", 4, 4)>
<cfset QuerySetCell(getData, "Name", "salmon poached in liquorice gel", 4)>

<cfset QuerySetCell(getData, "ID", 5, 5)>
<cfset QuerySetCell(getData, "Name", "nitro-scrambled egg and bacon ice cream", 5)>

<cfoutput query="getData">
	#getData.CurrentRow# of #getData.RecordCount#. #getData.Name#, 

	<cfset rating = getRating(getData.ID)>

	#rating#<br>
</cfoutput>

<cffunction name="getRating">
	<cfargument name="rating" required="yes" type="numeric">

	<cfset var score = 0>

	<cfset getData = QueryNew("ID,Name,Score")>
	<cfset QueryAddRow(getData, 3)>

	<cfset QuerySetCell(getData, "ID", 100, 1)>
	<cfset QuerySetCell(getData, "Name", "Alice", 1)>
	<cfset QuerySetCell(getData, "Score", RandRange(1,10), 1)>

	<cfset QuerySetCell(getData, "ID", 200, 2)>
	<cfset QuerySetCell(getData, "Name", "Bob", 2)>
	<cfset QuerySetCell(getData, "Score", RandRange(1,10), 2)>

	<cfset QuerySetCell(getData, "ID", 300, 3)>
	<cfset QuerySetCell(getData, "Name", "Eve", 3)>
	<cfset QuerySetCell(getData, "Score", RandRange(1,10), 3)>

	<cfloop query="getData">
		<cfset score = score + getData.Score>
	</cfloop>

	<cfreturn score>
</cffunction>

What I expect to see is:
1 of 5. nitro-green tea and lime mousse, 12
2 of 5. snail porridge, 14
3 of 5. roast foie gras “benzaldehyde”, 17
4 of 5. salmon poached in liquorice gel, 15
5 of 5. nitro-scrambled egg and bacon ice cream, 12

What I actually get is:
1 of 5. nitro-green tea and lime mousse, 10
1 of 3. Alice, 19
1 of 3. Alice, 23
1 of 3. Alice, 14
1 of 3. Alice, 11

So what’s going on? The problem comes from the fact that I’ve used a query of the same name in my function as in my .cfm page, and critically, that I haven’t var-scoped it.

So the first time through the loop, my page correctly outputs the record count as 5, and the name of the first dish from the query. Then, as soon as it executes the getRating function, the original query is essentially lost once we say:

<cfset getData = QueryNew("ID,Name,Score")>

Somewhere in ColdFusion’s internal workings it knows it has to loop 5 times. But it no longer retains any memory of what the original query was, and ends up outputting the first row of the new query each time.

All we have to do to fix this is change the above line to:

<cfset var getData = QueryNew("ID,Name,Score")>

This also applies to anything else that can return a query object, such as CFDirectory and CFHTTP.

Incidentally, if the query inside the cffunction didn’t have columns that were referenced in the calling page, an error would be thrown. e.g. if I only did:

<cfset getData = QueryNew("Name,Score")>

then I’d get the following error on the second iteration of the loop:
Element ID is undefined in GETDATA.

March 15, 2009

Just watched the Watchmen

Filed under: Film — duncan @ 8:05 pm
Tags: ,

Watchmen

Saw the Watchmen yesterday. Much better than I expected. I had warm fuzzy feelings for most of it. It’s very faithful to the comic book, almost all the shots and dialogue are from the comic. Different ending, but it works. A few minor scene changes here and there that don’t detract either.

I’m not sure how much I’d have appreciated it if I hadn’t read the comic book. Probably too many characters to take in. If you haven’t seen the film yet, I’d recommend you read the book first. Then read it again!

Looking forward to the Tales of the Black Freighter animation too.

My favourite film of 2009 so far. Best book adaptation I’ve seen since Lord of the Rings.


“Watchmen by Dane Rot” picture from piH9’s Flickr stream. Creative Commons license.

March 12, 2009

The importance of var scoping

Filed under: Coldfusion — duncan @ 9:33 pm
Tags: , , ,

As I mentioned in my Introduction to ColdFusion Components, var scoping is essential. This applies not just to CFCs, but to any functions in your CFML.

Let’s illustrate why…

Just for fun, I’m constructing an array with some ‘interesting’ entries from the menu of Heston Blumenthal’s Fat Duck restaurant*. Then I have a function that works out some random scores for each item.

<cfset food = ArrayNew(1)>

<cfset food[1] = "nitro-green tea and lime mousse">
<cfset food[2] = "snail porridge">
<cfset food[3] = "roast foie gras ""benzaldehyde""">
<cfset food[4] = "salmon poached in liquorice gel">
<cfset food[5] = "nitro-scrambled egg and bacon ice cream">

<cfloop index="i" from="1" to="#ArrayLen(food)#">
	<cfset rating = getRating(i)>

	<cfoutput>
		#i#. #food[i]#: #rating#<br>
	</cfoutput>
</cfloop>

<cffunction name="getRating">
	<cfargument name="rating" required="yes" type="numeric">

	<cfset score = 0>

	<cfloop index="i" from="1" to="3">
		<cfset score = score + RandRange(1,10)>
	</cfloop>

	<cfreturn score>
</cffunction>

What I expect to see is something like:
1. nitro-green tea and lime mousse: 17
2. snail porridge: 9
3. roast foie gras “benzaldehyde”: 22
4. salmon poached in liquorice gel: 11
5. nitro-scrambled egg and bacon ice cream: 20

Instead what I get is:
4. salmon poached in liquorice gel: 14
4. salmon poached in liquorice gel: 12
4. salmon poached in liquorice gel: 24
4. salmon poached in liquorice gel: 9
4. salmon poached in liquorice gel: 21

So, what’s going on? Well, the problem comes from the simple fact that I’ve failed to var scope the loop counter i in my function. Each time the function getRating is called, i ends up being equal to 4 at the end. You might expect it to end up being equal to 3. However, the way the loop works is that we add 1 to it until it is greater than the to attribute. Once it equals 4 we can stop looping.

So after we call getRating, when I refer to i in my code to reference a value in my array, I will always get the 4th array element.

What if I change the function to give me more random scores; let’s say I want to increase from 3 to 10:

<cffunction name="getRating">
	<cfargument name="rating" required="yes" type="numeric">

	<cfset score = 0>

	<cfloop index="i" from="1" to="10">
		<cfset score = score + RandRange(1,10)>
	</cfloop>

	<cfreturn score>
</cffunction>

This will throw an error due to i now being larger than the size of our array:

The element at position 11 of dimension 1, of array variable "FOOD," cannot be found.

How to fix this? Just add in a line in the function, immediately after any tags, but before any other CFML, like so:

<cffunction name="getRating">
	<cfargument name="rating" required="yes" type="numeric">

	<cfset var i = 0>
	<cfset var score = 0>

	<cfloop index="i" from="1" to="10">
		<cfset score = score + RandRange(1,10)>
	</cfloop>

	<cfreturn score>
</cffunction>

Notice that I’ve also changed the initialisation of the score variable, to also be var-scoped. Even though I know that I haven’t used another variable called score elsewhere in my code, this is just as important. Ideally your CFC functions should be de-coupled, i.e. you can’t guarantee that there won’t be external variables that share the same name. So protect everything by var scoping all variables.

This can also apply even when you’re not referring to variables of the same name elsewhere. If two users simultaneously called a page that had a function that wasn’t var scoped, strange things can happen! This is often the cause of mysterious errors that you can’t replicate yourself.

In all cases, the Var Scoper tool is very useful for finding un-var scoped variables.


* The Fat Duck is reputedly the best restaurant in Britain, and one of the best in the world. It has three Michelin stars; there are only two other 3-starred British restaurants. Coincidentally, one of them is located just round the corner from the ‘Duck.

Despite being so highly-regarded, the Fat Duck has just re-opened after a mysterious bout of illness amongst its diners.

Also, for a restaurant that charges £98 for the à la carte menu and £130 for the tasting menu, they’ve got a terrible website!

March 10, 2009

Installing ColdFusion 8 Developer Edition

Filed under: Coldfusion — duncan @ 12:00 am
Tags: , , , , ,

I decided it was about time I installed the free Developer Edition of ColdFusion 8 on my home PC.

Go to the Adobe ColdFusion 8 homepage and click the Download Free Trial link.

You then have to register or sign in to get to the Download page. There are two versions; the Developer edition or the 30-day Trial edition. Each version is available in English or Japanese for 8 different operating systems.

So far, so straightforward. I downloaded the English Developer edition for Windows.

Once downloaded, I double-clicked the .exe file to install. Which then coughs up this screen.

ColdFusion server installation

Choosing a different location doesn’t help. So I checked the System Requirements; yep, everything ok, plenty of free diskspace etc.

It seems somehow the download file gets corrupted. This has been a known problem since 2004. That forum discussion has many suggestions for how to fix it, none of which seem conclusive. Some of them suggest checking the checksum.

The Adobe site gives the filesize in bytes of each download. The file I downloaded was of the correct size. Adobe also supply the MD5 Checksums for each of the downloads. That’s very useful, if you know what to do with that information. I believe Unix has a built-in function to do Checksum validation. Nothing similar on Windows that I’m aware of. There is commercial software that will do checksums, but I wasn’t wanting to go down that route for obvious reasons.

Instead I found the ‘experimental’ Firefox add-on MD5 Hasher. This will display the MD2, MD5, SHA1, SHA256, SHA384 or SHA512 checksum for any file in the Firefox downloads window.

And unsurprisingly, the file I’d downloaded from Adobe didn’t match the checksum, i.e. implying the download was corrupt. So I downloaded it again, this time using the FlashGot download manager. However the MD5 Hasher plugin only works with files downloaded as a normal Firefox download, not with a download manager it seems.

At that stage, I could have just tried installing that file; in fact it seemed to work, but I chose to cancel installation because I wanted to check that the MD5 checksum validation was working correctly. So I downloaded the file again (3rd time lucky).

So now I had three copies of the same file. Each one of the same byte size. This time the third download’s MD5 checksum validated correctly, and I was able to continue with the installation successfully.

So in short, if you encounter the “Please select another location” problem when trying to do an install of ColdFusion server:

  • Download the file again
  • Use the MD5 Hasher plugin to do checksum validation until you get a download that works
  • And possibly use a download manager like FlashGot to ensure happy downloading!

March 9, 2009

Who reads the Watchmen?

Filed under: Film — duncan @ 12:00 am
Tags: , , , ,

Who watches the Watchmen? by brianjmatis, on Flickr

In case you weren’t aware, the Watchmen movie is out now. Despite being best known as a graphic novel, it was originally published as a 12 issue series. For those who’ve not read it, (or maybe just haven’t read it recently and want a refresher), the first issue (PDF) can be downloaded from DC Comics.

Photo by brianjmatis, Creative Commons license.

March 8, 2009

Debut album cover

Filed under: Photos — duncan @ 12:00 am
Tags: , , , ,

The Stroll - Help You Move A Body

This is one of those internet memes that’s currently infecting Facebook and elsewhere. A bit like the ‘porn star name’ meme from a while ago. I’ve rewritten the instructions slightly

CREATE YOUR DEBUT ALBUM COVER

  1. Go to Wikipedia. Click Random article
    The first random Wikipedia article you get is the name of your band. (alternatively, if the first article you hit is short, hit Random article two more times.)
  2. Go to http://www.quotationspage.com/random.php3
    The last four or five words of the very last quote of the page is the title of your first album.
  3. Go to Flickr and click on Explore the last seven days. Or even better, go to the Advanced Search, and search for photos licensed under Creative Commons “to modify, adapt, or build upon”.
    Third picture, no matter what it is, will be your album cover.
  4. Use Photoshop or similar to put it all together. Search for fonts on the web, or check out a site like Da Font

PS: thanks to Jack Pickard. I’d posted my album cover to Facebook, but hadn’t thought to blog it as well.

March 7, 2009

Glenrothes by-election missing register – inquiry report published

Last month it was reported that the Glenrothes by-election register of electors had gone missing, despite a statutory obligation to keep it for a year after the election. The inquiry into its disappearance has published its report (PDF). If you’re interested I’d recommend you read the PDF, because it contains much more information than any of the news reports, which don’t seem to go beyond the executive summary.

The report’s author, Bill McQueen CBE, is very clear to stress that there is no evidence or suggestion of foul play.

“Human error and management failure” are to blame. In particular, it seems to have been slightly bad luck that the basement they decided to store the files in was also being cleared out of old furniture and confidential waste by contract workers during November – January.

“A failure to store the registers in a more secure location” is cited, which is a clear breach of the Data Protection Act. I hope that the Information Commissioner will now issue an Enforcement Notice against the Scottish Courts Service.

The Returning Officer’s staff delivered all the papers from the election on the 18th and 26th November. Most of that was in labelled black bags, but the register of electors was hand-delivered in a box to the Office Manager at the Kirkcaldy Sheriff Court. This was “because the documents in this box were likely to have to be accessed to respond to requests from candidates”. Despite this, “Sheriff Court staff were clear that any box of registers received in the general office would have been quickly moved and stored in the basement along with the election black bags”.
FAIL!

The SNP had put in a preliminary request on the 19th November, asking for the cost to get a copy of the register. Surely knowing that, a week later when you get the documents they’re looking for, you might think to yourself “this could be handy, I’ll keep it here in the office” instead of dumping it in the basement.

The failure to respond to SNP Councillor John Beare’s request for over two months is particularly telling:
“A court officer … accepted responsibility for the task but ascribed it a lower priority than her core court duties. She worked part-time … and because of pressure of work and annual leave periods, did not seek to complete the task until late January.”
“there was no system in place … for her managers to monitor ad hoc duties such as this…”
“Councillor Beare received no acknowledgement to his letter of 19 November and … he made follow up phone calls to enquire about progress on 10 December, 14, 20, 23 and 29 January. He received responses that the officer dealing with his request was out of the office and that messages would be passed on and calls returned, but they were not.”

Anyone who’s worked in the public sector will recognise all the above as being quite common. Lack of management oversight, part-time workers hard to get in contact with, requests for information or minor tasks being overlooked for months, messages not passed on, etc.

Apparently one reason she’d put the task off was she thought she’d have to open 95 envelopes and count up the names to calculate the cost for Councillor Beare. However the costing system had changed, meaning it would have taken her seconds instead of hours to carry out the initial request. The Sheriff Clerk was aware of this, but hadn’t passed on the information to the staff member who would be doing this.
FAIL!

The use of bin bags to store all this information is maybe less than ideal. It’s no wonder that, when dumped in the corner of a basement, these might be mistaken for genuine rubbish to be dumped.
glenrothes by-election ballot papers

The register of postal electors has been re-constructed from available data by the Returning Officer. The postal votes were probably the most contentious issue for the SNP, given postal turn-out was much higher than anticipated. I expect they will by now have received a copy of this register, and are hopefully satisfied it was all legit.

The report as a whole is worth reading, and top marks to the author and his team for putting it together reasonably quickly (I expected something might come out after six months, by which time everyone would have forgotten it).

Next Page »

Blog at WordPress.com.