Problems with setting up a CFIF - coldfusion

<cfoutput query="allOutcomes" maxrows="10">
<div class="galleryOutcome">
<cfset thisPhoto = uploads.listPhotobyOutcomeID(#outcomeID#)>
<h3>#lastname#, #firstname#</h3>
<cfloop query="thisPhoto" >
<cfif isdefined(filename)>
<div class="gallerythumb">
<img src="documents/uploads/PHOTOS/#filename#" alt="#filename#" border="0" width="200"/>
</div>
<cfelse>
<p> NO PHOTOS </p>
</cfif>
</cfloop>
</div><div class="clear"></div><br /><br />
<div onClick="javascript: thumbHide()" id="thumbexpand" style="display:none; left:670px;; height:0px; position:fixed; top:100px;">
</div>
</cfoutput>
I have been trying to make it so that #lastname# and #firstname# do not display if there are no photos associated to them. I tried doing a cfif that checks to see if the filename is defined, but it didn't seem to work. It returns an error saying:
"Parameter 1 of function IsDefined, which is now (filepath to image), must be a syntactically valid variable name. "
Any tips?
Thanks

First, IsDefined expects the name of a variable. When you omit quotes, or use # signs, you are passing in the variable value instead. The correct syntax is:
<cfif IsDefined("variableName")>
However, query columns always exist. So it will not yield the correct result anyway. Instead you should test if the FileExists. If needed, use expandPath to generate an absolute physical path
<cfif FileExists( ExpandPath("/path/to/images/"& thisPhoto.fileName) )>
it exists. do something ...
<cfelse>
no photo
</cfif>
Edit: As Busches mentioned in the comments, generally structKeyExists is preferred over IsDefined because its results are more precise. Some may argue it also has better performance. But in most cases, any differences are negligible. Increased accuracy is the more compelling reason IMO.
<cfif structKeyExists( scopeOrStruct, "variableName")>

isDefined takes the name of the variable as a string, not the variable itself. change
<cfif isdefined(filename)>
to
<cfif isdefined("filename")>

use <cfif len(filename)>
I guess filename is one of the columns? In a query object, null is represented with empty string, so len() would work.

Related

Variable session passes from page to page coldFusion

CFBuilder admin storage
15cdb5dcb6.jpg
Application.cfm
34ed7586e1.jpg
Login.cfm
<cfif not isDefined('FORM.submitButton')>
<cfform name="loginForm" method="post" action="#CGI.SCRIPT_NAME#">
Login:
<cfinput type="text" name="login" required="yes">
Password:
<cfinput type="password" name="password" required="yes">
<br>
<cfinput type="submit" name='submitButton' value="Sign">
<br>
<cfinput type="button" name='registerButton' value="Register">
</cfform>
<cfelse>
<cfquery name='getUser' datasource="dbfortest">
SELECT * FROM usertable WHERE login="#FORM.login#" ;
</cfquery>
<cfif getUser.RecordCount NEQ 0>
<cfif FORM.password eq getUser.password>
<cflock scope="Session" timeout="60" type="exclusive" >
<cfset Session.loggedIn = "yes">
<cfset Session.user = "#FORM.login#">
</cflock>
<cfoutput>#StructKeyList(Session)#</cfoutput>
<cfelse>
Your pass isn't correct.
</cfif>
<cfelse>
There is no user with this name.
</cfif>
</cfif>
part of page when i want to use login including.
<cfif Session.loggedIn eq "no">
<cfinclude template="login.cfm">
</cfif>
<cfif structKeyExists(session, "user")>
<cfoutput>Welcome, #Session.user#.</cfoutput>
</cfif>
<cfoutput>#StructKeyList(Session)#</cfoutput>
Hello everyone, please help me understand these sessions' behavior.
The whole problem consists in attempting to pass variables from one page to another.
So after login i don't see the session.user in session struct.
How can i pass this?
Have already tried different browsers.
#Aquitaine has given you some good information. I just wanted to also point out that another part of your problem is likely that you have set a 10 second life span for your sessions. That's probably not long enough.
In the Application.cfm example that you posted you have this line:
sessiontimeout="#createTimespan(0,0,0,10)#"
The arguments for the CreateTimeSpan function are as follows:
createTimespan(days, hours, minutes, seconds)
As such you are assigning a 10 second lifespan for sessions. Perhaps you meant to set 10 minutes instead of 10 seconds.
To figure out what's going on with the session variables, try putting in some debug code right after your cfset session statements to make sure that they're happening. Maybe <cfdump var="#session#">.
You do not need to cflock your session scope (and have not needed to since CFMX). See Adam Cameron's 2013 post on when to lock scopes
If your debug code runs and you see the session variables, but then they're gone on the next page, that may be an issue with your session storage (which is a different part of cfadmin) or else whatever front-end webserver you're using. Try <cfdump var="#session#"> in onRequestStart in Application.cfc and make sure that JSESSIONID is the same on every request. (or try disabling J2EE session variables in CFADMIN and see if the same problem persists with CFID/CFTOKEN).
If your debug code doesn't run, then you should be seeing one of your error conditions.
For ease-of-reading, be consistent in your casing when refering to scopes, e.g. session not Session. While this kind of thing may not matter functionally, it can get you into trouble with portability when referencing paths or components.
Some other issues:
If you are going to use a boolean value for loggedIn then use a boolean value: true or false or 1 or 0 or (if you must) yes or no but not "yes" which is a string; instead of being able to do if (session.loggedIn) if you will have to do if (session.loggedIn == 'yes') and nobody will be happy.
If this is meant to be working, production site code, at a minimum you need to be using cfqueryparam as you do not ever want to pass unescaped user input directly to a database query.
You might also head over to the CFML slack at cfml.slack.com and ask on #cfml-beginners for some pointers on writing login forms.

Coldfusion how to get function name and line number when application crashed or error

i'm working on my legacy system old code of coldfusion, is there a way i can define cfcatch in application.cfc and catch all errors of my application with
Function name
Query name
Line Number of code
Template Name
To debug fast rather then writing everywhere in code.
application developer did not catch any error anywhere in code.i did insert cfcatch in code some of the places but still lot more to do, and because of production i don't want to modify so much of code.
im inserting cfcatch in databse and sending email to development team. because system is in production.
You can use the cferror tag, or onError to direct all errors to a given page/function.
If you use cferror, the exception will be passed in the error variable. If you use OnError, it's a parameter.
To help you along, my own error emails include the following. You will notice that we have special handling to help point out places where a blank may have been passed into a sql integer field, which happens more often than I'd like to admit.
An error occurred: http://#cgi.server_name##cgi.script_name#?#cgi.query_string#<br />
Time: #dateFormat(now(), "short")# #timeFormat(now(), "short")#<br />
<!--- Smarter error catching for form fields --->
<cfif (error.message contains "Invalid data '' for CFSQLTYPE CF_SQL_INTEGER") and isdefined("form")>
<!--- This stores a list of the Id fields --->
<cfloop collection="#form#" item="thisField">
<!--- Get the last two characters of the field name --->
<cfset lastTwoChars = right(thisField, 2)>
<!--- Get the value of the field --->
<cfset thisFieldValue = evaluate('form.#thisField#')>
<!--- Check to see if this is an Id field and if it's value is blank. --->
<cfif lastTwoChars eq 'Id' and thisFieldValue eq ''>
<h3 style="font-weight: bold; color: red">#thisField# is blank and it's possibly an integer field.</h3>
</cfif>
</cfloop>
</cfif>
<cfdump var="#error#" label="Error">
<br/>
<cfdump var="#form#" label="Form">
<br/>
<cfdump var="#url#" label="URL">
<br/>
<cfdump var="#session#" label="session">

Display a link only if no link is present using ColdFusion?

So the announcement functionality on our site displays a "read more" link by default using the following code (in part):
<cfif announcement.recordCount gt 0>
<cfloop query="announcement">
<cfoutput>
<td colspan="2"><span class="left">#teaser_text# Read more »
</cfoutput>
</cfloop>
(Note, there is a cfquery statement prior to that, which I excluded for brevity in the code)
What I'm trying to do here is get the "Read More" link to show after the #teaser_text# only if no link is contained within #teaser_text#, so that I can manually add links in if needed and remove the automatically generated link.
Any thoughts on a cfif statement that would do this?
Thanks.
EDIT: To clarify, I want to remove "Read more" if ANY link is found within teaser_text.
To only show the read more link if no hyperlink is found within teaser_text, this check is likely to be good enough:
<cfif NOT refindNoCase('<a\s[^>]*?\bhref\s*=',teaser_text) >
Read more »
</cfif>
If you want to check for URLs, not for hyperlinks, you need to get more fancy.
You also need to remember that this is treating teaser_text as text (not as HTML), so commenting out a link will not prevent it from being found (if that matters, you need to investigate HTML DOM parsers; and there aren't any for CF so you'd need to look at the Java ones).
This should work:
<cfif findnocase('http://', teaser_text) eq 0>
Read more »
</cfif>
If you are placing the links in manually just change the first parameter of the findnocase() function [i.e. htp/https] or use a regex to figure out if it is a url [via: refindnocse() ]
-sean
Something like this should do what you want
<cfif announcement.recordCount gt 0>
<cfloop query="announcement">
<cfif findnocase("href",anouncement.teaser_text) >
#anouncement.teaser_text#
<cfelse>
<a href="/announcements/?id=#announcement.id#" > #anouncement.teaser_text# Read more </a>
</cfif>
</cfloop>
</cfif>

Coldfusion #iif and sessions

I am buliting an add/edit user form, when the page is accessed there is an if statement which detects if we are editing a current user or addindg a new user by a url id
<cfif isDefined('URL.id')>
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=#URL.id#
</cfquery>
<cfset #name#=#getSquadMember.athlete_name# />
<cfelse>
<cfset SESSION.squad = structNew()>
<cfparam name="SESSION.squad.name" default="">
</cfif>
That is fine but the problem comes in evaluting if the session or value exists, I get an error
<cfinput class="text" name="name" type="text" id="name" value ="#IIf(IsDefined('name'), DE('#name#'), DE("#SESSION.squad.name#"))#" required="yes" />
Element squad.name is undefined in session. Why is it eveluating if session exists when the first condition is met?
Thanks,
R.
First up - if you can possibly avoid using iif(), then do so. It causes many more headaches than it has ever solved...
However, note the following from the ColdFusion documentation on iif():
If a variable is undefined, ColdFusion throws an error when it processes this function. The following example shows this problem:
#IIf(IsDefined("Form.Deliver"), DE(Form.Deliver), DE("no"))# This returns "Error resolving parameter FORM.DELIVER".
To avoid this problem, use the DE and Evaluate functions in code such as the following:
#IIf(IsDefined("Form.Deliver"), Evaluate(DE("Form.Deliver")), DE("no"))# This returns "no"; ColdFusion does not throw an error.
Or, if you're on CF9 (which supports ternary operators):
<cfinput class="text" name="name" type="text" id="name" value ="#IsDefined('name') ? name : SESSION.squad.name#" required="yes" />
Is there a reason as to why you need to have two different variable names for the same item? Could you just do:
<cfif isDefined('URL.id')>
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=<cfqueryparam value="#URL.id#" cfsqltype="CF_SQL_INTEGER" />
</cfquery>
<cfset name= getSquadMember.athlete_name />
<cfelse>
<cfset squad = structNew()>
<cfset name = "" />
</cfif>
<input type="text" name="name" id="name=" value="#name#" />
Which would then in turn remove the need for the iff statement
HTH
J
Couple of issues:
1)
<cfquery name="getSquadMember" datasource="#application.datasource#">
SELECT * from squad WHERE id=#URL.id#
</cfquery>
You're asking for a SQL injection here. Use cfqueryparam
2)
<cfset #name#=#getSquadMember.athlete_name# />
It's your second post where I notice weird use of #
It should be as Jason wrote it:
<cfset name = getSquadMember.athlete_name />
3) As for your question:
<cfinput class="text" name="name" type="text" id="name" value="#IIf(IsDefined('name'), DE('#name#'), DE("#SESSION.squad.name#"))#" required="yes" />
This way is not really readable.
Set some variable for the value first.
Second thing - you don't need to put the variables in DE like this, this will do:
DE(name)
And as you're using cfinput the whole thing probably needs to be correct. And another issue - you don't really need to use cfinput there. Normal HTML input will do and save you some CF parsing.
The problem you are seeing is that IIF() has to evaluate all parts of the statement.
You can't really use it for checking if a variable is defined or not as it will always try to evaluate the contents of both the true and false responses.
As long as you bear this in mind when using IIF() there's no problem with using it. Just keep it simple and don't try to use it when a variable might not exist.
I was going to point out the other issues with your code, but the other answers have already done a good job of covering these.

long/multiline content through cfset in Coldfusion

is there a way to set a variable with cfset that acts more like a cdata tag
or is there another way of having a page with some basic variables set and a couple of longer variables set for the main content;
ie.
<cfoutput>
<CFSET page_title = "TITLE">
<CFSET examplevariable = "ABC">
<CFSET content>
<!--something like this-->
<div>
bunch of content without any cf tags
</div>
</CFSET>
<cfinclude template="include/layout.cfm">
</cfoutput>
<cfsavecontent variable="header">
<cfoutput>
I can be HTML, javascript anything text.
remember to escape pound sysmbols ie: ##FF0000 instead of #FF0000
I can even <cfinclude template="headerpage.cfm"> and will be stored in variable
called header
</cfoutput>
</cfsavecontent>
<cfoutput>#header#</cfoutput>