Adding Open-Source LylaCaptcha to BlogCFC
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:
<!--- NOTE: added lyla capthca --->
<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:
<!--- captcha validation --->
<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) ;)
I'll stop spamming here now. ;)
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
The selected method setColor was not found.
Did you ever get this?
Line 248 that currently reads:
<cfset graphics.setColor(getConfigBean().getFontColor()) />
Should read:
<cfset graphics.setColor(getColorByType(getConfigBean().getFontColor())) />
It is unclear from your post - how do you fix the captcha text not available thing? I'm getting that now.
<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
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?
<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.
Does anyone know what may cause this to happen? Thanks for any help.
It gives a more generic example of how to add captcha to your site (though it uses some simple ajax for validation). There is also downloadable code for that as well.
Thanks!
Diana
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
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
"<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
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.
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
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!!
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
Shortening the app name solved the problem.

