Cast as integer in ColdFusion; sanitizing variables - validation

I'm rusty at ColdFusion, I've been used to PHP for so long. What I want to do is something like this:
<?php
$id = (isset($_GET['id'])) ? (int)$_GET['id'] : 0;
?>
Basically, check for a url parameter called id and if it exists make sure it's an integer so I can safely use it in database queries. If it ends up zero, that's fine too.
I have:
<cfscript>
if (IsDefined("URL.id") AND IsNumeric(URL.id)) {
id = int(URL.id);
} else {
id = 0;
}
</cfscript>
This is working, but is awfully messy. Is there a better way to do this?

Recent versions of ColdFusion also have a ternary conditional operator:
<cfset id = (structKeyExists(URL, "id") and isNumeric(URL.id)) ? int(URL.id) : 0>

I would use cfparam. I'd also scope explicitly, but that's not necessary. I wouldn't use the IIF() function, because it makes use of evaluate(), which can be problematic, I'd also avoid DE() for the same reason. In this case, it won't be an issue, but I avoid them on general principle in any situation where it's not absolutely necessary. I've been using CF for a few years now, and it hasn't been necessary yet.
<cfparam name="url.id" default="0" />
<cfif isNumeric(url.id)>
<cfset local.id = int(url.id) />
<cfelse>
<cfset local.id = 0 />
</cfif>

To me, the simplest way to ensure your variable is an integer is to wrap the variable in val().
It attempts to parse the string and extract any integer found (at the beginning of the string). If none is found it returns 0.
If TestValue = "234A56?7'", Val(TestValue) returns 234.
If TestValue = "234'5678'9?'", Val(TestValue) returns 234.
If TestValue = "BG234", Val(TestValue) returns the value 0, (not an error).
If TestValue = "0", Val(TestValue) returns the value 0, (not an error).
See http://cfquickdocs.com/cf8/#Val

Apologies for raising an old thread but came up with this same question and found a simple solution that might help others with this issue
NumberFormat(URL.id)
There are also various masks that you can specify in different scenarios
ColdFusion Reference
A formatted number value:
If no mask is specified, returns the value as an integer with a thousands separator.
If the parameter value is "" (an empty string), returns 0.
http://help.adobe.com/livedocs/coldfusion/8/htmldocs/help.html?content=functions_m-r_08.html

You might also look into cfparam.
<cftry>
<cfparam name="url.id" default="0" type="integer">
<cfcatch>
<!--- log? etc --->
<cfset url.id = 0>
</cfcatch>
</cftry>

You can use IIF. It's cool.
<cfset id = IIf(IsDefined("URL.id") AND Int(URL.id), Int(URL.id), DE("0"))>

Related

I have a need to see all session scope for all logged in users in ColdFusion2018

I start with this find;
<cfscript>
app = application.getApplicationSettings().name;
sessionCollection = application.sessionTracker.getSessionCollection(app);
</cfscript>
and then attempt to loop thru the collection;
<cfloop collection="#sessionCollection#" item="i">
#StructFind(i, 'CurrentAction')#
</cfloop>
which fails with;
You have attempted to dereference a scalar variable of type class java.lang.String as a structure with members.
I have tried
#CurrentAction[i]#
which fails with;
Variable CURRENTACTION is undefined.
when I know for a fact it exists
(https://ibb.co/ZJwsKFS)
Ive tried dot notation as well.
The purpose is to identify an ajax listener activity for one user, and affect an action on another specific user as a response. I am under the impression I can send an action by sessionID end user. Please feel free to let me know if this is NOT possible.
So this code:
<cfset x = {
a = 1
, b = 2
, c = 3
}>
<cfoutput>
<cfloop collection="#x#" item="i">
<li>#i#</li>
</cfloop>
</cfoutput>
Outputs the following:
A
B
C
Which means that i is the key of the struct defined in the collection attribute. Your code is trying to find a key in the collection (struct), but you're referencing the wrong variable.
To find the value of B, you would do StructFind(x, "b"). You don't need the cfloop either, you just need to check if the key exists, then get the value.
<cfset someVariable = "">
<cfif structKeyExists(x, "b")>
<cfset someVariable = structFind(x, "b")>
</cfif>

ArrayAppend returning boolean instead of array

OK I have been struggling with this for sometime and I figured I would go back to the basics and try and figure out my error, as I get the same error here as I do down the line.
Here is my Code:
<cfparam name="session.cart" default="arrayNew(1)">
<cfset session.cart = arrayAppend(session.cart,structNew() )>
<cfset thisCartItem = arraylen(session.cart)>
<cfset session.cart[thisCartItem].itemID = "X">
<cfset session.cart[thisCartItem].quantity = "X">
<cfset session.cart[thisCartItem].itemName = "X">
<cfdump var="#session.cart#">
Here is my error:
Object of type class java.lang.Boolean cannot be used as an array
The error means exactly what it says. The variable session.cart is not an array. It is a boolean value. If you read the ArrayAppend documentation it explains why. The function modifies the array in place and returns a boolean value:
Returns True, on successful completion.
By capturing the result here, you are actually setting the cart value to true/false:
<!--- Note the addition of the pound signs in the CFPARAM --->
<cfparam name="session.cart" default="#arrayNew(1)#">
<cfset session.cart = arrayAppend(session.cart, structNew())>
Having said that, you could simplify the code a lot by using the shorthand syntax supported in all recent versions of CF ie {} - new structure and [] - new array. To create a new array:
<cfset session.cart = []>
To append one or more structures to the end of that array:
<!--- append first structure to array --->
<cfset ArrayAppend( session.cart
, { itemID = "X", quantity = "X", itemName = "X" }
)>
<!--- append second structure to array --->
<cfset ArrayAppend( session.cart
, { itemID = "Y", quantity = "Y", itemName = "Y" }
)>

Check if argument exist in ColdFusion

I have a question about arguments that are passed with ajax in coldfusion. So I have three arguments that I'm passing date1, date2 and meetingDate. I have to compare three of these arguments and return the string based on the dates. Here is my logic:
<cfset sigDate1 = dateFormat(trim(arguments.date1),'yyyy/mm/dd')>
<cfset sigDate2 = dateFormat(trim(arguments.date2),'yyyy/mm/dd')>
<cfset meetDate = dateFormat(URLDecode(arguments.meetingDate),'yyyy/mm/dd')>
<cfelseif (sigDate1 LT meetDate) OR (sigDate2 LT meetDate)>
<cfset myResult = "blockDate">
<cfelse>
My current code has one problem, if I just pass one of these two dates(date1 or date2) I will always get "blockDate" returned with my ajax function. I detected the problem and if I just pass date1 but not date2 my elseif still will be executed no matter what. So I was trying to fix this problem with using one extra cfif and check if my date1 and date2 isDefined but that did not fix the problem. If anyone have any idea how to fix this bugg please let me know.
Thanks in advance.
There are a couple different ways to handle this. As I understand it; the arguments always exist, but you are concerned they may have blank values.
Here are some ideas you should be able to adapt to get you started:
use defaults
<cfset sigDate1 = iif(isDate(trim(arguments.date1),'dateFormat(trim(arguments.date1),'yyyy/mm/dd')','[default value]')/>
<cfset sigDate2 = iif(isDate(trim(arguments.date2),'dateFormat(trim(arguments.date2),'yyyy/mm/dd')','[default value]')/>
<cfset meetDate = iif(isDate(trim(URLDecode(arguments.meetingDate),'dateFormat(trim(URLDecode(arguments.meetingDate),'yyyy/mm/dd')','[default value]')/>
or (test dates)
<cfif isDate(trim(arguments.date1)) and isDate(trim(arguments.date2)) and isDate(URLDecode(arguments.meetingDate))>
<cfset sigDate1 = dateFormat(trim(arguments.date1),'yyyy/mm/dd')/>
<cfset sigDate2 = dateFormat(trim(arguments.date2),'yyyy/mm/dd')/>
<cfset meetDate = dateFormat(URLDecode(arguments.meetingDate),'yyyy/mm/dd')/>
<cfelse>
<--- error code --->
</cfif>
or (use try block)
<cftry>
<cfset sigDate1 = dateFormat(trim(arguments.date1),'yyyy/mm/dd')/>
<cfset sigDate2 = dateFormat(trim(arguments.date2),'yyyy/mm/dd')/>
<cfset meetDate = dateFormat(URLDecode(arguments.meetingDate),'yyyy/mm/dd')/>
<cfcatch type="expression">
<--- error code --->
</cfcatch>
</cftry>

Querying HTML attributes in Dart

I have HTML in this format:
<form name="fruit_name">
<input id="fruit-name" type="hidden" name="Banana">
</form>
I have Dart querying the fruit name like this:
var fruitName = query('#fruit-name').attributes.values.last;
This works great in Chrome and Safari. But In Firefox, the attributes come back in a different order, so name is no longer last. What's the best way to grab the attribute I'm after without relying on the browser so much?
attributes is a Map, so this should work:
var fruitName = query('#fruit-name').attributes['name'];
You can use :
var fruitName = query('input#fruit-name').name;
The result of the query is in fact a InputElement and you have more member that in a simple Element.
By prepending #fruit-name with input you will tell to the analyzer that the result of query is an InputElement. Without that you would get a warning ( There is no such getter 'name' in 'Element' ).
Finally, from a performance point of view, the best way to do this is with document.getElementById(id) because getElementById is really faster than querySelector ) :
InputElement fruitNameElement = document.getElementById('fruit-name');
var fruitName = fruitNameElement.name;
Here, the first line allows to type fruitNameElement to prevent warning when calling fruitNameElement.name.

Can I store a struct in a Coldfusion session variable?

I'm passing a struct to a CF Custom Tag. I'd like the CFM page that is this custom tag to assign this struct to a dynamically created session variable. Creating the session variable works when assigning it to a simple value such as a number, but fails when assigning it to the struct in the way I'm doing it below.
<cfset Evaluate("SESSION.myVar#ATTRIBUTES.count# = #ATTRIBUTES.myStruct#")>
I thought this was possible, but when I try to do so I get an error:
Complex object types cannot be converted to simple values.
This is how the struct is created:
<cfset testStruct = StructNew()>
<cfset testStruct.something = 2>
And passed through the custom tag:
<cf_myTag myStruct="#testStruct#" count="#i#">
I think the Evaluate portion is messing things up here.
As Leigh says, use array notation rather than Evaluate() to create your dynamically named session variable:
<cfset SESSION[ "myVar" & ATTRIBUTES.count ] = ATTRIBUTES.myStruct>
Yes you can,
Just use the duplicate method
<cfset SESSION.myVar = duplicate(ATTRIBUTES.myStruct) />
yes, you can just do the following:
note I'm using a cflock here to avoid any potential race conditions.
<cflock scope="session" throwontimeout="true" timeout="5" type="exclusive">
<cfset session["myVar" & ATTRIBUTES.count] = attributes.myStruct />
</cflock>
The issue above is the evaluate statement. It's trying to evaulate the structure as a simple value in the string, and then evaluate the string.
You can get around evaulate entirely. The reason is you want a dynamically named session variable?

Resources