Apr 24, 2006
Are you tired of comment spam? Well, I am not...I love it (cue Police Squad). Well, fortunately
Peter Farrell recently released
LylaCaptcha, an highly configurable and high-quality open-source captcha solution. Also fortunately, adding LylaCaptcha to
Ray Camden's
BlogCFC is also easy...here's how.Obviously the first thing you need to do is download LylaCaptcha and unzip it. I placed my copy in the org folder of BlogCFC as this seemed like an obvious location for it.
The next step is to edit the xml config file for LylaCaptcha. You will need to set the location for the temp image files by modifying the outputDirectory attribute. I set mine to /img/captcha/ which is a folder I created for this purpose. I also decided to change height config to 45 and font size to 25 to shrink the size of the generated file (this is purely for appearance sake...this step is not necessary but it shrinks the size of the captcha a bit so it doesn't utlize so much real estate). That's it. The rest of the configuration parameters can remain the same unless you choose to go further. One of the nice things about LylaCaptcha is the sheer amount of configurable settings it includes (and for a new open-source project, it is very well documented - though the documentation could potentially include a more usable example, but Peter has mentioned that an example application is in the works).
Ok, now we need to modify some of the BlogCFC files - you will need to keep this in mind for future BlogCFC upgrades. You can begin by adding this code to line 60 of application.cfm:
<cfset application.captcha = CreateObject("component","org.captcha.captchaService").init(configFile="/org/captcha/captcha.xml") /> <cfset application.captcha.setup() />
This code is exactly what it seems, it initializes the captcha component with your configuration XML. The second line is required because LylaCaptcha was built with user's adding dependency injection via ColdSpring in mind.
The next step will be to create two include files (which I have included in the download attachment to this post). The first is called captcha.cfm. It includes the form fields necessary to display the captcha and collect the user's response. It includes the hash needed to verify the correct response in a hidden form field. The code is pretty basic:
<cfset variables.captcha = application.captcha.createHashReference() /> <cfoutput> <input type="hidden" name="captchaHash" value="#variables.captcha.hash#" /> <tr> <td colspan="2" align="right"> Captcha text: <input type="text" name="captchaText" size="6" /> </td> </tr> <td colspan="2" align="right"> <img src="showCaptcha.cfm?hashReference=#variables.captcha.hash#" /> </td> </tr> </cfoutput>
The createHashReference() function creates the hash code that we will use later to generate the captcha and it is stored in the hidden form field. Finally, the image src is another include of sorts (showCaptcha.cfm) that will serve up the generated captcha image via cfcontent like so:
<cfset variables.captcha = application.captcha.createCaptchaFromHashReference("file",url.hashReference) /> <cfcontent type="image/jpg" file="#variables.captcha.fileLocation#" deletefile="true" reset="false" />
You will notice that the captcha file is generated from hash reference above. Both of these files are placed in the root directory of your blog (i.e. the client folder in the blogCFC zip download). Now just include captcha.cfm in the form line 193 of addcomment.cfm.
The next step is including the code to validate the captcha entry. You can add the captcha validation at line 73 of addcomment.cfm as follows:
<cfif not len(form.captchaText)> <cfset errorStr = errorStr & "Please enter the Captcha text.<br>"> <cfelseif NOT application.captcha.validateCaptcha(form.captchaHash,form.captchaText)> <cfset errorStr = errorStr & "The captcha text you have entered is incorrect.<br>"> </cfif>
The first part of the if statement obviously checks to ensure that the captcha was entered, but the second code validates the entry using the validateCaptcha() function of LylaCaptcha. It takes two arguments, the first being the hash code and the second is the captcha text (i.e. the form entry by the user) and simply returns a boolean either validating or invalidating the match. Simple enough. Note, I did not use the resource bundle in BlogCFC to generate the error messages obviously to make the example code easier to follow.
Well, that's it...comment spammers be damned. If you would like to test out my code, just comment on this entry with whatever ego boosting compliments you might have for me (unless you are a spammer that is) ;)
Download the attachment.
Just an update. I recommend changing the launchcomment javascript function on tags/layout.cfm to a height of 550 to prevent the need to scroll to find the post button when adding the initial comment (further comments will need to scroll anyway).
Posted By Brian Rinaldi / Posted on 04/25/2006 at 8:07 AM
Good job! I'll try this out on my blog. I had played with LylaCaptcha a bit, but got an error message so didn't continue. Now I'll have to try again.
I keep getting "Captcha not available" in random font variations and I've read the FAQ (located at
http://lyla.maestropublishing.com/ ) and uncertain what I'm missing. The hash is being sent in correctly, but there's a talk about "a "" string of text," but I'm uncertain where to debug/track that down.
Posted By
Todd / Posted on 05/04/2006 at 7:57 AM
Ok, found the issue. The function getHashReference() is returning text = "". Not sure why variables.instance.hashReferenceCache isn't being found yet.
I'll stop spamming here now. ;)
Posted By
Todd / Posted on 05/04/2006 at 8:04 AM
No problem. If you figure it out feel free to share the fix. One note I should make to this post is that I did have to implement the setColro fix listed under Known Bugs or Problems on the lylaCatpcha site.
Posted By Brian Rinaldi / Posted on 05/04/2006 at 8:09 AM
Brian,
Getting closer to the issue. Least, I know where the disconnect is now. I have a feeling that Steven is running into the same issue (or chose his to be static or pulled from a list), because if you look at his comments page and hit refresh a few times, you'll start to see a pattern. It's not random like yours.
The disconnect is that the variables.captcha.hash that you're passing into showCaptcha.cfm isn't matching up with the CFC's getHashReference's variables.instance.hashReferenceCache[1].
If I turn the <img src=""> code temporarily into a module or comment out the cfcontent part and work with showCaptcha.cfm directly, they match up and it randomly generates like yours does. The moment I use the the img tag again, it fails again and falls back on the default answer of "" from getHashReference().
So, now I'm beginning to wondering if this isn't a code issue, but a server issue. I'm using Apache 2. How about you?
~Todd
Posted By Todd / Posted on 05/04/2006 at 8:50 AM
Todd, I went to Steven's site and did about 15 refreshes without error. I am running on IIS, so perhaps that is the issue. I would recommend submitting a bug via the email on the site. I will try to pass your issue on to the author and see if he is aware of them.
Posted By Brian Rinaldi / Posted on 05/04/2006 at 9:05 AM
Sorry. I don't mean to imply that you'll get an error on Steven's website. I mean to imply that if you refresh it 15 times, you'll start to see a pattern of words that he's using. He's not using the random feature of the Captcha text as you are. He has a defined list.
Posted By Todd / Posted on 05/04/2006 at 9:13 AM
Right...rereading your comment, I now see what you meant. I did see a repeat words because he chose to run off a static list (as his post mentions), nonetheless, I did not see a "pattern"...the repetition seemed random.
Posted By Brian Rinaldi / Posted on 05/04/2006 at 9:17 AM
I got it working. Stupid error on my part. I was so focused on reproducing what you have here that I forgot the context of how you were using it (in conjunction with BlogCFC) as I was just randomly using it without a framework involved (BlogCFC). Code works pretty good. Not too crazy about the actual image creation being dependent on the application scope, but.. oh well.
Posted By Todd / Posted on 05/04/2006 at 11:45 AM
Hey Brian, I'm beggining the integration work. I'm getting:
The selected method setColor was not found.
Did you ever get this?
Yup. It is listed under the known bugs on the lyla site. Here's the fix from the site:
Line 248 that currently reads:
<cfset graphics.setColor(getConfigBean().getFontColor()) />
Should read:
<cfset graphics.setColor(getColorByType(getConfigBean().getFontColor())) />
Posted By Brian Rinaldi / Posted on 05/06/2006 at 11:51 AM
Got it. He forgot to mention that this bug is on two lines.
It is unclear from your post - how do you fix the captcha text not available thing? I'm getting that now.
Never mind. All is well now. Thanks Brian! (Oh, you ARE ok with this code going into v5, right?)
Absolutely! Glad I could contribute.
Posted By Brian Rinaldi / Posted on 05/06/2006 at 12:01 PM
I have tried your code with a couple of small changes on a want ad reply page on my site. You will find a test page here -
http://www.expat-online.com/living/classifieds/ad_reply.cfm?id=7282. I can't seem to get the validate command to work. I am using cfform with required=yes so I do not need the first line of your validation and am using this:
<cfif NOT application.captcha.validateCaptcha(form.captchaHash,form.captchaText)>
<cfset captcha_error = 'yes'>
and then I include the error text in the cfform if captcha_error is yes.
Can you help me on this?
Thanks
John
John, your form validation doesn't seem to have anything to check if the captcha was not entered (as described above) - as I get the captcha error before I even submit the form. Beyond that, you would need to provide me more information for me to assist. For instance, are you getting an error? What exactly is happening? As long as you create the image from the proper hash reference you should be good to go.
Posted By Brian Rinaldi / Posted on 05/12/2006 at 7:10 PM
I'm having problems getting your code snippets to work on a very simple page. First, I can get the sample to work:
http://www.gyro4.org/captcha/captchatest.cfm
When I create a simple form using the examples from the blog, the picture doesn't show.
http://www.gyro4.org/captcha/test2.cfm
my application.cfm has:
<cfset application.captcha = CreateObject("component","captchaService").init(configFile="/captcha/captcha.xml") />
<cfset application.captcha.setup() />
test2.cfm has:
<cfset variables.captcha = application.captcha.createHashReference() />
<cfoutput>
<input type="hidden" name="captchaHash" value="#variables.captcha.hash#" />
<tr>
<td colspan="2" align="right">
Captcha text: <input type="text" name="captchaText" size="6" />
</td>
</tr>
<td colspan="2" align="right">
<img src="showCaptcha.cfm?hashReference=#variables.captcha.hash#" />
</td>
</tr>
</cfoutput>
and showcaptcha.cfm has:
<cfset variables.captcha = application.captcha.createCaptchaFromHashReference("file",url.hashReference) />
<cfcontent type="image/jpeg" file="#variables.captcha.fileLocation#" deletefile="true" reset="false" />
When I access the test.2cfm, it does create a new jpg in the directory I told the xml file to put it into. Any thoughts as to what I might have messed up?
Posted By Dennis Longnecker / Posted on 05/25/2006 at 11:36 PM
Dennis, are your appliation variables being set inside a conditional statement? It should be like this:
<cfif not structKeyExists(application,"captcha")>
<cfset application.captcha = CreateObject("component","captchaService").init(configFile="/captcha/captcha.xml") />
<cfset application.captcha.setup() />
</cfif>
Other than that, I am not sure...you could send me the files.
Posted By Brian Rinaldi / Posted on 05/26/2006 at 7:44 AM
I have been trying to get the captchatest.cfm example to work. Something is obviously wrong as it force downloads a CFM file to my desktop.
Does anyone know what may cause this to happen? Thanks for any help.
I'm having a problem with my implementation and was wondering if you have a suggestion; if one person loads my page with the captcha on it and then a second person comes along and accesses the same page, before the first person has finished typing the captcha text, the first person will then get "invalid captcha text" error. I have it implemented almost exactly as it is presented in this blog. Is this a known issue? Any suggestions?
Thanks!
Diana
Posted By diana / Posted on 09/14/2006 at 9:33 AM
Diana, No, this is not a known issue. It sounds to me like maybe you are missing the cfapplication perhaps? Are you actually integrating into blogCFC because I didn't cover certain things in great detail because they were already in blogCFC. If you like, check out my other more general instructions at
http://www.remotesynthesis.com/blog/index.cfm/2006/6/21/Validating-CAPTCHA-with-AJAX
Posted By Brian Rinaldi / Posted on 09/14/2006 at 9:07 PM
Hello,
I can get the test to work, but when i try to implement, I get no graphic. If this helps, when I try to go to the url of the captcha image on working models it takes me to a save this file prompt but what I get for mine is the following error:
The web site you are accessing has experienced an unexpected error.
Please contact the website administrator.
The following information is meant for the website developer for debugging purposes.
Error Occurred While Processing Request
Element CAPTCHA is undefined in a Java object of type class [Ljava.lang.String; referenced as
Posted By Michael Appenzellar / Posted on 10/16/2006 at 2:52 PM
Hi,
I've managed to get lylaCaptcha working on my development server, but when I've uploaded it to my live server I get the following error from CF Diagnostics:
Element INSTANCE.HASHREFERENCECACHETIMESTAMP is undefined in VARIABLES.
The error occurred on line 936.
The erroring file is showCaptcha.cfm. Has anyone else received this error before? I think it has something to do with the way the two servers could be caching variables but I'm not too sure.
Cheers
J
Posted By
J / Posted on 11/16/2006 at 9:01 AM
Having just moved from CF5 to MX 7 development I have plunged into the deep end with this. I am quite used to java so I can read the code but the debugging of why I was only seeing "captch not available" had me utterly perplexed. Especially as I could not find an equivlent of the "System.out" in Java to print debug rubbish to the console. I was delving into all the instance of object stuff when I cam across this note on this blog:
"<cfif not structKeyExists(application,"captcha")>"
So if I understand this correctly, when I don't have this line I just keep creating more unique objects each time the page is refreshed. And thus "instance" never refers to the right one.
I added that test and all was well. So far. I will get better at this - I promise.
Is there simple "System.out.println" in CF
The debugging tag you are looking for is <cfdump var="#whatever#">
You are also correct on the application variable.
Also, unless you are trying to edit an older copy of blogCFC (the recent versions already include this code), I would probably refer you to my other post -
http://www.remotesynthesis.com/blog/index.cfm/2006/6/21/Validating-CAPTCHA-with-AJAX
While that focuses on using LylaCaptcha with Ajax, it is a more generalized example.
Posted By Brian Rinaldi / Posted on 11/28/2006 at 8:09 PM
I too am getting:
Element INSTANCE.HASHREFERENCECACHETIMESTAMP is undefined in VARIABLES
from showCaptcha.cfm
when running on a live server which I believe is 6.1. Any ideas?
Julian
For those with the INSTANCE.HASHREFERENCECACHETIMESTAMP undefind problem, check you application name, and make sure there are no special characters my blog was having the same problem
http://www.johnramon.com and I found an underscore in my application name was the problem.
Posted By
John Ramon / Posted on 01/24/2007 at 11:08 AM
Well, I have read your both the tutorials, but when I implement them to my site the image never gets showed?:S do you know what am i missing here? i also downloaded your own zipped code and implemented it too but i still get no graphics:S i am really fedup now coz I am unable to fix this problem and trying since last three days... can u help me with this? my email id iz meet.love@hotmail.com
Thanx for your tutorials! I loved the ajax one!! coz i use mx kollection and it is being impossible for me to implement and captcha service in it!!
Anyway thanx!!
Posted By Brian / Posted on 05/30/2007 at 1:27 PM
Another developer got LylaCaptcha working last year, but after we moved to a new web server it suddenly stopped working (none of the code had changed either). I re-downloaded and tried to re-configure the code from scratch, but I basically ran into the same issue as Todd according to his 5/4/06 posting.
I went over the documentation for 2 days straight and could never figure out what was wrong. After going through the examples in this blog I found this in my showCaptcha.cfm file wasn't working:
<cfset variables.captcha = application.captcha.createCaptchaFromHashReference("stream",url.hashReference) />
<cfcontent type="image/jpg" variable="#variables.captcha.stream#" reset="false" />
Switching to this code did the trick for me.
<cfcontent type="image/jpg" file="#variables.captcha.fileLocation#" deletefile="true" reset="false" />
That along with another code modification got the captcha to verify.
Thanks!
I couldn't find this fix anywhere in the LylaCaptcha documentation.
Jose
We found that when your application name is longer than 35 characters it throws that error ('Element INSTANCE.HASHREFERENCECACHETIMESTAMP is undefined in VARIABLES')!
Shortening the app name solved the problem.
Posted By
Lewis John / Posted on 06/30/2008 at 8:41 AM
With regard to the 'Element INSTANCE.HASHREFERENCECACHETIMESTAMP is undefined in VARIABLES' - I discovered quite by accident that the name attribute of the cfapplication tag in Application.cfm (CFMX 7) requires at least 11 characters. I am working on an Obituary website. When name="obituaries" I got the error, but when name="obituaries1" the captcha worked.
The word "Obituaries" has exactly 10 characters. So when name="obituariesobituariesobituariesobituaries" (40 characters), the captcha still worked. When I tried name="obituarieso" (11 characters), the captcha still worked. But again, when name="obituaries" (10 characters) it errors out.
So it doesn't matter if you use numbers or text - it has to be at least 11 characters. I'm using IIS 6 on Win2003.
I am trying to integrate the LylaCaptcha into an existing form. Both the ajaxCFC and the lylacaptcha folders have been copied to a folder named components. The Application file is modified to account for this path change and the captcha image displays correctly on the form. When the submit button calls the validateCaptcha function, I get an alert window displaying Invalid Response From Server. I believe the error is in this code that I modified to account for the new path, but I have not been able to correct it.
_ajaxConfig = {'_cfscriptLocation':'/components/ajaxCFC/ajaxCaptcha.cfc', '_jsscriptFolder':'/components/ajaxCFC/js'};
Posted By Les Phipps / Posted on 09/24/2008 at 8:51 AM
@les - obviously I can't tell if that path is correct just by looking at the pasted code, but your CFC is in the ajaxCFC folder? I would probably recommend putting it elsewhere but that likely isn't the cause of your issue. Probably you have debugging turned on or something like that that is appending some garbage to the XML response. I recommend something like Firebug which will allow you to see exactly what the call is returning.
Posted By Brian Rinaldi / Posted on 09/24/2008 at 10:08 AM
It appears that the component does not like the application file in our website. When I run the index page included with the code, it works fine. Then when I delete the application file in the same folder and force it to use the site's application page, it generates the Invalid Response from Server message. The captcha code in the site's application is as follows:
These paths do point to the files and do generate the image correctly. It is only on the validateCaptcha and newCaptcha functions that the error is generated.
Posted By Les Phipps / Posted on 09/24/2008 at 1:57 PM
I removed the underscores from the app name and it resolved the Element INSTANCE.HASHREFERENCECACHETIMESTAMP is undefined in VARIABLES. error.
Posted By
Kelly / Posted on 11/20/2008 at 9:53 AM