7 Replies Latest reply on Jun 24, 2008 3:21 PM by Newsgroup_User

    <cflocation to a file located 'above' the httpdocs folder

    happysailingdude Level 1
      hi guys, i got a tricky one here...

      users can upload word documents (.doc) to my server (using cffile).

      the idea is to only allow certain users access to those documents, therefore i am thinking that storing them 'above' the httpdocs folder is probably a wise move (that way no one can get to them using httpaccess, right?)

      i can write the files to my desired location using <cffile action="copy"... just fine

      the problem arrises in giving (the authorised) users access to those documents.

      i want them to be able to download those documents via their browser and had planned to do so using <cflocation url="#absoloute-path-to-required-document-on-server.doc#" >

      it seems this works fine if the file is within the httpdocs folder, but not if it's above it..

      does anyone have any suggestions?

      i'd be very grateful of any input whatsoever (if you think i'm tackling this the wrong way for example, i won't be offended :)

      thanks very much indeed.

      kind regards

      Nick
        • 1. Re: &lt;cflocation to a file located 'above' the httpdocs folder
          Kronin555 Level 1
          Instead of using cflocation (which would then give the user a URL that they could copy and send to anyone else, even the users that shouldn't have access to the .doc file, and they would be able to get it), have the link for your .doc file actually be to a .cfm file that:
          1. checks for authorized access
          2. sets the content-type header via
          <cfheader name="Content-Disposition" value="inline; filename=document.doc">
          3. does a <cfcontent...> that reads in the .doc file and sends it to the user
          <cfcontent deleteFile="no" file="#absolute-path-to-required-document-on-server.doc#" reset="yes" type="application/msword">
          • 2. Re: &lt;cflocation to a file located 'above' the httpdocs   folder
            Level 7
            To expand on Kronin's answer a bit.

            A <cflocation...> call does an HTTP 301 redirect, thus the end target
            must be HTTP accessible under a web root.


            The <cfcontent...> tag allows the server to retrieve content from
            anywhere and deliver it to the user dynamically without giving them
            direct access to this source.

            • 3. Re: &lt;cflocation to a file located 'above' the httpdocs   folder
              happysailingdude Level 1
              Thank you very much Kronin and Ian, that's really helpful - thank you.

              May I ask you 2 further quick questions please..

              1. I slightly simplified my situation in the interests of keeping my post clear, in reality some of the docs are word docs - but some are .rtf, some are .pdf and some are .txt

              looing at Kronin's post where he says "<cfcontent deleteFile="no" file="#absolute-path-to-required-document-on-server.doc#" reset="yes" type="application/msword">" it looks like i will need to also find out the "type" attributes for the .rtf, .pdf and .txt documents - anyone know what they are please?

              2. Ian you very kindly clarified that cflocation does an "HTTP 301 redirect" - does this mean that if someone has asked their browser to ignore http redirects (i think firefox facilitates this?) then in effect a cflocation tag would be ignored and the cfm page would keep on running through the code entered after that cflocation tag? - that's a bit scary as i use cflocate to 'bounce' anyone trying to access a page that they dont have authorisation to be on, ought i to go through all my code and stick in a cfabort tag immediately after any cflocation tags just in case?

              thanks ever so much, really appreciate your help :)

              Nick
              • 4. &lt;cflocation to a file located 'above' the httpdocs folder
                Kronin555 Level 1
                rtf = application/rtf
                pdf = application/pdf
                txt = text/plain

                I actually wrote some code to pull the mime-type using the requested filename. It uses Java to get the mime-type. If the filename's extension isn't listed in either of the locations below, then I default to setting it to text/plain. filename should be just the file name, not the whole path (so just myfile.doc, not /var/www/html/docs/myfile.doc or C:\blah\myfile.doc)
                <!---
                // 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(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>


                2. No. Once an HTTP redirect is sent, processing on that page stops.
                • 5. Re: &lt;cflocation to a file located 'above' the httpdocs     folder
                  Level 7
                  Kronin555 wrote:
                  > rtf = application/rtf
                  > pdf = application/pdf
                  > txt = text/plain

                  These are just 'mime' types. A quick Google search would find
                  documentation of any and every type you could ever care to use.

                  >
                  > 2. No. Once an HTTP redirect is sent, processing on that page stops.

                  Yes, a user who did not allow a relocation would just receive notice
                  that a relocation request was sent, what would they like to do about it.
                  They have noway to access the page relocated from.

                  P.S. If you want clean downloads using the <cfcontent...> method there
                  are some headers you would probably want to set as well to inform the
                  browser the proper file name and extension of the download. This is
                  well discussed and blogged all over the internet and full examples are
                  plentiful.


                  • 6. &lt;cflocation to a file located 'above' the httpdocs folder
                    Kronin555 Level 1
                    > P.S. If you want clean downloads using the <cfcontent...> method there
                    are some headers you would probably want to set as well to inform the
                    browser the proper file name and extension of the download. This is
                    well discussed and blogged all over the internet and full examples are
                    plentiful.

                    Ian, do you mean like the <cfheader...> tag I posted in my original reply?
                    <cfheader name="Content-Disposition" value="inline; filename=document.doc">

                    The full code I use to push files to users is as follows. Save this as getFile.cfm, update the fileshareroot variable, update the code that checks that the user has valid access rights, and access by sending a user the url: http://myserver.com/getFile.cfm?filename=myFileToGet.ext

                    <cfparam name="filename">
                    <cfset fileshareroot="/my/fileshare/root">

                    <!--- verify user can access this file. --->
                    <cfset validAccess = false>
                    <cfif userCanAccess> <!--- must be customized --->
                    <cfset validAccess = true>
                    </cfif>
                    <cfif not validAccess>
                    You are not authorized to view this document.
                    <cfabort>
                    </cfif>

                    <!--- verify document exists --->
                    <cfif not FileExists("#FileshareRoot#/#filename#")>
                    The document you requested doesn't exist.
                    <cfabort>
                    </cfif>

                    <!---
                    // 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(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="#FileshareRoot#/#filename#">
                    • 7. Re: &lt;cflocation to a file located 'above' the httpdocs       folder
                      Level 7
                      Yes those are fine examples that I forgot you posted.