Happy New Year!

Happy New Year to all!
Early 2008 should bring about a complete rehash of this site (possibly without the blogging, we shall see…) – stay tuned!

Ralph Allwood

Ralph’s site has had a bit of clean up – see http://www.ralphallwood.com.

It features a more extensive discography, and is generally easier to read.

Revisiting Form Spam

After having the code outlined in my previous post deployed for a while, I thought I’d share some points which have come up.

The form is still working (for me at least!) – the only odd behaviour I got at first was this – which I got from the error handling in my applicaton:

14-11-07 : 19:55 – “{ts” is an invalid date or time string.

What was happening here? I started logging ALL the form submissions, to see if there were any common traits – I was particularly interested in the “hidden” timestamp field; After all, if the form was submitted properly, it shouldn’t really have been an issue.

What I found was that the spam bots were unintelligently replacing ALL the form fields, hidden or not, with junk.

So my nice hidden form field which should have read:

<input id=”timeloaded” name=”timeloaded” type=”hidden” value=”{ts ‘2007-11-16 09:50:39’}” />

Was being replaced with:

<input id=”timeloaded” name=”timeloaded” readonly=”readonly” type=”hidden” value=”{ts &lt;br&gt;spamMe@domain.com&lt;br&gt;” />

As I’m not checking to see whether the TimeStamp was a valid one, it was triggering the global error handling. The question is now whether to change this – but I don’t think I will. The spam bots seem quite happy tripping up on it, and it’s only because it’s throwing an error that I even noticed it – but I’m just surprised that THAT is what is stopping the spam, rather than all the other bits!

Go figure… :)

Preventing form spam with ColdFusion serverside validation, rather than CAPTCHA

Web developers all over the world are constantly fighting form spam; there are lots of techniques, some good, some bad; most of them unfortunately involve looking at a graphic of some sort and then entering a series of numbers or digits to proceed with the form submission (a CAPTCHA).

This is obviously completely useless if you’re someone who can’t see the screen, or are using an assisted technology to help browse the web.

What I outline here is a combination of methods for fighting form spam using serverside validation. My requirements are:

  • no javascript: the form must work with or without it.
  • must be as accessible as possible
  • must be as “useable” as possible
  • and obviously, must prevent automated submission as much as possible.
  • Throw errors and alert the user without making them reinsert all the data into the form.

In this example, I’m doing the following tests:

  • the “empty form field hidden by CSS” trick: this still seems to work a bit; create a form field called Referral code, and hide it with CSS display:none; The dumber spam bots tend to fill in all the form fields with junk.
  • Check it’s a valid email address
  • Check there are no URLs in the subject or name line: refers again to the bots filling in forms unintelligently
  • Check the form is less that 8 hours old, but older than 3 seconds: this should prevent a spam bot caching the form and then using the cached version to pump POST requests to your processing page; bots submit automatically, so will trigger the less than 3 seconds error. The time in the form is set by the server
  • Check the form is being submitted from the correct URL/Domain/IP address: again, an anti spam caching technique.

Part One: setting up params, and error checking code

<cfparam name=“form.name” default=“” type=“string”>
<cfparam name=“form.email” default=“” type=“string”>
<cfparam name=“form.subject” default=“” type=“string”>
<cfparam name=“form.message” default=“” type=“string”>
<cfparam name=“form.referral” default=“” type=“string”>
<cfparam name=“form.timeposted” default=“#Now()#” type=“date”>
<cfparam name=“showform” default=“true”>

<!—Add your domain name here—>
<cfparam name=“yourdomainname” default=“www.oxalto.co.uk”>

<!—Create Error Handling Struct—>
<cfset errorStruct=StructNew()>
<cfif isdefined(“form.submit”)>
  <!—Check Referrer—>
  <cfif cgi.SERVER_NAME NEQ yourdomainname>
    <cfset errorStruct.serverError=“Oh dear. It looks to me like you’re trying to send a POST request from a machine other than the authorized webserver.”>
  <!—Check Time submitted vs Now()—>
    <cfif DateDiff(“s”, form.timeposted, now()) LTE 3>
    <cfset timetocomplete= DateDiff(“s”, form.timeposted, now())>
    <cfset errorStruct.timetocomplete=“This form seems to have been submitted a little too quickly (#timetocomplete# seconds). Try again and take your time..”>

<!—Check Form isn’t too old—>
<cfif DateDiff(“d”, form.timeposted, now()) GTE 1>
  <cfset errorStruct.formage=“This form seems to be really old: you may have submitted it from a cached version.”>

<!—Check Valid Email—>
<cfif NOT isValid(“email”, form.email)>
<cfset errorStruct.email=“That doesn’t appear to be a valid email address, please check and try again.”>

<!—Check Referral field is empty—>
<cfif len(form.referral) GT 1>
<cfset errorStruct.reffield=“That does not appear to be a valid referral code: please only enter a code here if you have been given one by our administrator”>

<!—Check Subject—>
<cfif len(form.subject) LT 1>
<cfset errorStruct.subject=“You must enter a subject”>

<!—Check Name—>
<cfif len(form.name) LT 1>
<cfset errorStruct.name=“You must enter your name”>

<!—Check Message—>
<cfif len(form.message) LT 1>
<cfset errorStruct.Message=“You didn’t enter a message”>

<cfif StructisEmpty(ErrorStruct)>
<!—If all ok, send mail—>
<cfmail to=“you@yourdomainname.com“ from=“#form.email#” subject=“[foo] #form.subject#”>


Part Two: The output

<!—Some Sample CSS—>
.contact-form {width:450px;}
.contact-form input { display:block;}
.error {color: #FF0000;}
.success {color:#009933;}
label { background-color:#000000; display:block; color:#FFFFFF;}


<!—Notify of error or success—>
<cfif isdefined(“form.submit”)>
<cfif NOT StructisEmpty(errorStruct)>
<p class=“error”>Message sending failed: there are errors in this form, please review before re-submitting.</h3>
<cfif StructKeyExists(ErrorStruct, “serverError”)><cfoutput><p class=“error”>#ErrorStruct.ServerError#</p></cfoutput></cfif>
<cfif StructKeyExists(ErrorStruct, “TimeToComplete”)><cfoutput><p class=“error”>#ErrorStruct.TimeToComplete#</p></cfoutput></cfif>
<cfif StructKeyExists(ErrorStruct, “FormAge”)><cfoutput><p class=“error”>#ErrorStruct.FormAge#</p></cfoutput></cfif>
<cfset showform=true>
<h3 class=“success”>Thank you, your message has been sent</h3>
<cfset showform=false>

<cfif showform>
<cfform method=“post” action=“#cgi.SCRIPT_NAME#” name=“contact-form” class=“contact-form”>
<legend>Contact Form</legend>
<label for=“name” <cfif structkeyexists(errorStruct, “name”)>class=“error”</cfif>>Name</label>
<cfinput type=“text” name=“name” message=“Please enter your name” value=“#form.name#”>
<cfif structkeyexists(errorStruct, “name”)><cfoutput><p class=“error”>#ErrorStruct.name#</p></cfoutput></cfif>
<label for=“email” <cfif structkeyexists(errorStruct, “email”)>class=“error”</cfif>>Email Address</label>
<cfinput type=“text” name=“email” message=“You must enter a valid email address” value=“#form.email#”>
<cfif structkeyexists(errorStruct, “email”)><cfoutput><p class=“error”>#ErrorStruct.email#</p></cfoutput></cfif>
<div style=“display:none;”>
<label for=“referral” <cfif structkeyexists(errorStruct, “reffield”)>class=“error”</cfif>>Referral Code (optional)</label>
<cfinput type=“text” name=“referral” value=“#form.referral#”>
<cfif structkeyexists(errorStruct, “reffield”)><cfoutput><p class=“error”>#ErrorStruct.reffield#</p></cfoutput></cfif>
<label for=“subject” <cfif structkeyexists(errorStruct, “subject”)>class=“error”</cfif>>Subject</label>
<cfinput type=“text” name=“subject” message=“You need to add a subject” value=“#form.subject#”>
<cfif structkeyexists(errorStruct, “name”)><cfoutput><p class=“error”>#ErrorStruct.subject#</p></cfoutput></cfif>
<label for=“message” <cfif structkeyexists(errorStruct, “message”)>class=“error”</cfif>>Message</label>
<cftextarea name=“message” message=“You haven’t said anything in the message field” rows=“5″ cols=“35″><cfoutput>#form.message#</cfoutput></cftextarea>
<cfif structkeyexists(errorStruct, “name”)><cfoutput><p class=“error”>#ErrorStruct.message#</p></cfoutput></cfif>
<cfinput type=“hidden” value=“#now()#” readonly=“yes” name=“timeposted” class=“hide”>
<cfinput type=“submit” name=“submit” value=“submit” class=“submit”>

Galleon 2 released

The ever tireless Ray Camden has released Galleon Forums V 2:

Rays Blog

Get it HERE

Using the Flickr API to retrieve a list of photosets

[Edit: 7 years later, flickr’s changed their API to SSL only, so you may have to change all http references to https]

[Edit: 9 years later, here’s some simpler code: https://gist.github.com/neokoenig/d98f678054df0f08df77cba98ed30876 ]

Lots of good work has been done on the Flickr API with ColdFusion already: specifically, CFlickr – see http://chris.m0nk3y.net/projects/CFlickr/.

However, for my uses, I didn’t need anything near as complicated: All I wanted to do was to pull a list of photosets, their titles, primary thumbnail and description.

Thankfully, this is quite easy due to the Flickr API.

Part One: Making the request to Flickr

I’m assuming you have an API code, and know your userID:

<!---Flickr Params-->

<!---url.reinit used to manually refresh-->

<!--- Do we have this value? -->

<!---Send my Request to Flickr: this will get an XML doc with all my public photosets-->

<!---parse the XML doc-->

<!---Is XML request returned properly?-->


<!---Set the time this was done-->

<!---Parse/narrow down the info I need into an Array-->

Part Two: Output: I’ve got my XML data, and now just need to loop over the Array.

<!--XML last cached #application.FlickrXmlstarted#--></pre>
<div id="photoset" class="clear">
<!---Output primary image--> <img class="left" src="http://farm#photosets[i].XmlAttributes['farm']#.static.flickr.com/#photosets[i].XmlAttributes['server']#/#photosets[i].XmlAttributes['primary']#_#photosets[i].XmlAttributes['secret']#_s.jpg" /> <!---output title-->
<h4><a href="http://www.flickr.com/photos/#userid#/sets/#photosets[i].XmlAttributes['id']#/">#photosets[i].title.xmltext#</a></h4>

<!---If description exists, show--> #photosets[i].description.xmltext#</div>

And that’s it: I’ve cached the XML data in the Application scope for speed, and I’m looping over the XML data object. If a description exists for the set, it’s output.

Jakoti Hand Shears now available

Jakoti Hand Shears are now available in the UK! If you’ve not tried these, they are superb; one handed and extremely sharp, they seem to cut through anything. We clear our allotment with ours :)

Get yourself a pair!

Hand Shears
Hand Shears
Hand Shears

BBC iPlayer – a few weeks on

I think I’m fed up with this now; it took me a while to realise that the Kservice.exe process was running in the background, even after a reboot, after which the iPlayer wasn’t turned on. So you have to Contrl + Alt + Delete the process every time you turn on the machine.

You’ve got the Kservice.exe file running and using your bandwidth without notification – this is a real oversight : I understand why – most people will unwittingly share the latest episode of Eastenders, and the service will seem really fast (which I still think, it is).

But for those of us which limit out bandwidth usage on peak hours, this is as good as a slap in the face.

Let’s hope the BBC have got the message about this?

Kirsten Johnson

Kirsten Johnson’s website has been re-released.

“Kirsten Johnson’s recordings and performances have delighted listeners around the world. She has performed in Austria, the Czech Republic, Italy, Japan and throughout the United States and United Kingdom. Her CDs have been given airplay on BBC Radio 3, on public radio stations across the U.S., and on radio stations in many European countries. In the UK she has performed in the Wigmore Hall, the Purcell Room, the Royal Academy of Music, the Holywell Music Room, Oxford, and the Austrian Institute, London.”