Skip to main content
June 19, 2006
Answered

application.cfm login and file access

  • June 19, 2006
  • 4 replies
  • 3162 views
Hi,

I am using an application.cfm login for my application. I have just found out that uploaded files (ppt, doc, pdf, xls, etc) can be accessed by just using the complete URL to the file and the user is not directed to login, even though the files are within an application.cfm protected directory.

For example,

www.domain.com/login/ returns the user to the login page
www.domain.com/login/resources/ returns the user to the login page
www.domain.com/login/resources/thisFile.pdf will load the pdf file and not return the user to the login page.

How do I overcome this?

Thanks,

jo
This topic has been closed for replies.
Correct answer
And I, too, apologize for complicating all of this by changing the parameter name of my pasted code.

Funny, I was looking in the variables scoping section of the livedocs, not the <cffile> tag. Good find, BKBK. The fact that a java method is being called must confuse CF a bit when overriding a built-in struct variable, FILE in this case, with a string. Strange.

Hi Kronin, BKBK and Paul,

Thanks for your comments!

This is working like a dream...

<cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
<cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor(filename)>

<!--- if the file extension isn't found in JAVA_HOME/jre/lib/content-types.properties,
then myMimeType isn't defined. Set it to text/plain --->
<cfif not isDefined("myMimeType")><cfset myMimeType = "text/plain"></cfif>

<cfheader name="Content-Disposition" value='inline; filename="#fileName#"'>
<cfcontent type="#myMimeType#" deletefile="No" file="#APPLICATION.ResourcesRoot#/#fileName#">

Thanks once again!

Kind regards,

jo

4 replies

BKBK
Community Expert
Community Expert
June 20, 2006
Did you even look at the Javadocs?
I did.

URLConnection.getFileNameMap is a static function that returns a FileNameMap
True.

FileNameMap.getContentTypeFor(String fileName) gets the MIME type for the specified filename
True again. However, I suspect Coldfusion will interprete the combination,

<cfset file="d:\fileStore\pdf\testFile.pdf">
<cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
<cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor(file)>


differently. As Ojoonline00 has pointed out, Coldfusion will tell you "The selected method getContentTypeFor was not found." However, the error should disappear when you instead do

<cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
<cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor("d:\fileStore\pdf\testFile.pdf")>


In any case, it is sufficient for Ojoonline00 to keep the files out of the webroot and to use <cfheader> and <cfcontent>.


Participating Frequently
June 20, 2006
Change all references to "file" to something else, like "filename", and it will work.

My mistake. In my code, I had the param named "filename". I stupidly changed it to "file" in the code I posted.

Since I had never prefixed variables with FILE. before, I wasn't aware that it was a reserved word. If you put this line in an otherwise blank template, you'll get returned an empty struct:
<cfdump var="#file#">

I didn't know that. It's listed in the Macromedia ColdFusion MX Web Application Construction Kit book, page 167, as a variable scope, but nowhere is it in the online docs (at least that I could find).

I use these lines in my code and they work perfectly. I stupidly changed "filename" to "file" in the code I posted originally...
<cfset filename="testFile.pdf">
<cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
<cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor(filename)>
BKBK
Community Expert
Community Expert
June 20, 2006
Change all references to "file" to something else, like "filename", and it will work.
Indeed. The mind boggles. Unlike you, I have used file as a convenient variable name here and there in my applications. Never any problems.

I didn't know that. It's listed in the Macromedia ColdFusion MX Web Application Construction Kit book, page 167, as a variable scope, but nowhere is it in the online docs (at least that I could find).
According to the cffile livedocs, the use of file as a system structure is deprecated. So, it is very likely that this is caused by some unresolved throwback to the old version. That would make getContentTypeFor(file) an overloaded method, as it is now reading a structure, hence not a declared method of the interface. That fits well as an explanation of the error message.

If so, then I owe you an apology. In this scenario, my assumption that the variable name file made Coldfusion to cast a class or interface differently is wrong.


BKBK
Community Expert
Community Expert
June 20, 2006
> I am still getting this error though: The selected method getContentTypeFor was not found.

A missing URL object as argument or missing call to openConnection(), and URLConnection.getFileNameMap() being a static FileNameMap interface are possible complications.

> Anyways, I use a shared host and I've finally found the setting to make the directory
> inaccessible by URL. That bit is ok.


Then it is sufficient for you to do

<cfheader name="Content-Disposition" value="attachment; filename=testFile.pdf">
<cfcontent type="application/pdf" file="d:\fileStore\pdf\testFile.pdf" deletefile="no">

Substitute inline for attachment to also enable the user to open the document in the browser.

Participating Frequently
June 20, 2006
As PaulH asked, what's in the "file" variable that you're passing to that java call?

Edit: All I pass to that call in my code is the filename. For example, "myfile.ppt"

Since you're wanting to use this for .ppt, .xls, .pdf, .doc, etc, then what BKBK posted isn't sufficient. That's only sufficient for .pdf files. That's why I have all that additional code calling out to java functions, to figure out the mime type of each file before serving it via cfcontent.
BKBK
Community Expert
Community Expert
June 20, 2006
That's why I have all that additional code calling out to a java library, to figure out the mime type of each file before serving it via cfcontent.

Without the additional Java code, the code

<cfheader name="Content-Disposition" value="inline; filename=testFile.ppt">
<cfcontent type="application/vnd.ms-powerpoint" file="F:\fileStore\testFile.ppt" deletefile="no">

opens the Powerpoint file in the browser, and

<cfheader name="Content-Disposition" value="attachment; filename=testFile.ppt">
<cfcontent type="application/vnd.ms-powerpoint" file="F:\fileStore\testFile.ppt" deletefile="no">

makes the browser show me a dialog box to enable me download the file. The test also succeeds with testFile.xls(type="application/vnd.ms-excel") and with testFile.doc (type="application/vnd.msword").

BKBK
Community Expert
Community Expert
June 19, 2006
How do I overcome this?
Remove the files from the web root. That will compel you to offer them through a cfm page, using <cfheader> and <cfcontent>.






June 20, 2006
Hi,

Well, I feel like a bit of a dilly as I've found out that Google has picked up these files that were supposed to be password protected... little did I realise that they weren't protected by my application.cfm login.

Anyways, I use a shared host and I've finally found the setting to make the directory inaccessible by URL. That bit is ok.

I am still getting this error though:

The selected method getContentTypeFor was not found.
Either there are no methods with the specified method name and argument types, or the method getContentTypeFor is overloaded with arguments types that ColdFusion can't decipher reliably. If this is a Java object and you verified that the method exists, you may need to use the javacast function to reduce ambiguity.

The error occurred in D:\Inetpub\mySite\login\resources\getFile.cfm: line 9

7 : --->
8 : <cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
9 : <cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor(file)>
10 :
11 : <!--- if the file extension isn't found in JAVA_HOME/jre/lib/content-types.properties,

I've set <cfset APPLICATION.ResourcesRoot = "D:\inetpub\mySite\login\resources\">
and ColdFusion MX is the version the site is running. I'm not sure what JDK is?

thanks :-)

jo

Participating Frequently
June 19, 2006
This is expected behavior. Application.cfm is only used on requests for .cfm files.

You can make all requests go through a cfm file, thereby utilizing your Application.cfm security, by using <cfcontent>

Make a file, called something like "getFile.cfm" or similar, and place it in your resources folder. Pass it the filename you want, like http://www.mydomain.com/login/resources/getFile.cfm?file=blah.pdf

You'll need to set APPLICATION.ResourcesRoot to the full filesystem path to the resources directory.

== getFile.cfm ==
<cfparam name="file">

<!---
// getContentTypeFor() uses mime types from
// JAVA_HOME/lib/content-types.properties or
// JAVA_HOME/jre/lib/content-types.properties
--->
<cfset URLConnection = CreateObject("Java","java.net.URLConnection")>
<cfset myMimeType = URLConnection.getFileNameMap().getContentTypeFor(file)>

<!--- if the file extension isn't found in JAVA_HOME/jre/lib/content-types.properties, then myMimeType isn't defined. Set it to text/plain --->
<cfif not isDefined("myMimeType")><cfset myMimeType = "text/plain"></cfif>

<cfheader name="Content-Disposition" value='inline; filename="#file#"'>
<cfcontent type="#myMimeType#" deletefile="No" file="#APPLICATION.ResourcesRoot#/#file#">
June 19, 2006
Hi Kronin,

Thanks for your reply :-) I got this error when I tried to use it:

The selected method getContentTypeFor was not found.
Either there are no methods with the specified method name and argument types, or the method getContentTypeFor is overloaded with arguments types that ColdFusion can't decipher reliably. If this is a Java object and you verified that the method exists, you may need to use the javacast function to reduce ambiguity.


I guess I'm confused about how this will work if only the URL is called and not through the getFile.cfm file.

www.domain.com/login/resources/blah.pdf

thanks,

jo
Participating Frequently
June 19, 2006
> I got this error when I tried to use it:
> The selected method getContentTypeFor was not found.

What JDK do you have Coldfusion running under? What version?

> I guess I'm confused about how this will work if only the URL is called and not through the getFile.cfm file.
> www.domain.com/login/resources/blah.pdf

It won't. You'll need to get the file by going through getFile.cfm. You can put all the files in a location that isn't accessible through the web server, then you avoid the problem of people being able to access them directly.