What is wrong with this CFIF structure? - coldfusion

I have the following at the top of a page...
<cfif isdefined("session.loggedin") and session.loggedin eq true>
<cfinclude template="includeUserInfo.cfm">
<cfinclude template="includeSideBar.cfm">
<cfelse>
<cflocation url="../sign-in.cfm">
</cfif>
When I execute the page and session.loggedin DOES equal true it executes as expected and adds the included files.
If I hit the page without logging in - I'm not being redirected to the sign in page - I'm just getting a completely blank page - zero html in the view source.
Session management is enabled in my application.cfc file
I'm not sure if what I am doing is wrong - appreciate any advice.

OK - so (as is often the case) I had missed the underlying cause of the problem - and while focussing on the imagined problem with the CFIF statement itself, missed the small cfinvoke that was before it in the code. That was trying to execute a database lookup, but failing when a user was not logged in.
swapping these around and making sure the block above is before everything else on the page has done the trick. Go me. Thanks everyone for the input.

Related

how can I use cfdirectory to make a list of documents downloadable using ColdFusion/Lucee?

In my Application.cfc, I setup a mapping
this.mappings["/downloads"]="J:\Downloads\documents";
In my template, I have
<cfdirectory action="list" directory="#expandpath("/downloads")#" filter="*.zip|*.docx" name="downloads" recurse="yes">
<!--- <cfdump var="#expandpath("/software")#"> --->
<cfdump var="#downloads#">
<ul>
<cfoutput query="#downloads#">
<li>#downloads.name#</li>
</cfoutput>
</ul>
I'm trying to make the documents downloadable but when the link is clicked, nothing is happening which makes me think my links are not correct however when I mouse over the link, I see the full path which is correct.
What am I missing to make the list of documents clickable?
Here is the URL displayed when mouseover the 3rd document for example.
Since the files are outside of your webroot you will need to have ColdFusion read the file and send it back to the browser.
You will need to create a page, like download.cfm, that can accept a URL parameter to know which file to access. Once you have selected the file you can use something like the following to stream the file.
<cfheader name="Content-disposition" value="attachment;filename=#datafile#">
<cfcontent file="#datafile#" type="application/pdf">
The above code was pulled from https://www.raymondcamden.com/2006/03/10/Ask-a-Jedi-Using-ColdFusion-to-serve-files
WARNING:
Reading URL parameters in this way and giving people access to the filesystem is extremely unsafe. Safer alternatives should be considered before moving something like this into a production environment.
All I needed to do for this exercise is to setup a mapping in my Application.cfc. As others have stated, there is zero security here but for the purpose of this exercise of understanding virtual directories (IIS) and aliases (CommandBox), this is sufficient.
this.mappings["/guides"]="J:\guides";
Then I can use cfdirectory to build my query object
<cfdirectory action="list" directory="j:\guides" recurse="false" name="nameofqry" type="file" sort="datelastmodified desc" filter="*.docx">
Next, perform a cfoutput using my alias as the a href link
<cfoutput query="nameofqry" maxrows="40">
<li>#nameofqry.name#</li>
</cfoutput>

Session variable not found

for a long period of time I have an issue with Session variables. I'm looking for some pointers or directions to address this problem. I try to explain what is happening and I understand that the information provided isn't sufficient to understand what is happening, but I'm trying to solve this and it's driving me nuts :-)
I have several Lucee webapplications (Lucee: 5.3.7.48) which are also available as Cordova app. Error messages are sent to my by e-mail. On a daily bases I receive about 100 messages that the session variable can not be found.
[APP] is a session variable, set in the file index.cfm.
<cfparam name="SESSION.auth.app" default="">
In line 592 there is something like
<cfif session.auth.app is 1>do something</cfif>
I don't want to focus on line 592, the real problem is that the session variable is/gets lost. What happens next is that the user is redirect to the login page (login.cfm), because the session is lost and then the problem repeats, it's a kind of loop. The application has a save username/password option.
This all happens when the application is running in the background, like the Cordova app running in the background. I know this because I reached out to a user when receiving 20 error messages, and he told me that I wasn't using the application at the time of the error messages.
In conclusion I measure a user when he is using the login.cfm page. As you van see in the image there is a peak in usage on March 16th, which has to do with the problem described.
I understand that I provided not much useful information to go on, but can someone give me some directions how to approach this problem?
UPDATE April 14th
I have changed the way session vars are set and followed the suggestions in the reactions.
In the application.cfc I have add:
<cffunction name="onSessionStart" access="public" returntype="void" output="false" hint="I fire when a new session begins.">
<cfset SessionRotate()>
<cfset SESSION.app = ''>
<cfset SESSION.device = ''>
<cfset SESSION.app_file_url = 'window.open'>
</cffunction>
Restarted Lucee just the be sure. But still the same error messages, APP doesn't exist. After some additional searching I found: https://www.bennadel.com/blog/1535-coldfusion-session-is-always-created-even-if-onsessionstart-fails.htm
Could this be a Lucee bug? Are do you have more suggestions to try?
In your onSessionStart function, Can you please change it to this?
<cfset session.auth = {}>
<cfset session.auth.app = ''>
I see you are checking <cfif session.auth.app is 1>do something</cfif> which should have the session.auth defined for it to work.
I hope the above helps.
Also, I'd be interested in knowing what are you dumping on the screen?

How do I locate a custom tag instantiation in a coldFusion App

I am migrating a very old app (currently running in CF8) to Lucee. But I am running into a problem with what appears to be a custom tag of some sort.
I have tried to make sure that all the virtual directories are the same in IIS for both the old and the new installs. And made sure the mapping and custom tag paths in both the CFIDE and the Lucee Admin are the same.
But I am getting this error. And can't figure out how this cflink is being instantiated.
I have found the location of the erroring code on line 300 the utils.cfc file
I haven't used custom tags in a long time but thought they were generally called with an underscore and the code should like more like <cf_link pageid="#LinkPageID#" Init="start"> if this was being called as a custom tag.
If I go the the current CF server that is running this app I can find that a cfclass files HAS been created
From a file called cflink.cfm in a directory called "tags" even though there seems to be no mapping for the "tags" directory nor is is listed under "custom tags paths" in the administrator.
This App was start in 2003 and as you can imagine has grown into a mis-match of spaghetti code and no one from the beginning is around to ask how this tag is instantiated.
Does anyone with experience in legacy code has any other ideas where I should be looking to try to get this to work? The currently has only a production environment and if I can get it to work on Lucee it will not only be a dev environment that hasn't existed here in 10 years but will be a great way for me to be able to continue showcasing Lucee as a great CFML engine
Adding addition info
Leigh had asked if the init might be a jar reference but in the cflink.cfm file I see this code:
<cfif Attributes.Init IS "start">
<cfset Request.PageID = Attributes.PageID>
<cfset Request.Page_Width = Variables.qParentInfo.Page_Width>
<cfset Request.Page_Height = Variables.qParentInfo.Page_Height>
<cfset Request.Page_TypeID = Variables.qParentInfo.Page_TypeID>
<cfset Request.AddPath = "">
<cfif IsDefined("Attributes.Anchor")>
<cfset Request.Anchor = Attributes.Anchor>
<cfelse>
<cfset Request.Anchor = "">
</cfif>
<cfset Request.IsInternalLink = false>
<cfexit method="EXITTAG">
</cfif>
There are also references to cflink in the code inside tags\cflink.cfm
<cfif Len(Variables.qParentInfo.ParentID) GT 0>
<!--- Add the page title to the end of the path --->
<cfset Request.AddPath = ReplaceNoCase(Variables.qParentInfo.Nav_Title," ","_","ALL") & "/" & Request.AddPath>
<cflink init="working" pageid="#Variables.qParentInfo.ParentID#" popcode="#Attributes.popcode#">
<cfelse> ......</cfif>
Although this may be recursion given it was written in 2004 I kind of doubt it
Adding screen shots of searches
If anyone else runs into this. In CF8, and presuming earlier versions, you could put a cfm file into the ColdFusion8\wwwroot\WEB-INF\cftags Directory and that file in this case ColdFusion8\wwwroot\WEB-INF\cftags\link.cfm Then acts as any other cftag.
I was able to find the person who originally build this app in 2004 and he told me that they did it this way to avoid typing the underscore that they would have typed if they'd done it as a custom tag.
I kind of get it since this tag is used everywhere in the app, literally hundreds of times. Bit boy with a bitch to find.
Now all I have to do is figure out how to move it to the Lucee world in a similar fashion. So it instanciates the same way.
Thanks #Leigh for all your help, you are always amazing!
Adding more information
if there are files in the WEB-INF\lucee\library\tag the corresponding Lucee directory is WEB-INF\lucee\library\tag. These files are read on load and then able to be used as any other cf tag.
For example if you have file WEB-INF\lucee\library\tag\link.cfm it can be called by `cflink'.
Seems like a cool idea but a bit of a bitch for someone to find 10 years after the fact

How to properly use Coldfusion's FileExist() method?

I don't use coldfusion much at all, I'm needed to patch up some code though. Basically I'm trying to check and see if a file I uploaded exist and if it does exist, increment a variable by 1. Then repeat untill I get a unique file name. For whatever reason I can't figure out the proper way to use FileExist(). Some forums suggest using it with len() but those are from 2006 and when I do that it seems to always come out true. Also, when I look at http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c66.html it says it returns either Yes or No. I tried to check against the result various ways, but no luck.
This is the portion of code I have which I am dealing with. The application.filepath is just a variable in my application file which store the expandpath().
<cffile action="upload" destination="#Application.filePath#ListingsGallery/" filefield="iconImage" nameconflict="makeunique">
<cfset iconPlace = #cffile.serverfile#>
<cfset myExt = listLast(iconPlace,".")>
<cfset i = 1 >
<cfset myVar = false>
<cfloop condition="myVar EQ false">
<cfset newIconName = "iconPhoto" & i &"."& myExt>
<cfset iconName = Application.filePath & "ListingsGallery/" & #newIconName#>
<cfoutput>#iconName#</cfoutput><br />//just checking to see if it is the correct path, it is.
<cfif FileExists(iconName) EQ 'Yes'>
<cfoutput>#myVar#</cfoutput> //checking the value, it never hits here.
<cfelse>
<cfoutput>#myVar#</cfoutput><br /> //checking the value, it always hits here.
<cfset myVar = true>
<cfoutput>#myVar#</cfoutput> //Again check the value.
</cfif>
<cfset i++>
</cfloop>
<cffile action="rename" source="#Application.filePath#ListingsGallery/#iconPlace#" destination="#Application.filePath#ListingsGallery/#newIconName#">
The absolute path on a unix server is something like, /var/www/website folder name/ etc....
Correct? That's the absolute server path, the coldfusion docs seem to specify at least a microsoft absolute server path so I'm assuming this is what is needed.
Edit---------------------------
PS: I can' only give one of you credit, so I gave it to Kruger since he came a minute earlier.
lol...
FileExists() returns a boolean value. This should work fine now that the typo has been fixed:
<cfif fileExists(TheFile)>
// do this
<cfelse>
// do that
</cfif>
Assuming your application.Filepath is the correct file path you are on the right track. It looks like your upload directory might be beneath the web root - considering moving it outside the web root for security. Take a look at #expandPath('.')# as a way of creating guaranteed file paths without typos :) Also makes your code more portable.
To my eye the code above would work. FYI - you don't need "EQ 'YES'. You are fine to just do:
<Cfif FileExists(iconName)>...
You could also do
condition="NOT myVar">
There are several ways to handle logic code in CF.
If your fileExists() never hits take a closer look at your rename. Are you throwing an eror?
I can't add notes to answers yet, but I wanted to let the OP know that CF is typeless when it comes to boolean evaluations in functions. 0 is the same as "no" is the same as "false", whereas any positive number is the same as "yes" is the same as "true".
Its great to have back-end security, but this should have been handled on the front-end so you never get values you don't want. The new HTML5 input patterns would prevent this from ever being submitted, so you wouldn't have to fix this on the back end.
http://www.w3schools.com/tags/att_input_pattern.asp

ColdFusion security by checking ARGUMENTS.TargetPage in Application.onRequestStart?

I have a ColdFusion app in which I wish to restrict access to certain pages, based on some criteria. I am currently doing it like this, in Application.cfc:
<cffunction name="OnRequestStart" access="public" returntype="boolean" output="true">
<cfargument name="TargetPage" type="string" required="true" />
<cfif not SESSION.isAdmin and REFindNoCase("/admin",ARGUMENTS.TargetPage) >
<!--- Deny non-admin access to admin pages. --->
<cfinclude template="/notauth.cfm">
<cfreturn false />
</cfif>
<cfreturn true />
</cffunction>
My main concern is: How vulnerable is the general approach of checking TargetPage against a regex, and are there ways to improve the security of this design? Specifically, I'm concerned about avoiding "canonical representation vulnerabilities." See here.
For example, using just a REFind instead of REFindNoCase would let people slide right on through if they went to "/ADMIN/". Are there are other things to watch out for here?
I know there are other designs, like using another Application.cfc in a subfolder, or doing checks right in the page code. But I like the idea of having all my security code in one place. So please only suggest those in your answer if there's no way to do the above securely, or if it's just really a bad idea for some reason. Thanks.
I'm sure there are reams of this stuff on the internets but here is my take on it :)
They way I would solve your specific example is to maintain a database list of scripts that are restricted (a blacklist) unless you are a member of a certain group (i.e. you are an admin).
You can make this as complicated as you wish but for a simple start you could compare the full script name (CGI.SCRIPT_NAME) to a query of queries representing blacklisted pages you store in the APPLICATION scope that you loaded in onApplicationStart() called qRestrictedList.
So in onRequestStart you could do the following:
<cfquery name="qThisPageRestricted" dbtype="query">
SELECT * FROM qRestrictedList
WHERE ScriptName = '#CGI.SCRIPT_NAME#'
</cfquery>
<cfif qThisPageRestricted.recordCount and not SESSION.isAdmin>
<cfinclude template="/notauth.cfm">
<cfreturn false />
</cfif>
Even better, you can expand on this at a later date by wrapping all this in a 'authentication' CFC and creating user groups and levels, i.e. move your logic out of onRequestStart() and encapsulate it.
But as a start, storing the data in the database might be a more maintainable way for you to get this done and provide a better foundation for future changes to how your authentication works.
I hope this helps.
It may worth to make regex a bit stricter:
REFindNoCase("\/admin\/([A-Za-z_]+)\.cfm", ARGUMENTS.thePage)
A better approach would be to put an application.cfc in the /admin directory that controls access (maybe based on a SESSION variable set through logging in as an admin), and have that "child" application.cfc reference the parent one if necessary.
See this question for an example on how to do this: Extending application.cfc in a subdirectory