If you have code like so:
<cfcase value="Test">
/**Do Stuff
</cfcase>
Is it possible to reference that value within the case statement?
I want to concatenate a list that can handle multiple cases and be able to dynamically reference the variables like so:
<cfcase value="Test,Another,Yes,No">
<cfif this.value EQ 'Test'> blabla </cfif>
</cfcase>
I can't find anything that detailed about this for everywhere I have looked, just curious if it is even possible.
Yes, you can run multiple case statement in a cfcase tag:
<cfswitch expression="#URL.TestValue#">
<cfcase value="Blue,Red,Orange" delimiters=",">
<cfoutput>#URL.TestValue#</cfoutput>
</cfcase>
<cfcase value="Yellow">
<cfoutput>#URL.TestValue#</cfoutput>
</cfcase>
</cfswitch>
Well... yeah... if your <cfswitch> expression was #originalExpression#, then the value that caused the case to trigger will be... #originalExpression#. There's no need to be tricky about it!
IE: you'll need to do something like this:
<cfswitch expression="#originalExpression#">
<cfcase value="Test,Another,Yes,No">
<!--- stuff common to all of Test,Another,Yes,No ---->
<!--- stuff specific to various cases --->
<cfif originalExpression EQ "test">
<!--- do stuff ---->
<cfelseif listFindNoCase("Yes,No", originalExpression)>
<!--- do stuff ---->
<cfelse>
<!--- do stuff for "another" --->
</cfif>
</cfcase>
<!--- other cases etc --->
</cfswitch>
I don't think it is possible using ColdFusion tags. You can do something similar with <cfscript>
switch (expression) {
case "Test" :
// Do some extra stuff
// No break here
case "Another" : case "Yes" : case "No" :
// Do yet some normal stuff
break;
}
Disclaimer: I would not want to maintain this code
Related
i am writing a code to check for session and session value and if they do not exists or exists but have empty value or 0, i want them redirected
here is my start
<cfset lstofSessionsToCheck = 'EmplyID,Username'>
<cfset st = {}>
<cfloop collection="#session#" item="i">
<cfset SetVariable("st.session.#i#",duplicate(session[i]))>
</cfloop>
<cfparam name="redirection" default="false">
<cfif session.Username eq ''>
<cfset redirection = true>
<cfelseif session.EmplyID eq ''>
<cfset redirection = true>
</cfif>
it is missing some checks here
check if session is defined before it checks its value
if its defined, its value should not be empty or 0 or -1
please guide,m i am almost near its end but stuck at that
session is a special scope in ColdFusion and either always or never exists. It depends on the state of the sessionManagement attribute in your Application.cfc (or Application.cfm/<cfapplication>). In case sessionManagement is false, accessing session will immediately throw an exception. I assume you are not seeing this error, so session management is enabled in your environment. That leaves you with checking if the session fields are initialized. Your new best friend is called structKeyExists().
<!--- username needs to exist and must not be empty --->
<cfset hasUsername = (
structKeyExists(session, "Username") and
(len(session.Username) gt 0)
)>
<!--- ID needs to exist, must be a number and > 0 --->
<cfset hasID = (
structKeyExists(session, "EmplyID") and
isNumeric(session.EmplyID) and
(session.EmplyID gt 0)
)>
<!--- if either username or ID is not properly set, do a redirect --->
<cfif (not hasUsername) or (not hasID)>
<cfset redirection = true>
</cfif>
You can simplify the last line to a single expression:
<cfset redirection = ((not hasUsername) or (not hasID))>
As for your usage of setVariable(): You should generally avoid this function (along with evaluate()) as they can be easily exploited and pose a security risk.
Rewrite:
<cfset st = {}>
<cfloop collection="#session#" item="i">
<cfset SetVariable("st.session.#i#",duplicate(session[i]))>
</cfloop>
to
<cfset st = {}>
<cfset st.session = {}>
<cfloop collection="#session#" item="i">
<cfset st.session[i] = duplicate(session[i])>
</cfloop>
(And by the way, i is actually a key here, not a numeric index. Only use i with a for loop.)
I'm not sure the best way to do this is by looping through the entire thing every time you check. Unless those values are coming from a database or something after authentication?
Typically, if you want to restrict access to a page, you would check the session scope using structKeyExists(), for just a couple specific things.
The code would look something like this:
<!---This code sees if the user is logged in at all. If they are missing important information, I clear the session scope and redirect them to the login page. --->
<cfif !structKeyExists(SESSION, 'Username')>
<cfset structClear(SESSION)>
<cflocation url="YourPageHere" addtoken="maybe">
</cfif>
<!---This code checks for a specific permission to be defined. If not, it stops or redirects the user.--->
<cfif structKeyExists(SESSION, 'CanEditUsers') AND SESSION.CanEditUsers eq 1>
<!---your code here--->
<cfelse>
<cflocation url="YourPageHere" addtoken="maybe">
</cfif>
This is only a rough example - but hopefully puts you on the right path. Let me know if anything is unclear or needs to be edited to better fit your situation.
Our code base has quite a bit of the following example as we allow a lot of our base pages to be customized to our customers' individual needs.
<cfif fileExists("/custom/someFile.cfm")>
<cfinclude template="/custom/someFile.cfm" />
<cfelse>
<cfinclude template="someFile.cfm" />
</cfif>
I wanted to create a custom CF tag to boilerplate this as a simple <cf_custominclude template="someFile.cfm" />, however I ran into the fact that custom tags are effectively blackboxes, so they aren't pulling in local variables that exist prior to the start of the tag, and I can't reference any variable that was created as a result of the tag from importing the file.
E.G.
<!--- This is able to use someVar --->
<!--- Pulls in some variable named "steve" --->
<cfinclude template="someFile.cfm" />
<cfdump var="#steve#" /> <!--- This is valid, however... --->
<!--- someVar is undefined for this --->
<!--- Pulls in steve2 --->
<cf_custominclude template="someFile.cfm" />
<cfdump var="#steve2#" /> <!--- This isn't valid as steve2 is undefined. --->
Is there a means around this, or should I utilize some other language feature to accomplish my goal?
Well, I question doing this at all but I know we all get handed code at times we have to deal with and the struggle it is to get people to refactor.
This should do what you are wanting. One important thing to note is that you will need to ensure your custom tag has a closing or it won't work! Just use the simplified closing, so like you had it above:
<cf_custominclude template="someFile.cfm" />
This should do the trick, called it has you had it : custominclude.cfm
<!--- executes at start of tag --->
<cfif thisTag.executionMode eq 'Start'>
<!--- store a list of keys we don't want to copy, prior to including template --->
<cfset thisTag.currentKeys = structKeyList(variables)>
<!--- control var to see if we even should bother copying scopes --->
<cfset thisTag.includedTemplate = false>
<!--- standard include here --->
<cfif fileExists(expandPath(attributes.template))>
<cfinclude template="#attributes.template#">
<!--- set control var / flag to copy scopes at close of tag --->
<cfset thisTag.includedTemplate = true>
</cfif>
</cfif>
<!--- executes at closing of tag --->
<cfif thisTag.executionMode eq 'End'>
<!--- if control var / flag set to copy scopes --->
<cfif thisTag.includedTemplate>
<!--- only copy vars created in the included page --->
<cfloop list="#structKeyList(variables)#" index="var">
<cfif not listFindNoCase(thisTag.currentKeys, var)>
<!--- copy from include into caller scope --->
<cfset caller[var] = variables[var]>
</cfif>
</cfloop>
</cfif>
</cfif>
I tested it and it works fine, should work fine being nested as well. Good luck!
<!--- Pulls in steve2 var from include --->
<cf_custominclude template="someFile.cfm" />
<cfdump var="#steve2#" /> <!--- works! --->
<cfparam name="instance.params.sel_isCriteriaChanged" default="false">
Here instance is a global structure but "sel_isCriteriaChanged" inside that is created using form variable. But in certain form i dont have that variable. It'll be undefined in that case.
So in that case how to set the variable to false as default value.
I am using this variable inside CFC file
If I understand the question correctly you have something like this:
<cfparam name="instance.params.sel_isCriteriaChanged" default="false">
<cfset instance.params = {}>
<cfloop collection="#FORM#" item="key">
<cfset instance.params[key] = FORM[key]>
</cfloop>
but the cfparam gets overwriten here. Just make sure the form value is always defined:
<cfparam name="FORM.sel_isCriteriaChanged" default="false">
If I understand your problem correctly, you might do something like the following:
<cfset instance.params.sel_isCriteriaChanged = structKeyExists(form, "sel_isCriteriaChanged") ? form.sel_isCriteriaChanged : false />
This is shorthand for:
<cfif structKeyExists(form, "sel_isCriteriaChanged")>
<cfset instance.params.sel_isCriteriaChanged = form.sel_isCriteriaChanged />
<cfelse>
<cfset instance.params.sel_isCriteriaChanged = false />
</cfif>
I like the terseness of the ternary operator ? : and I try to avoid using <cfparam> if possible. Hope this helps.
I have a ColdFusion program which needs to switch to another page, but which page depends on a condition. It would be nice to write code such as
<cfif a GT 5>
<cfinclude template = 'pageone.cfm'>
<cfelse>
<cfinclude template = 'pagetwo.cfm'>
</cfif>
The problem is, if I include pageone or pagetwo the final </cfif> disappears from ColdFusion's radar, and I get an error. Can anyone suggest a way to accomplish what I'm trying to do above?
Change your approach to something like this:
<cfset a = 6>
<cfif a GT 5>
<cfset templateTarget = 'pageone.cfm'>
<cfelse>
<cfset templateTarget = 'pageTwo.cfm'>
</cfif>
<cfinclude template = '#templateTarget#'>
With ColdFusion MX7 if we encounter an exception we send an email to the development team containing dumps of the various data scopes including the form structure.
This works great for debugging except in the case of an error when the user logs in. We end up getting the password printed out.
So, the question is, is there a way to modify the CFDUMP file so that it filters the password value out of the form object?
Naturally we could put it in the same code that sends the email, however it would be ideal to put it in the CFDUMP file so that we do not have to worry about it showing up in other spots.
I have located the CFDUMP file and it seems to be binary, so I'm guessing we can't do it.
You can copy the dump.cfm file to dumporiginal.cfm, and then make a new dump.cfm that calls dumporiginal.cfm.
<!---
So that it won't execute twice if you
have a closing slash (<cfdump ... />)
--->
<cfif thisTag.executionMode neq "start">
<cfexit method="exitTag" />
</cfif>
<!---
defaults for optional attributes, taken from the docs
http://livedocs.adobe.com/coldfusion/8/htmldocs/Tags_d-e_08.html
--->
<cfparam name="attributes.expand" default="yes" />
<cfparam name="attributes.format" default="html" />
<cfparam name="attributes.hide" default="all" />
<cfparam name="attributes.keys" default="9999" />
<cfparam name="attributes.label" default="" />
<cfparam name="attributes.metainfo" default="yes" />
<cfparam name="attributes.output" default="browser" />
<cfparam name="attributes.show" default="all" />
<cfparam name="attributes.showUDFs" default="yes" />
<cfparam name="attributes.top" default="9999" />
<!--- Hide the password, but store its value to put it back at the end --->
<cfif isStruct(attributes.var) and structKeyExists(attributes.var, 'password')>
<cfset originalPassword = attributes.var.password />
<cfset attributes.var.password = "{hidden by customized cfdump}"/>
</cfif>
<!---
Call the original cfdump.
Which attributes you pass depends on CF version.
--->
<cfswitch expression="#listFirst(server.coldfusion.productVersion)#">
<cfcase value="6">
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
hide = "#attributes.hide#"
label = "#attributes.label#"
>
</cfcase>
<cfcase value="7">
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
hide = "#attributes.hide#"
label = "#attributes.label#"
top = "#attributes.top#"
>
</cfcase>
<cfdefaultcase>
<cfdumporiginal
var = "#attributes.var#"
expand = "#attributes.expand#"
format = "#attributes.format#"
hide = "#attributes.hide#"
keys = "#attributes.keys#"
label = "#attributes.label#"
metainfo = "#attributes.metainfo#"
output = "#attributes.output#"
show = "#attributes.show#"
showUDFs = "#attributes.showUDFs#"
top = "#attributes.top#"
>
</cfdefaultcase>
</cfswitch>
<!--- Restore the password, in case it's read after cfdump call --->
<cfif isDefined("originalPassword")>
<cfset attributes.var.password = originalPassword />
</cfif>
No, I don't think there is a way to modify <cfdump>'s behavior. I can't be sure, obviously. It's thinkable that such a hack exists, though it's not necessarily recommendable.
Why not go with a simple:
<cftry>
<cfset DoSomethingThatFails()>
<cfcatch>
<cfif StructKeyExists(FORM, "Password")>
<cfset FORM.Password = "***">
</cfif>
<cfdump var="#FORM#">
</cfcatch>
</cftry>
CFDUMP began life as a custom tag (CF_DUMP) way back in the CF5 days. You could always get the code for that custom tag and modify it to your needs and use that instead of the built-in tag.
Is it only the password that is a problem of showing? If so, perhaps the solution is to salt/hash the password? That I think is good practice anyway.
http://blog.mxunit.org/2009/06/look-ma-no-password-secure-hashing-in.html