ColdFusion recaptcha form and server validation - coldfusion

I'm basically wanting to do server side validation and then post the form data to a URL. My Google Foo is lacking as I haven't found any actual examples of doing this.
Here's what I have so far but maybe I'm going about it wrong.
<!doctype html>
<html lang="en">
<head>
<title>Untitled</title>
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script>
<script type="text/javascript">
var noRobot = function(response){
document.getElementById("sub").disabled = false;
}
</script>
</head>
<body>
<!-- Form Post -->
<CFIF CGI.Request_method IS "post">
<!-- Sends the recaptcha token to Google to verify -->
<cfinvoke component="/components/recaptcha" method="isRecaptchaGood" returnvariable="isGood">
<!-- Only post data if valid recapthca -->
<CFIF isGood>
<p>Good Recaptcha</p>
<!---
How do I foward on all the form data to the API?
// <cfhttpparam type="CGI" value="cgivar " name="mycgi">
// <cfhttp method="Post" url="http://myapi.com/api/users">
--->
<CFEXIT>
<CFELSE>
<p>Bad Recaptcha</p>
</CFIF>
</CFIF>
<CFOUTPUT>
<!---
I used to just post the data to the API, but now I first need to validate the recaptcha response on the server
<form action="http://myapi.com/api/users" method="post">
--->
<form action="#CGI.Script_Name#" method="post">
Name: <input type="text" name = "user" />
<CFIF Application.recaptcha.enabled>
<!--- A simple wrapper around generating the recaptcha div with the appropriate key --->
<cfinvoke component="/components/recaptcha" method="makeRecaptcha">
</CFIF>
<button type="submit" id="sub" name="con" disabled="disabled">Continue</button>
</form>
</CFOUTPUT>
</body>
</html>
As a disclaimer, I have about 6 hours of ColdFusion experience so I assume I'm missing something simple.
Form values edit:
<body>
<cfparam name="form.user" type="string" default="">
<cfparam name="form.amount" type="string" default="">
<form action="#CGI.Script_Name#" method="post">
User: <input type="text" name="user" value="#form.user#" />
Amount: <input type="number" name="amount" value="#form.amount#" />
</form>
</body>

Thanks to the help from #dan-bracuk and #Leigh, here's the working end result which might help someone else down the road:
<!doctype html>
<html lang="en">
<head>
<title>Untitled</title>
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script>
<script type="text/javascript">
<!--- The callback function recaptcha calls when the user has completed the step--->
<!--- Enable the Submit button--->
var recaptchaResponse = function(response){
document.getElementById("submit").disabled = false;
}
</script>
</head>
<body>
<!--- Declare default values for the form so if it fails validation the form can be redisplayed --->
<cfparam name="form.user" type="string" default="">
<cfparam name="form.amount" type="string" default="">
<!--- On Form Post --->
<CFIF CGI.Request_method IS "post">
<!--- Sends the recaptcha token to Google to verify --->
<cfinvoke component="components/recaptcha" method="isRecaptchaGood" returnvariable="isValid">
<!--- Only post data if valid recapthca --->
<CFIF isValid>
<p>Good Recaptcha</p>
<!--- Post the to API --->
<cfhttp method="Post" url="http://localhost:1249/api/users">
<!--- Send Form field values except for the recaptcha response --->
<cfloop list="#Form.FieldNames#" item="i">
<CFIF form[i] eq "G-RECAPTCHA-RESPONSE">
<cfcontinue />
<CFELSE>
<cfhttpparam type="formfield" name="#i#" value="#form[i]#">
</CFIF>
</cfloop>
</cfhttp>
<cflocation url="next.cfm">
<CFEXIT>
<CFELSE>
<!--- Recaptcha verification failed, redisplay the Form --->
<p>Bad Recaptcha</p>
</CFIF>
</CFIF>
<CFOUTPUT>
<!--- Post the Form back to itself first for server side validation --->
<form action="#CGI.Script_Name#" method="post">
User: <input type="text" name="user" value="#form.user#" />
Amount: <input type="number" name="amount" value="#form.amount#" />
<CFIF Application.recaptcha.enabled>
<!--- A simple wrapper around generating the recaptcha div with the appropriate key --->
<cfinvoke component="components/recaptcha" method="makeRecaptcha">
</CFIF>
<!--- Initially disable the continue button until the user completes the Recaptcha --->
<button type="submit" id="submit" disabled="disabled">Continue</button>
</form>
</CFOUTPUT>
</body>
</html>

Related

Passing parameter to cfprogressbar

Using ColdFusion 2018, and trying to add a progress bar on an API call.Created a cfc function to fetch this API details. For this called a "getStatus()" function through bind params. And able to load the cfprogress bar successfully. The problem is that I need to pass an en extra parameter to this getstatus function . Is it possible?
Please see the sample code I tried to load cfprogressbar
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>
<script type="text/javascript">
function startProgress() {
ColdFusion.ProgressBar.start("mydataProgressbar");
};
function onfinish() {
alert("Done");
};
</script>
<body>
<cfif IsDefined("Session.STATUS")>
<cfscript>
StructDelete(Session,"STATUS");
</cfscript>
</cfif>
<cfset sjsondata = '{"name":"Jibin","id":"1234"}'>
<!--- For code simplicity, formatting is minimal. --->
<cfform name="kitform">
<p>To make our service better and to benefit from our special offers,
take a moment to give us your email address and send us a comment.</p>
<p>Name:
<cfinput type="text" name="name"> </p>
<p>E-mail:
<cfinput type="text" name="email"> </p>
<p>Comment:
<cftextarea name="cmnt"/></p>
<p>
<cfoutput>
<cfinput type="hidden" name="jsondata" value="#sjsondata#">
</cfoutput>
<cfinput type="button" name="bttn1" value="Send Comment"
onClick=startProgress()></p>
<!--- The progressbar control --->
<cfinput type="button" name="bttn2" value="Send Comment 2"
onClick=startProgress2()></p>
<div style="padding-left:3px" >
<cfprogressbar name="mydataProgressbar"
bind="cfc:progressbar.getstatus({jsondata})"
interval="1700"
width="200"
oncomplete="onfinish"/>
</cfform>
</body>
</html>
File progressbar.cfc
<cfcomponent name="progressbar">
<cffunction name="getstatus" access="remote">
<cfargument name="jsonData" type="string" required="false">
<cfset str = StructNew()>
<cfset str.message = "Saving Data">
<cfif NOT IsDefined("session.STATUS")>
<cfset session.STATUS = 0.1>
<cfscript>
Sleep(200);
</cfscript>
<cfelseif session.STATUS LT 0.9>
<cfset session.STATUS=session.STATUS + .1>
<cfscript>
Sleep(200);
</cfscript>
<cfelse>
<cfset str.message = "Done...">
<cfset session.STATUS="1.0">
</cfif>
<cfset str.status = session.STATUS>
<cfreturn str>
</cffunction>
</cfcomponent>
Question 1: Is there a way to pass parameter to cfprogressbar getstatus() function?
Question 2: Is there any other alternative method to implement this process in progressbar.

The IDPAGE argument passed to the getPage function is not of type numeric Coldfusion

I am trying to add a new page called result.cfml to the ColdFusion website. This page(result.cfml) contains all basic Html tags and displays inside main.cfml. I see other page( result2.cfml) has the same setup, and it works fine inside main.cfml. However, I am not be able to view the page(result.cfml). So do i have to register this result.cfml within main.cfml?
Here is an error that i got when calling the result.cfml. Please help me.
The IDPAGE argument passed to the getPage function is not of type numeric.
If the component name is specified as a type of this argument, it is possible that either a definition file for the component cannot be found or is not accessible.
main.cfml
<div><img src="/images/titles/<cfoutput>#session.language#</cfoutput>/stepfinal.png" usemap="#STEPS" /></div>
$box:final$
final.cfml
<form action="<cfoutput>#application.site.index#</cfoutput>" method="post">
<input name="event" type="hidden" value="update-final" />
<input name="tpPayment" type="hidden" value="A" />
<button type="submit" style="height:30"></button>
</form>
<form action="<cfoutput>#application.site.index#</cfoutput>" method="post">
<input name="event" type="hidden" value="update-final" />
<input name="tpPayment" type="hidden" value="B" />
<button type="submit" style="height:30"></button>
</form>
update-final.cfml
<cfif form.tpPayment is "B">
<cflocation addtoken="no" url="#application.site.index#/page/result"/>
</cfif>
<cfif form.tpPayment is "A">
<cflocation addtoken="no" url="#application.site.index#/page/result2"/>
</cfif>
result.cfml
<h1>Title1</h1>
<p>some other paragraphs here</p>
result2.cfml
<h1>Title2</h1>
<p>some other paragraphs here</p>
getPage() function
<cffunction name="getPage" access="public" returntype="query" output="no">
<cfargument name="idPage" type="numeric" required="no">
<cfquery name="qryPage" datasource="#application.global.dsn#">
Select idPage
, idTemplate
, idSection
, nmPage
, nmFile
, tpFile
, dsTitle
, dsTitleContent
, stPage
, flMenu
, nmMenu
, flSiteMap
, dsContentTitle
, dsPage
, dtSchedule
, dtExpire
, flProtected
, cdGrantedKeys
, dtCreate
, dtLastUpdate
From Page
<cfif IsDefined("arguments.idPage")>
Where idPage = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.idPage#">
</cfif>
Order by nmPage
</cfquery>
<cfreturn qryPage>

Self submitting form redirect still contains internal anchor

I currently have a form which points to itself but more precisely, to an internal anchor for errors:
<form action="#errors" method="post">
...
</method>
When the form is submitted, I will validate incoming data and if errors are present output them on the screen (located inside the internal anchor). If the data is valid, I will redirect to a confirmation page:
<cflocation url="confirm.cfm" addToken="no" />
My problem is that the page redirected to still contains the reference to the internal anchor. The URL looks like this:
http://mydomain.com/confirm.cfm#errors
I've tried this with other languages and was able to replicate this functionality without the anchor remaining after having redirected.
Edit #1
This is on CF10, Windows 2008 R2.
Form page:
<cfif not structIsEmpty(form)>
<cfinvoke component="#request.cfcPath#.val" method="init" returnvariable="valObj"></cfinvoke>
<cfset valObj.validateGame()>
<cfif valObj.hasErrors()>
<cfoutput>#valObj.showErrors()#</cfoutput>
<cfelse>
<cfif form.editYN eq 0>
<cfinclude template="actInsert.cfm">
<cfelse>
<cfinclude template="actUpdate.cfm">
</cfif>
</cfif>
</cfif>
actUpdate.cfm
<!--- Redirect --->
<cfquery>...</cfquery>
...
<cflocation url="default.cfm?fuseaction=Confirm.gameUpdated" addtoken="No">
actInsert.cfm
<!--- Redirect --->
<cfquery>...</cfquery>
...
<cflocation url="default.cfm?fuseaction=Confirm.gameAdded" addtoken="No">
Edit #2
Here's a test case:
<!DOCTYPE html>
<head>
<title></title>
</head>
<body>
<cfif StructKeyExists(form, "doRedirect")>
<cfif form.doRedirect eq 1>
<cflocation url="http://stackoverflow.com" addtoken="false">
<cfelse>
<div id="errors">
<ul>
<li>Some error could have occured here.</li>
</ul>
</div>
</cfif>
</cfif>
<form action="#errors" method="post">
<div><label for="doRedirect">Do Redirect?</label><select name="doRedirect" id="doRedirect"><option value="0">No</option><option value="1">Yes</option></select></div>
<div><input type="submit" value="Go"/></div>
</form>
</body>
</html>
you can add a # value in the action part of the form.
Otherwise, you can do like:
<form action="" method="post">
<div><label for="doRedirect">Do Redirect?</label><select name="doRedirect" id="doRedirect"><option value="0">No</option><option value="1">Yes</option></select></div>
<div><input type="submit" value="Go"/></div>
</form>

recaptcha not displaying on FF or chrome, IE displays after allowing blocked content

The server that is hosting the code is running coldfusion 4.5. The page in question is a frameset, so I can't link directly to it.
It's this page: http://www.palosverdes.com/calendar/, and then the sign up link on the right under "Admin".
The code that is there right now works as expected for IE after allowing blocked content. Here's the code:
<cfscript>
CHALLENGE_URL = "http://api.recaptcha.net";
SSL_CHALLENGE_URL = "https://api-secure.recaptcha.net";
VERIFY_URL = "http://api-verify.recaptcha.net/verify";
</cfscript>
<cfif isDefined("form.recaptcha_challenge_field") and isDefined("form.recaptcha_response_field")>
<cftry>
<cfhttp url="#VERIFY_URL#" method="post" throwonerror="true">
<cfhttpparam type="formfield" name="privatekey" value="6LfwVs0SAAAAAIlIJpLDvIay_d5G0RncS0VSrnV0">
<cfhttpparam type="formfield" name="remoteip" value="#cgi.REMOTE_ADDR#">
<cfhttpparam type="formfield" name="challenge" value="#form.recaptcha_challenge_field#">
<cfhttpparam type="formfield" name="response" value="#form.recaptcha_response_field#">
</cfhttp>
<cfcatch>
<cfthrow type="RECAPTCHA_NO_SERVICE"
message="recaptcha: unable to contact recaptcha verification service on url '#VERIFY_URL#'">
</cfcatch>
</cftry>
<cfset aResponse = listToArray(cfhttp.fileContent, chr(10))>
<cfset form.recaptcha = aResponse[1]>
<cfset structDelete(form, "recaptcha_challenge_field")>
<cfset structDelete(form, "recaptcha_response_field")>
<cfif aResponse[1] eq "false" and aResponse[2] neq "incorrect-captcha-sol">
<cfthrow type="RECAPTCHA_VERIFICATION_FAILURE"
message="recaptcha: the verification service responded with error '#aResponse[2]#'. See http://recaptcha.net/apidocs/captcha/ for error meanings.">
</cfif>
<cfelse>
<cfset form.recaptcha = false>
</cfif>
<cfif isdefined("form.recaptcha") and form.recaptcha neq "false">
<cfinclude template="addorgresults.cfm">
<cfelse>
I've used this page http://www.palosverdes.com/sandbox/captchatest.cfm to determine that the captcha itself is working correctly, so my guess is that it has something to do with putting the captcha in a frameset. Any ideas?
The reason it isn't working in Firefox:
api-secure.recaptcha.net uses an invalid security certificate.
The certificate is only valid for www.google.com
(Error code: ssl_error_bad_cert_domain)
You appear to be using 2 different sets of code for your test one (that works) and the one that doesn't work.
The one that is broken:
<script type="text/javascript"
src="https://api-secure.recaptcha.net/challenge?k=6LfwVs0SAAAAAClnUJ5XD7O19d9ZdlGBFgAn8Gws">
</script>
<noscript>
<iframe src="https://api-secure.recaptcha.net/noscript?k=6LfwVs0SAAAAAClnUJ5XD7O19d9ZdlGBFgAn8Gws"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field"
value="manual_challenge">
</noscript>
The one that works:
<script type="text/javascript"
src="http://www.google.com/recaptcha/api/challenge?k=6LfwVs0SAAAAAClnUJ5XD7O19d9ZdlGBFgAn8Gws">
</script>
<noscript>
<iframe src="http://www.google.com/recaptcha/api/noscript?k=6LfwVs0SAAAAAClnUJ5XD7O19d9ZdlGBFgAn8Gws"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field"
value="manual_challenge">
</noscript>
I think you need to change the URL's on the first one from api-secure.recaptcha.net to google.com/recaptcha/api

Can't get my reCaptcha to work on my ColdFusion form

I signed up for reCaptcha, got my private/public keys, made my recaptcha.cfm and put the code in my form. The form renders perfectly when you go to the URL but it submits even when the person doesn't put anything in the captcha. This is the code for my recaptcha.cfm and I have the relevant code for the form page commented out in recaptcha.cfm under "Sample." Any help would be greatly appreciated. Thank you.
<cfsetting enablecfoutputonly="true">
<!---
Use the reCAPTCHA API to verify human input.
reCAPTCHA improves the process of digitizing books by sending words that
cannot be read by computers to the Web in the form of CAPTCHAs for
humans to decipher. More specifically, each word that cannot be read
correctly by OCR is placed on an image and used as a CAPTCHA. This is
possible because most OCR programs alert you when a word cannot be read
correctly.
You will need a key pair from http://recaptcha.net/api/getkey to use this tag.
Sample
--------------------------------
<html>
<body>
<cfform>
<cf_recaptcha
privateKey="6LepjdQSAAAAAMspsO04gZUXltxddkiI0ZgSF02h"
publicKey="6LepjdQSAAAAADoLvfvgkwacBAI_GbL-nTy2zvS6">
<cfinput type="submit" name="submit">
</cfform>
<cfif isDefined("form.submit")>
<cfoutput>recaptcha says #form.recaptcha#</cfoutput>
</cfif>
</body>
</html>
--->
<cfscript>
CHALLENGE_URL = "http://api.recaptcha.net";
SSL_CHALLENGE_URL = "https://api-secure.recaptcha.net";
VERIFY_URL = "http://api-verify.recaptcha.net/verify";
</cfscript>
<cfif not structKeyExists(attributes, "publicKey")>
<cfthrow type="RECAPTCHA_ATTRIBUTE"
message="recaptcha: required attribute 'publicKey' is missing">
</cfif>
<cfif not structKeyExists(attributes, "privateKey")>
<cfthrow type="RECAPTCHA_ATTRIBUTE"
message="recaptcha: required attribute 'privateKey' is missing">
</cfif>
<cftry>
<cfparam name="attributes.action" default="render">
<cfif not listContains("render,check", attributes.action)>
<cfset sInvalidAttr="action not render|check">
<cfthrow>
</cfif>
<cfset sInvalidAttr="ssl not true|false">
<cfparam name="attributes.ssl" type="boolean" default="false">
<cfparam name="attributes.theme" type="regex" pattern="(red|white|blackglass)" default="red">
<cfif not listContains("red,white,blackglass", attributes.theme)>
<cfset sInvalidAttr="theme not red|white|blackglass">
<cfthrow>
</cfif>
<cfset sInvalidAttr="tabIndex not numeric">
<cfparam name="attributes.tabIndex" type="numeric" default="0">
<cfcatch type="any">
<cfthrow type="RECAPTCHA_ATTRIBUTE"
message="recaptcha: attribute #sInvalidAttr#">
</cfcatch>
</cftry>
<cfif isDefined("form.recaptcha_challenge_field") and isDefined("form.recaptcha_response_field")>
<cftry>
<cfhttp url="#VERIFY_URL#" method="post" timeout="5" throwonerror="true">
<cfhttpparam type="formfield" name="privatekey" value="#attributes.privateKey#">
<cfhttpparam type="formfield" name="remoteip" value="#cgi.REMOTE_ADDR#">
<cfhttpparam type="formfield" name="challenge" value="#form.recaptcha_challenge_field#">
<cfhttpparam type="formfield" name="response" value="#form.recaptcha_response_field#">
</cfhttp>
<cfcatch>
<cfthrow type="RECAPTCHA_NO_SERVICE"
message="recaptcha: unable to contact recaptcha verification service on url '#VERIFY_URL#'">
</cfcatch>
</cftry>
<cfset aResponse = listToArray(cfhttp.fileContent, chr(10))>
<cfset form.recaptcha = aResponse[1]>
<cfset structDelete(form, "recaptcha_challenge_field")>
<cfset structDelete(form, "recaptcha_response_field")>
<cfif aResponse[1] eq "false" and aResponse[2] neq "incorrect-captcha-sol">
<cfthrow type="RECAPTCHA_VERIFICATION_FAILURE"
message="recaptcha: the verification service responded with error '#aResponse[2]#'. See http://recaptcha.net/apidocs/captcha/ for error meanings.">
</cfif>
<cfelse>
<cfset form.recaptcha = false>
</cfif>
<cfif attributes.action eq "render">
<cfif attributes.ssl>
<cfset challengeURL = SSL_CHALLENGE_URL>
<cfelse>
<cfset challengeURL = CHALLENGE_URL>
</cfif>
<cfoutput>
<script type="text/javascript">
<!--
var RecaptchaOptions = {
theme : '#attributes.theme#',
tabindex : #attributes.tabIndex#
};
//-->
</script>
<script type="text/javascript"
src="#challengeURL#/challenge?k=#attributes.publicKey#">
</script>
<noscript>
<iframe src="#challengeURL#/noscript?k=#attributes.publicKey#"
height="300" width="500" frameborder="0"></iframe><br>
<textarea name="recaptcha_challenge_field" rows="3" cols="40">
</textarea>
<input type="hidden" name="recaptcha_response_field"
value="manual_challenge">
</noscript>
</cfoutput>
</cfif>
<cfsetting enablecfoutputonly="false">
That custom tag is badly out of date. You need to update the URLs because Google changed them. Change them to this:
CHALLENGE_URL = "http://www.google.com/recaptcha/api";
SSL_CHALLENGE_URL = "https://www.google.com/recaptcha/api";
VERIFY_URL = "http://www.google.com/recaptcha/api/verify";
I have posted an updated version of this custom tag as a Gist here: https://gist.github.com/2210356