Form Last Name Length Check in ColdFusion? - coldfusion

We have a form and we're trying to validate the entry of the last name field to make sure that, at a minimum, there is at least two characters entered. Here is the type of code we're using:
<cfif form.last_name is "S">
<cfset errors = errors & "<li>You must include your <b>complete</b> last name.</li>">
</cfif>
Any thoughts on how we can make sure that the last name field has two or more letters (without doing each letter individually as a separate check, as above). Other thoughts on how to validate last names more effectively would be helpful as well.

Use the Len() function:
<cfif Len(FORM.last_name) GTE 2>
<!--- perform success stuff here --->
</cfif>
The above code means "If the length of the last_name field submitted via http form post is 2 or more characters..."
Free tip: Be super-fancy and trim the field's whitespace before making the check:
<cfif Len(Trim(FORM.last_name)) GTE 2>
<!--- perform success stuff here --->
</cfif>

Related

Coldfusion Complex Construct

I am trying to construct a coldfusion conditional statement that looks for incremental form ID checkboxes to have been selected. All checkboxes are defined as Component[component number]. I have established a loop that is looking for a URL variable that is different for every form that calls on the condition as seen below. The issue I am having is that I recieve an error when executing that tells me "Complex constructs are not supported with function parameterexists."
Clearly it has to do with the dynamic nature of the parameterexists statement, but I do not fully know what this means. Can anyone explain this and also offer a solution? I am fairly new to coldfusion and coding, so take it easy on me.
<cfloop from="1" to="#URL.loopcounter#" index="loopvar">
<cfif parameterexists(Form.Component#loopvar#)>
INSERT INTO Results (MP_Barcode, Reworked, Reworked_By)
VALUES ('#Form.MontaplastBarcode#', 'YES', '#URL.BadgeNumber#')
</cfloop>
<cfoutput>
<p class="success">YOUR REWORK HAS BEEN SUBMITTED SUCCESSFULLY.</p>
</cfoutput>
<cfelse>
<p class="error">NO REWORK WAS SUBMITTED. NO COMPONENTS SELECTED.</p>
</cfif>
Depending on the form that calls on this action, the URL loopcounter variable could range from 1 to 50.
To answer the question, there are several ColdFusion functions that won't allow you to create a dynamic name before the function evaluates it. parameterExists() was one of those. Both isDefined() and structKeyExists() will allow dynamic variables. So will the member function of structKeyExists() > structName.keyExists("theKey").
Again, if you are new to ColdFusion, I'd simply pretend you never saw parameterExists(). I believe it has been listed as "deprecated" since CF 4.5 or somewhere around there. That's almost 20 years ago. That function has actually become somewhat of a joke about how Adobe never really throws away their trash.
As I pointed out above, I'd get rid of it completely and go with structKeyExists(). I also don't know what your whole page is doing, but with the code you provided, I'd change it to something like this:
<cfloop from="1" to="#url.loopcounter#" index="loopvar">
<cfoutput>
<cfif structKeyExists(form,"Component#loopvar#")>
<!--- SANITIZE INPUTS --->
<cfset inMontplastBarcode = sanitizingFunction(FORM.MontaplastBarcode)>
<cfset inBadgeNumber = sanitizingFunction(URL.BadgeNumber)>
<!--- Now use sanitized inputs in query with queryparams --->
<cfquery name="InsertStuff" datasource="myds">
INSERT INTO Results (MP_Barcode, Reworked, Reworked_By)
VALUES (
<cfqueryparam value="#inMontaplastBarcode#" cfsqltype="cf_sql_varchar" maxlength="50">
, 'YES'
, <cfqueryparam value="#inBadgeNumber#" cfsqltype="cf_sql_varchar" maxlength="20">
)
</cfquery>
</cfif>
</cfoutput>
</cfloop>
In your database, Reworked should be a boolean datatype. It appears that it may be a 'Yes' or 'No' string. A true boolean will be a) smaller and b) easier to validate. In the cfqueryparams, if you are using a cf_sql_varchar datatype, make sure you set an appropriate max length. You'll need to look at the available CF datatypes and see how they match up to your database datatypes. (Also see https://cfdocs.org/cfqueryparam)
For your sanitizingFunction() that you'll use to sanitize your input variables, you'll want to write a function that will follow through the steps to clean up your variables to strip out unsafe characters or other things you don't want. That is an entirely different, extremely large topic all on its own.
In your form, name your checkboxes simpler. Like reworked01 through reworked50.
On the action page use cfparam to default them to zero (since html forms don't post unchecked boxes):
<cfloop from="1" to="#url.loopCounter#" index="i">
<cfparam name="form.reworked#numberFormat(i, 00)#" default="0">
</cfloop>
Then instead of fumbling with whether or not a variable exists, you can instead look for the value:
<cfloop from="1" to="#url.loopCounter#" index="i">
<cfif evaluate("form.reworked"&i) eq 1>
<!--- some logic here --->
<cfelse>
<!--- some other logic here --->
</cfif>
</cfloop>

Use FindNoCase to find url string

I've search around and find some valuable info. about FindNoCase but I have not yet found the answer to this specific question.
I'm using FindNoCase to find "/us/" in the url and then process some code. This works fine for one country site.
<cfif FindNoCase("/us/",#cgi.SCRIPT_NAME#)>
Process some code here.
</cfif>
My question is: Is there a way to find the piece of the url, "/xx/", for multiple country sites and process the same code between the cfif tags? For example "/us/", "/ca/", "/mx/", etc.
Hopes this makes sense.
If searching for multiple different codes among a string, I'd use REFindNoCase. Make a regex like so (/us/)|(/ca/) which would look for /us/ or /ca/ and per the documentation (http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7e99.html) you can return the sub-expressions and reference them.
No looping required.
REFindNoCase("(/us/)|(/ca/)", URL, 1, true)
To reference the strings you would do:
<cfset URL = 'domaim.com/page/us/' />
<cfset match = REFindNoCase("(/us/)|(/ca/)", URL, 1, true) />
<cfif arrayLen(match) GT 0>
<cfset value = Mid(URL,match.pos[1],match.len[1]) />
<cfswitch expression="#value#">
<cfcase value="/us/">
<!--- Do something for US match --->
</cfcase>
<cfcase value="/ca/">
<!--- Do something for CA match --->
</cfcase>
<!--- ETC --->
</cfswitch>
<cfelse>
<!--- Do something if no match found --->
</cfif>
In this case, value would equal /us/. Or it should anyway. I'm writing all of this here and not actually testing on my server. You'd have to adjust this if you want to cover multiple matches in a string.
If I'm understanding your question correctly, you want to process the SAME code for several countries, if detected in the URL. You could just create a database of country codes you want to process a certain way (CountryTableXYZ), query it, then loop through that query so it'll search the URL for each entry you have in the table.
<cfloop query="CountryQuery">
<cfif FindNoCase("#countryCode#",#cgi.SCRIPT_NAME#)>
Process some code here.
</cfif>
</cfloop>
At least that's how I interpret it. If I'm not correct please let me know or clarify your initial post.

Check values in a list are all identical

Ok here's a thing, I have a form which when submitted can only update a table when a particular checkbox form variable values are identical, if one is different then it should proceed to update the table. So basically the user is selecting different rows and hitting the submit button.
So for example a good submission would be
form.claimid = 12,12,12,12,12
a bad submission would be
form.claimid = 1,5,77,33,4,
I'm not sure how to check in a list if all the values in the form.claimid list are identical or not?
I would appreciate any ideas on this.
You can also use CF's native ListRemoveDuplicates() if the version is sufficient (CF10, Railo/Lucee 4)
https://wikidocs.adobe.com/wiki/display/coldfusionen/ListRemoveDuplicates
<cfif ListLen(ListRemoveDuplicates(mylist)) eq 1>
I'll leave this as an alternate means for older CFs.
I'm not sure how to check in a list if all the values in the form.claimid list are identical or not?
There are a couple ways, most of which involve looping, but I'm going to show you a regular expression that can do this. We're going to get the first value using ListFirst, and use a ReReplace on that value to see if every other value matches.
I use a loop here but only as a demonstration.
<cfoutput>
<cfset mylist = "11,22,33,44|44,44,33,44|557,557,557">
<cfloop list="#mylist#" index="m" delimiters="|">
<cfset matchele = listfirst(m)>
<cfset eradicate = rereplace(m,"(?:(?:^|,)#matchele#(?=,|$))+","","ALL")>
"#m#", "#matchele#", "#eradicate#"<br />
</cfloop>
</cfoutput>
If you're stuck on CF 9 or lower, you could loop over the list and put the elements into a struct:
<cfset list_coll = structNew() />
<cfloop list="#mylist#" index="myitem">
<cfset list_coll[myitem] = "dummy" />
</cfloop>
<cfif structCount(list_coll) EQ 1>
<!--- This is good --->
<cfelse>
<!--- This is bad --->
</cfif>
The reason this works is that structs can't have duplicate keys.

Insert data from form with dynamically named fields

OK. I've done a terrible job of explaining what I'm trying to do. I will try one more time to be more clear.
I have a list of variables that is submitted to a page with a cfquery insert. The variables come from dynamically named form fields, and are captured using a cfloop:
<cfloop list="#form.fieldnames#" index="item">
</cfloop>
What I have are form fields dynamically named, and a value added, as such:
<input type="hidden" name="ticketid_#some_number#" value="#some_quantity#">
For brevity, lets say the form field name is ticketid_6, and the value is 4. This could be a different name and value (for instance, ticketid_3 with a value of 1), or there might be several form fields of similar construct with different names and/or values.
So, on the insert page, I need to insert ticketid_6 4 times (creating 4 separate rows) into my table. So, a row in the database for each dynamically named form field, times the value of each.
I hope that explains it better.
Leigh,
I am still open to your suggestion on the previous post, but I fear I might not have explained my situation clearly enough for you to give your best recommendation. I will re-approach that question after I get this part figured out.
If you need to loop through all your field names and treat each one of those fields as a list you'd need to do two loops to insert each item.
<cfloop list="#form.fieldnames#" index="item"><!--- loop through all the form fields --->
<cfif find('ticketid_',item)><!--- if the form name contains 'ticketid_'. Use findNoCase if you want to ignore case sensitivity --->
<cfloop from="1" to="#form[item]#" index="counter"><!--- loop through the number in form.ticketid_ --->
<cfquery datasource="#dsn#">
INSERT INTO table (fieldname, fieldValue, TicketNum)
VALUES (
<cfqueryparam value="#item#" cfsqltype="cf_sql_varchar">,--fieldName from the form
<cfqueryparam value="#form[item]#" cfsqltype="cf_sql_varchar">--value of the fieldName in the form
<cfqueryparam value="#counter#" cfsqltype="cf_sql_integer">--ticket number being inserted
)
</cfquery>
</cfloop>
</cfif>
</cfloop>
You'll need to do server side validation to verify they haven't entered a non numeric number for the input box, but assuming you've done that this should achieve what you're looking for.
You need to use Evaluate function to get form dynamically input field value
Try this one
<input type="hidden" name="ticketid_#some_number#" value="#some_quantity#">
<cfloop list="#form.fieldnames#" index="item">
<cfoutpuy>Evaluate("ticketid_#item#")</cfoutpuy>
</cfloop>
You need to first bundle your data into an XML structure
<cfsavecontent variable="myFormData">
<cfoutput>
<ul class="xoxo">
<cfloop list="#form.fieldnames#" index="item">
<cfloop list="#form[item]#" index="eachItem">
<li><b>#xmlformat(item)#</b> <var>#xmlformat(eachItem)#</var>
</cfloop>
</cfloop>
</ul>
<cfoutput>
</cfsavecontent>
Then do a single insert
<cfquery>
INSERT INTO table (formData)
VALUES (<cfqueryparam value="#myFormData#" cfsqltype="cf_sql_varchar">)
</cfquery>
When you pull the data, you can
Show it as is, a bulleted list,
Promote to a bunch of rows in a table
Note that the data is inserted as both HTML and XML

Handling CFSELECT

I'm totally unused to Cold Fusion, I'd like to know how to handle a multiple CFSELECT, in particular how to know how many rows I've selected and taking them one by one.
Actually I've managed to see all the rows togheter:
<!--- page_a.cfm --->
<cfform name="fooform" ........>
<cfselect query="myquery" name="fornitori" multiple="yes"></cfselect>
<!--- page_b.cfm --->
<cfoutput>#form.fornitori#</cfoutput>
And, if it's not too much, I'd like to know why it's not correct to write:
<!--- page_b.cfm --->
<cfoutput>#fooform.fornitori#</cfoutput>
Since it is a multiple selection list, the options you select will be submitted to page_b.cfm as a comma delimited list. This means you can use list functions to calculate the total items selected and cfloop to iterate through the selections individually. Note, when using "multiple" select lists, if you select nothing the form field will not exist.
<cfparam name="form.fornitori" default="">
<cfoutput>
Total Items Selected = <cfoutput>#listLen(form.fornitori)#</cfoutput>
Individual Selections:<br>
<cfloop list="#form.fornitori#" index="theSelection">
#theSelection#<br>
</cfloop>
</cfoutput>
why it's not correct to write ..
Because FORM refers to a special system structure, not the name of your html form (ie fooform). FORM contains any form fields submitted via method=POST.
#myquery.recordcount#
btw, use cfdump to display anything. you see some really interesting stuff (I'm not sure whether recordcount is in there though)
getting to the elements:
<cfoutput query="queryname">#title#<br />#content#</cfoutput>
inside the cfoutput you have access to the variables of an element.
coldfusion 9 help