Spellify for Coldfusion V1.0 Released

Spellify is an awesome textarea spell checker which uses a smooth and effective Ajax based interface. It's written by Nikola Kocic and can be downloaded here: http://www.spellify.com/

I was immediately impressed by the look and feel of this project which uses the Google spelling API but was dissapointed to see that it only supported PHP and .NET.

Well, I couldn't have this so set to work on a Coldfusion version. As CF makes these kinds of thing simple, within 30 minutes I had knocked together a Coldfusion version of Spellify.php which makes the call to the Google API and returns the XML to the Spellify Javascript.

I haven't tested this massively but it's a simple piece of code and seems to work nicely so I thought I'd get it released so you can get integrating Spellify if you need a spellchecker for textareas on your site.

Let me know if you find any issues with it.

This *should* work with all versions of CF - at least back to CF6 anyway.

Download Spellify.cfm V1.0

Here are the instructions - taken from the included READ ME.txt:

================================================================================================
Spellify - Spellify.cfm v1.0 (based on Spellify.php by Nikola Kocic - http://www.spellify.com/)
Copyright (c) 2009 James Allen. (jamesallen.name, www.jwadevelopments.com)

E-Mail: james@jamesallen.name
================================================================================================

Spellify.cfm is a Coldfusion version of Spellify.php for use with the superb Spellify text area spellchecker.

INSTALLATION (the following is based on the default spellify.php install and using demo.html to test):

1. Download and unpack the Spellify PHP package: http://www.spellify.com/download.html

2. Place it somewhere in your webroot, e.g /wwwroot/spell/

3. Copy Spellify.cfm to the same location as Spellify.php in the Spellify sub-folder (e.g wwwroot/spell/spellify/spellify.cfm).

4. Edit 'spellify/src/spellify.js', line 47. Change:

var defUrl  = 'spellify/spellify.php';

to

var defUrl  = 'spellify/spellify.cfm';

That's it!

Spellify should now be working with Coldfusion. You will probably have to change the defURL when you implement the code on your site (e.g /functions/spellify/spellify.cfm etc).

Problems connecting to SagePay's TEST and SIM servers - FIXED

Since Tuesday afternoon we have found that we can't connect to the TEST or SIM servers at SagePay. Live is fine however, even though the exact same code is used.

It's a strange problem as an immediate connection failure is received when attempting to POST a transaction registration to either the test or sim servers.

After this had happened we contacted SagePay support who did some checks but told us that there are no problems on the server. However, when I did a quick Twitter search I found another developer who is also getting this issue. I confirmed the problem via my local development server in the office and on the live server so it doesn't appear to be a specific ISP routing problem etc.

However over the past few day SagePay have confirmed that a small number of user's are having problems. It's most certainy not affecting the majority though.

This has led support to believe that the problem is due to Coldfusion and the way it is sending the POST request to the SagePay server.

The Solution

Luckily while throwing this problem out to Twitter a very helpful user (@Zefer) suggested that the problem might be due to the server sending back a gzipped response which cfhttp in Coldfusion can't handle (and certain URL functions in PHP it seems). To fix this we just need to send headers to tell the server what we can accept:

<cfhttpparam type="Header" name="Accept-Encoding" value="deflate;q=0">
<cfhttpparam type="Header" name="TE" value="deflate;q=0">

The raw headers sent in the request will look like this:

Accept-Encoding: deflate;q=0
TE: deflate;q=0

Once I made this change the problem went away immediately.

I assume that SagePay must have made a system change on SIM and TEST but not on LIVE (luckily).

How to Secure Railo 3.1 Admin in IIS 6

I recently setup my new VPS with the awesome Railo 3.1 on Server 2003 and I soon started thinking about the security of the admin URL. With Adobe Coldfusion it's good practice to either move the administrator so it only runs on a non-standard port with IP filtering or protect it with a username and password via web server security.

I decided that I would go the route of securing the Railo admin path via IIS directory security, however I soon realised that in Railo the admin URL is not a physical path. I.E. It is not created as either a virtual directory or a real directory within the webroot of each website hosted on the server.

The Railo admin URL is as follows:

http://www.mysite.com/railo-context/admin/index.cfm

The way this URL is processed is that the ISAPI filter which Railo uses looks out for any call to railo-context and forwards it to the correct place within the Railo system. This is all done outside of IIS.

So how do we protect the URL?

The answer is actually pretty simple although you will have to do it on every virtual site setup on the server.

All we have to do is to create two physical folders within the webroot of the website we want to protect as follows:

railo-context/admin

Once this is created we can then go into the IIS 6 manager, locate the 'admin' folder, right click and select 'properties'. Within 'Directory Security' it is then possible to either restrict accces via IP or via authentication and access control.

If using username and password security go into the 'Authentication Methods' panel and uncheck 'Enable anonymous access' and leave 'Integrated Windows authentication' ticked.

Now, whenever you access the railo admin URL you can log in via an account on the server (e.g administrator). It's recommended that you create a special windows account that will only be used for admin access. You could then only give that user permissions to access the '/railo-context/admin' - though this would need to be done on each folder in each web root. In a hosted scenario this would be a good idea anyway as each customer should really have their own web user account to ensure they can only access their resources on the system.

Note: If you do decide to just log in using the administrator account on the server I recommend you do this over SSL ONLY. If you do it over http:// it would be possible for a user on the same network (e.g wifi access point) to sniff your http packets and determine your admin password - not good.

 

Monkey Island: Special Edition Released

Just a quick non-Coldfusion related post about the release of the classic point and click adventure game by LucasArts - Monkey Island.

Nineteen years after release the guys at LucasArts have taken the original game - keeping the exact same engine - and given it a visual and audiotory overhaul. They have redone all of the graphics (painstakingly redrawn by hand), updated the musical score and added a complete vocal track - using the voice actor from later Monkey games to play Guybrush again.

The results are frankly mind blowing. The graphics look fantastic and really give new life to this amazing example of the point and click adventure genre. I always longed to have Monkey Island as a 'talkie' but never thought it would happen. With this update I finally get to hear what all these awesome characters sound like and the results are brilliant.

I have only played it for a few minutes but got a huge buzz as soon as the opening titles appeared in glorious HD. I will be playing it on my 50inch plasma at 1080p resolution (1920x1080) and have to say it looks stunning.

It's being sold through Steam for the bargain price of £6.99 in the UK and $9.99 in the US.

It's a meaty 2.5gb or so download but the whole process is made nice and simple via Steam - I'm very impressed with the whole delivery mechanism I must say.

The game is available on PC via Steam direct download or on the XBox 360 via the Xbox Market Place,

You can get the PC version from here: http://store.steampowered.com/app/32360/

Details about the Xbox 360 version here: http://www.xbox.com/en-US/games/s/secretofmonkeyislandxbla/

Being able to play this again brings back some awesome memories of the first day I got my Amiga A500+ in 1990. Once I started playing I couldn't stop until it was completed.

I now just hope that it sells in bucket loads and convinces LucasArts to give the same treatment to Monkey Island 2: Le Chucks Revenge.

Here's some shot's of the game on my TV: (click for a larger view)


UPDATE:
You might not have realised yet but if you press F10 (on the PC version) at any time the game will revert back to the original look exactly - complete with actions panel at the bottom of the screen. It also removes the vocal track and goes back to the original music. Awesome to see the difference.

SagePay: Inconsistency in IFrame 'Low profile' option on Server solution - ** Workaround **

I've recently been integrating the SagePay Server solution into a client site and it was decided to utilise the new 'Low Profile' option (introduced in protocol 2.23). This new option allows the SagePay payment pages to appear within an Iframe placed inside the main site template. The obvious benefit of this is that the customer is not redirected to another site to complete payment and confidence in the vendor is improved.

The integration went pretty well with the SagePay XSLT templating system being relatively easy to use and customise. I soon had a template which nicely matched the style of the vendor's website.

During testing everything worked great. The payment form appeared within the IFrame, the card details could be entered and the 3D Secure page worked as expected. After the payment side had been handled SagePay redirect back to the vendor website outside of the IFrame - just what we need.

However, during testing I tested an AMEX card. AMEX cards are not part of the 3D Secure system and so the customer is not shown a 3D Secure page - just the card input form. Now this shouldn't really be a problem but when the card details have been entered and validated, SagePay redirect the customer back to the vendor site but inside the IFrame!

This is definetely NOT what we want as once redirected to our payment processing template the full site design is shown within the IFrame (header, sidebar and footer).

At this point I hit the HTTP debugger to find out what was causing this inconsistency. Here is what I found:

When 3DS authentication is required, the following HTTP requests are triggered:

https://test.sagepay.com/gateway/service/carddetails                302         POST     test.sagepay.com                /gateway/service/carddetails   
https://test.sagepay.com/gateway/service/cardconfirmation    302         GET        test.sagepay.com                /gateway/service/cardconfirmation       
https://test.sagepay.com/gateway/service/authentication         200         GET        test.sagepay.com                /gateway/service/authentication            
https://test.sagepay.com/mpitools/accesscontroler?action=pareq         200         POST     test.sagepay.com                /mpitools/accesscontroler?action=pareq                            
https://test.sagepay.com/mpitools/accesscontroler?action=auth            200         POST     test.sagepay.com                /mpitools/accesscontroler?action=auth               
https://test.sagepay.com/gateway/service/authentication?action=callback        200         POST     test.sagepay.com                /gateway/service/authentication?action=callback           
https://test.sagepay.com/gateway/service/authentication?action=completion                302         POST                test.sagepay.com            /gateway/service/authentication?action=completion
REDIRECT
http://dev.jamesallen.name/index.cfm/page/orders.order.cfm             200         GET                dev.jamesallen.name /index.cfm/page/orders.order.cfm

In this case, the final SagePay request is a POST (assumng it uses target="_top" which jumps the customer out of the Iframe)
The redirect back to the site is thus outside of the Iframe and all is good.


If 3DS authentication is NOT required the following HTTP requests are triggered:

https://test.sagepay.com/gateway/service/cardselection?vpstxid={283FE985-CE13-A510-B9E6-840531*****} 302                GET        test.sagepay.com            /gateway/service/cardselection?vpstxid={283FE985-CE13-A510-B9E6-840531*****}
https://test.sagepay.com/gateway/service/carddetails                200         GET        test.sagepay.com                /gateway/service/carddetails   
https://test.sagepay.com/gateway/service/carddetails                302         POST     test.sagepay.com                /gateway/service/carddetails   
https://test.sagepay.com/gateway/service/cardconfirmation    302         GET        test.sagepay.com                /gateway/service/cardconfirmation       
https://test.sagepay.com/gateway/service/authentication         302         GET        test.sagepay.com                /gateway/service/authentication
REDIRECT            
http://dev.jamesallen.name/index.cfm/page/orders.order.cfm             200         GET                dev.jamesallen.name/index.cfm/page/orders.order.cfm

In this case the last request inside SagePay is a GET which means the customer is left in the Iframe.

So there is a fundamental inconsistency in the implementation of the new 'Low Profile' option in the SagePay Server product. So, how do we solve this?

After some head scratching I came up with a solution which I feel is fairly straight forward and will ensure that when SagePay fix the problem, the site will not suddenly change it's behaviour and will be easy to modify to remove the Javascript redirect.

The solution is as follows:

  1. In your notification template (the one that SagePay POSTS back to and you respond with Status, RedirectURL, StatusDetail), set the RedirectURL to a new handler template (e.g http://site.com/orders/go.cfm). Then set a session variable to the URL you want the customer redirected to to continue the payment process.

  2. Create the handler template. This will build a dynamic form whose target is set to the redirect URL set in session in the step above. Javascript will be used to automatically submit the form when the page is loaded. An HTML submit button will be created inside the form in case the user does not have Javascript enabled.

That's the solution in a nutshell. We are modifying our notification template to always redirect to a new handler template which will jump the customer out of the Iframe and direct them to the correct template that continues the order process. The form target on the handler template is set to "_top" which causes the form submission to break out of the IFrame.

To help with this below is the code I use on my handler template (go.cfm). I use JQuery for the automatic form submission and to hide the submit button. You could of course code that functionality without JQuery.

<!--- URL to redirect to (set in session before the jump to here) --->
<cfset targetURL = session.targetURL>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><html>

<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <link rel="stylesheet" href="/styles/styles.css" type="text/css" />
   
    <title>Payment Processor</title>
   
    <script language="javascript" src="/functions/jquery.js"></script>
    
    <script language="javascript">
        $(document).ready(function() {
            $("#jump").hide();
            $("#jump").submit();
        });
    </script>
</head>

<body>
    <cfoutput>
        <form id="jump" action="#targetURL#" target="_top">
            <input type="submit" value="Click to continue your order">
        </form>   
    </cfoutput>
</body>
</html>

With this approach, once SagePay fix the inconsitency I can simply change this template to perform a server redirect to the required URL instead of using the Javascript and self submitting form.
Either that, or to change the notification template so that it goes directly to the required URL's as before.

Hopefully this will help some people who have got this problem when implementing the Server solution.

Follow me on Twitter - CFJamesAllen

I recently got introduced to the crazy world of Twitter and have to say I've got well and truly addicted! It's a brilliant new way to communicate, network and keep up to date with people. I have now setup a special Twitter account for Coldfusion and Internet programming related twittering so please feel free to follow me if your interested.

I've just setup a mini-feed on the right hand site of the blog which shows the recent 'tweets' that I've posted.

Follow as I get angry with CSS and tweet about all manor of Coldfusion and other Internet goodness.. Things often hot up around Friday evening when the weekend usually kicks off with beer, chips (fries to the US readers) and US TV shows. :)

My username on Twitter is CFJamesAllen.

Fixing "java method security exception" when installing Mango Blog

I've just setup a new blog which I'm going to use for tracking my weight loss and fitness goals this year. As part of the planning for the project I had to decide what blog software to use. I was all set to go with BlogCFC (as I use for this blog) but then Mango Blog came onto my radar. The brilliant API system and easy to use skinning facilities swung me so I decided to build the new blog using Mango.

However, when I uploaded the code to my CF7 hosting and accessed the web root I got this error:

java method security exception. A security exception occurred while
invoking java method on a "java.lang.Class" object. MethodName is
getMethods. Possible cause: createobject function and cfobject tag are
disabled in the security sand box.

After searching the MangoBlog forums I found other people had experienced this problem. However, the author of MangoBlog could only suggest that maybe the ISP has disabled the CreateObject function.

To check this, I did some tests but found that CreateObject was working perfectly.

Very weird. However, I have found the solution - though one which makes 0 sense to me.

If you get this, to fix open up application.cfc.

Now, comment out the entire onError function:

<cffunction name="onError" returnType="void">
<cfargument name="Exception" required="true" />
<cfargument name="EventName" type="String" required="true" />
<cfset request.message = createObject("component",variables.componentsPath & "Message") />
<cfset request.message.setTitle("Error: " & arguments.EventName) />
<cfset request.message.setText(arguments.exception.message) />
<cfset request.message.setStatus("error") />
<cfset request.message.setData(arguments.exception.detail) />

<!--- Set appropriate HTTP status code --->
<cfif REFindNoCase("NotFound$",arguments.exception.type)>
<cfheader statuscode="404" statustext="Not Found" />
<cfelse>
<cfheader statuscode="500" statustext="Internal Server Error" />
</cfif>

<cftry>
<cfsetting enablecfoutputonly="false">
<cfinclude template="generic.cfm">
<cfcatch type="any">
<cfsetting enablecfoutputonly="false">
<cfinclude template="error.cfm">
</cfcatch>
</cftry>
</cffunction>

Now access the webroot again.. The install wizard should appear as expected. At this point you can uncomment the onError handler and reupload. Everything should work fine then.

What the hell is going on here then? It could be just me who this works for but I'd be interested to hear from anyone else who has success with this fix. I am using Coldfusion MX 7.

My local development server running CF8 has no issues.

New SagePay URL's

I thought it might be easier if I listed the new SagePay URL's here.

I'll start with some code for Coldfusion developers who want to quickly copy and paste straight into their payment pages.

Note: These URL's are for the VSPDirect product

Also, this is not a complete list of the operations available (I don't use all of them in my code so didn't include).

<cfset protx = StructNew()>
<cfset protx.live.purchaseURL = "https://live.sagepay.com/gateway/service/vspdirect-register.vsp">
<cfset protx.live.voidURL = "https://live.sagepay.com/gateway/service/void.vsp">
<cfset protx.live.refundURL = "https://live.sagepay.com/gateway/service/refund.vsp">
<cfset protx.live.releaseURL = "https://live.sagepay.com/gateway/service/release.vsp">
<cfset protx.live.repeatURL = "https://live.sagepay.com/gateway/service/repeat.vsp">
<cfset protx.live.authoriseURL = "https://live.sagepay.com/gateway/service/authorise.vsp">
<cfset protx.live.callbackURL = "https://live.sagepay.com/gateway/service/direct3dcallback.vsp">

<cfset protx.test.purchaseURL = "https://test.sagepay.com/gateway/service/vspdirect-register.vsp">
<cfset protx.test.voidURL = "https://test.sagepay.com/gateway/service/void.vsp">
<cfset protx.test.refundURL = "https://test.sagepay.com/gateway/service/refund.vsp">
<cfset protx.test.releaseURL = "https://test.sagepay.com/gateway/service/release.vsp">
<cfset protx.test.repeatURL = "https://test.sagepay.com/gateway/service/repeat.vsp">
<cfset protx.test.authoriseURL = "https://test.sagepay.com/gateway/service/authorise.vsp">
<cfset protx.test.callbackURL = "https://test.sagepay.com/gateway/service/direct3dcallback.vsp">

<cfset protx.sim.purchaseURL = "https://test.sagepay.com/Simulator/VSPDirectGateway.asp">
<cfset protx.sim.voidURL = "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorVoidTx">
<cfset protx.sim.refundURL = "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRefundTx">
<cfset protx.sim.releaseURL = "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorReleaseTx">
<cfset protx.sim.repeatURL = "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRepeatTx">
<cfset protx.sim.authoriseURL = "https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorAuthoriseTx">
<cfset protx.sim.callbackURL="https://test.sagepay.com/Simulator/VSPDirectCallback.asp">

Now here are the URL's without the code:

LIVE

 

purchaseURL = https://live.sagepay.com/gateway/service/vspdirect-register.vsp
voidURL = https://live.sagepay.com/gateway/service/void.vsp
refundURL = https://live.sagepay.com/gateway/service/refund.vsp
releaseURL = https://live.sagepay.com/gateway/service/release.vsp
repeatURL = "ttps://live.sagepay.com/gateway/service/repeat.vsp
authoriseURL = https://live.sagepay.com/gateway/service/authorise.vsp
callbackURL = https://live.sagepay.com/gateway/service/direct3dcallback.vsp

TEST

purchaseURL = https://test.sagepay.com/gateway/service/vspdirect-register.vsp
voidURL = https://test.sagepay.com/gateway/service/void.vsp
refundURL = https://test.sagepay.com/gateway/service/refund.vsp
releaseURL = https://test.sagepay.com/gateway/service/release.vsp
repeatURL = https://test.sagepay.com/gateway/service/repeat.vsp
authoriseURL = https://test.sagepay.com/gateway/service/authorise.vsp
callbackURL = https://test.sagepay.com/gateway/service/direct3dcallback.vsp

SIM

purchaseURL = https://test.sagepay.com/Simulator/VSPDirectGateway.asp
voidURL = https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorVoidTx
refundURL = https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRefundTx
releaseURL = https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorReleaseTx
repeatURL = https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorRepeatTx
authoriseURL = https://test.sagepay.com/Simulator/VSPServerGateway.asp?Service=VendorAuthoriseTx
callbackURL = https://test.sagepay.com/Simulator/VSPDirectCallback.asp

 

Protx - SagePay URL switch today - Old URL's DO NOT work anymore due to forwarding failure

NOTE: It looks like this problem may only affect Coldfusion and Java.

Protx have just switched over to the new SagePay URL's today on LIVE and unfortunately the old URL's have broken. This was not supposed to happen and the old URL's should have continued for the forseeable future.

SagePay are telling developers to update all sites to the new URL system.

I can't imagine how many orders are being lost this morning.

Get your URL's updated ASAP, full details here:

https://support.sagepay.com/forum/Topic8090-22-1.aspx

ProtX is rebranding to SagePay - TEST and SIM servers now use different URL!

I wondered why when I tried to test my Protx VSPServer integration today that it just wouldn't work. I kept getting this SSL problem when submitting the HTTP POST:

I/O Exception: Name in certificate `test.sagepay.com'
does not match host name `ukvpstest.protx.com'

I assumed this was a temporary issue but have just found out that ProtX is rebranding to SagePay and you need to use the following domain for TEST and SIM:

http://test.sagepay.com

There is also a new path for each operation so check out the table posted on the ProtX support forums:

https://support.sagepay.com/forum/Topic8090-22-1.aspx

More Entries

© 2010 James Allen | Contact Me
This blog runs on the awesome power of BlogCFC - created by Raymond Camden. This blog is running version 5.9.