Relative File Paths Work In A ColdFusion File System

Posted July 16, 2012 at 9:37 AM by Ben Nadel

Tags: ColdFusion

For years, I've been using regular expressions as a means to traverse file paths in my ColdFusion applications. By chopping-off the last directory "pattern" in a file path, I was able to move up into the parent directory:

  • <!--- Get the current directory. --->
  • <cfset currentDirectory = getDirectoryFromPath( getCurrentTemplatePath() ) />
  •  
  • <!---
  • Get parent directory by chopping off the last directory of the
  • current directory path: /(xxxxxxxx/)
  • --->
  • <cfset parentDirectory = reReplace(
  • currentDirectory,
  • "[^/]+/$",
  • "",
  • "one"
  • ) />
  •  
  • <!--- If the Hello file exists, execute it. --->
  • <cfif fileExists( parentDirectory & "relative_paths/subfolder/hello.cfm" )>
  •  
  • <cfinclude template="./subfolder/hello.cfm" />
  •  
  • </cfif>

Here, you can see that I am using the reReplace() method to move up the currentDirectory path in order to obtain the parentDirectory path. Then, I am using this parentDirectory path in a fileExists() call. This code successfully runs and outputs the following message:

Hello from the SubFolder!

This works. But, it lacks clarity and readability. While the intent may be evident from my variable name choices, the implementation may remain a mystery to anyone who's not comfortable with regular expressions.

In the last few months, I've abandoned this convoluted approach to path traversal and replaced it with relative-path constructs in my ColdFusion path logic:

  • <!--- Get the current directory. --->
  • <cfset currentDirectory = getDirectoryFromPath( getCurrentTemplatePath() ) />
  •  
  • <!--- Get the parent directory using relative pathing. --->
  • <cfset parentDirectory = (currentDirectory & "../") />
  •  
  • <!--- If the Hello file exists, execute it. --->
  • <cfif fileExists( parentDirectory & "relative_paths/subfolder/hello.cfm" )>
  •  
  • <cfinclude template="./subfolder/hello.cfm" />
  •  
  • </cfif>

Here, rather than chopping off the last directory, I am simply adding the relative-path construct, "../", to my currentDirectory value. And, when I run this code, I get the following output:

Hello from the SubFolder!

Not only does this work, it's significantly more intuitive than the regular-expression-based approach.

I used to dislike the idea of having "../" constructs in my ColdFusion file paths. But, this fear was emotional. For some reason, it felt dirty; like there was "clean up" left to be done on the file path and I wasn't doing it. But, I have since overcome this emotional limitation and started using the easier, more intuitive, more maintainable notation in my ColdFusion file paths.

A Note On Security

Using relative-file-path constructs can be dangerous if you're letting your uses define or manipulate paths. This is why (I believe) "../" constructs are disabled, by default, in ASP Classic applications. If you are using "../" file paths as part of your internal configuration, however, there is absolutely no security exposure.




Reader Comments

Jul 16, 2012 at 12:42 PM // reply »
3 Comments

I've always found ColdFusion's lists (delimited with "/") to be an elegant way of traversing directories. (Though it doesn't fair as well with this example.)

  • <cfset parentDirectory = ListDeleteAt(currentDirectory, ListLen(currentDirectory, "/"), "/") />

That said, I might just like it because I have a few list utility routines to help me out here, and could write this as

  • <cfset parentDirectory = ListDrop(currentDirectory, 1, "/") />

(where ListDrop drops the last n elements of a list, n being it's second argument).

But at that point I might as well write my own set of directory traversal functions as well...


Jul 16, 2012 at 2:01 PM // reply »
5 Comments

After I spent too much time with traversing file paths, supporting win (\) + lin (/) servers, I realized that actually I didn't want to traverse paths.

What I wanted is to hardcode filepaths in a platform independend way, so I came up with the idea of project relative paths. My project root is where the Eclipse .project file resides.

Instead of traversing the code looks like this:

  • if( fileExists( Path.getProject("/cache/myFile.ini") ) ){...}

As I code all that paths in a project fully qualified way, it is possible to use search & replace on refactorings.

The Path.cfc starts with:

  • relativeProjectPathOfThisFileRegEx = "project[/\\]path[/\\]of[/\\]this[/\\]Path.cfc";
  • project = reReplace(getCurrentTemplatePath(), relativeProjectPathOfThisFileRegEx, "");

and all path methods are build on top of that.

This is from the comments: The ColdFusion function expandPath() is usefull, but not reliable with virtual mappings, defined in IIS or Apache and also not reliable in environments with path rewriting (my experience, not documented). The functions getCurrentTemplatePath() and getBaseTemplatePath() are usefull for file operations relative to the current location or the webroot. Still, this class provides the easiest way, to cope with any system paths inside the project root.


Jul 16, 2012 at 2:08 PM // reply »
11,246 Comments

@Thom,

I've also played with the list-based usage as well. The one thing that always bothered me was having to determine the length of the list - the listDrop() method would be nice for that (or rather, for not caring what the length is).

@Walter,

I think I used to use a similar approach where I used a Config.cfc instead of a Path.cfc; but then, inside the Path.cfc, I usually had some branch-logic for which server I was on (ex. Live vs Dev).

Now, I tend to just put all my path calculations inside my onApplicationStart() event handler. Luckily, I believe the path-support has gotten much stronger in the last few releases of ColdFusion (in terms of cross-OS path separators).


Jul 16, 2012 at 2:39 PM // reply »
5 Comments

Just curious, do you set per application mappings or customtag paths in the Application.cfc, somehow based on that path calculations in the onApplicationStart? Sorry, a little off topic.


Jul 31, 2012 at 9:34 AM // reply »
11,246 Comments

@Walter,

I tend to set up per-app mappings and tag paths (though less tag paths these days) in my Application.cfc pseudo constructor. Typically, I'll set up some sort of "root" directory property and then build off that:

  • <cfcomponent>
  •  
  • <cfset this.rootDir = getDirectoryFromPath( getCurrentTemplatePath() ) />
  •  
  • <cfset this.mappings[ "/com" ] = (this.rootDir & "com/") />
  •  
  • </cfcomponent>

... like that.

You can't set up per-app mappings in the onApplicationStart() as this is already *too late* for those mappings to take effect. They have to be calculated and defined in the pseudo-constructor.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 25, 2013 at 10:01 PM
My Experience With AngularJS - The Super-heroic JavaScript MVW Framework
@Avi, Really glad to help! @Jaredwilli, I'm finding a this image hits home with a lot of people :) Hopefully we can all work through the rough patches together! @Prateek, AngularJS has error ... read »
May 25, 2013 at 9:53 PM
Nested Views, Routing, And Deep Linking With AngularJS
@Mrsean2k, I'm glad I could help! I haven't been able to keep up with the ui-router stuff. I keep saying that I'll carve out time, but I just haven't gotten to it :( ... read »
May 25, 2013 at 9:49 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, Thanks for the book recommendations. I am looking them up right now. I can see that Object Thinking is available for the Kindle App - sweet! Also, I just recently heard Martin Fowler on the ... read »
May 25, 2013 at 9:41 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
@Chris, I'm super excited to hear that my posts are helpful. I am also loving AngularJS; but, it definitely has some caveats and some odd behaviors and some things that just don't seem to "wor ... read »
May 25, 2013 at 9:36 PM
Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion
@Adam, @Jason, After reading these comments, I double-checked my latest implementation and I am happy to report that I am using listFirst() and listRest(). ... read »
May 25, 2013 at 9:31 PM
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
@Daxesh, I am not sure I understand the question about the current node. If you already have a reference to the current node, why would you need to query for it? As for parent node, I believe that ... read »
May 25, 2013 at 10:08 AM
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
@Ben, my question is that i want the current node with its tag and its parent node. i just want only that data. So, give me the solution for that. and remember solution is working on " xpath 1.0 ... read »
May 25, 2013 at 10:01 AM
Using "//" And ".//" Expressions In XPath XML Search Directives In ColdFusion
hey ben, i want get my current node tag and also want the root node tag withing. So, how can i fix it.. ! ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools