<!--- 
  Filename: SimpleFileExplorer2.cfm
  Author:   Nate Weiss (NMW)
  Purpose:  Provides an interface for exploring files and subfolders
            within the ows root
--->


<!--- The user can explore this folder and any nested subfolders --->
<!--- Assume that the parent of the folder that contains this ColdFusion --->
<!--- page (that is, the "ows" folder) should be considered explorable --->
<cfset baseFolder = expandPath("../")>

<!--- The SubfolderPath variable indicates the currently selected folder --->
<!--- (relative to the BaseFolder). Defaults to an empty string, meaning --->
<!--- that the BaseFolder will be current when the page first appears --->
<cfparam name="subfolderPath" type="string" default="">


<!--- Utility function to return the parent of a folder, simply by --->
<!--- treating the supplied path as a CFML list, with / and \ characters --->
<!--- as the delimiters. --->
<cffunction name="getFolderParent" output="false" returnType="string">
  <cfargument name="Folder">
  
  <!--- We'll start off assuming that the folder has no parent --->
  <cfset var parent = arguments.folder>

  <!--- If there is at least one element in the list --->  
  <cfif listLen(arguments.folder, "/\") gt 0>
    <!--- Remove the last element and return the rest --->
    <cfset parent = listDeleteAt(arguments.folder, arguments.listLen(folder, "/\"), "/\")>
  </cfif>

  <!--- Return the result --->  
  <cfreturn parent>
</cffunction>


<!--- If the user wants to create a folder --->
<cfif isDefined("FORM.createFolder") and FORM.folderToCreate neq "">
  <cfset newDirectory = baseFolder & 
    "#FORM.currentSubfolderPath#/#FORM.folderToCreate#">

  <!--- Assuming that the folder doesn't already exist --->
  <cfif NOT directoryExists(newDirectory)>
    <cfdirectory action="Create" directory="#newDirectory#">
  </cfif>  

  <!--- Now consider the new folder to be the current selection --->
  <cfset subfolderPath = "#FORM.currentSubfolderPath#/#FORM.folderToCreate#">
</cfif>

<!--- If the user wants to delete a folder --->
<cfif IsDefined("FORM.deleteFolder")>
  <cfset dirToDelete = "#baseFolder#/#FORM.currentSubfolderPath#">

  <!--- Attempt to delete the folder --->
  <cfdirectory action="Delete" directory="#dirToDelete#">

  <!--- Now consider the deleted folder's parent to be current selection --->  
  <cfset subfolderPath = getFolderParent(FORM.currentSubfolderPath)>
</cfif>

<!--- This variable, then, is the full path of the selected folder --->
<cfset folderToDisplay = baseFolder & subfolderPath>

<!--- Is the user currently at the top level? --->
<cfset isAtTopLevel = listLen(subfolderPath, '/') eq 0>

<!--- Get a listing of the selected folder --->
<cfdirectory directory="#folderToDisplay#" name="directoryQuery" sort="Name ASC" filter="*">
    
<cfoutput>
  <html>
    <head><title>Simple File Explorer</title></head>
  <body>
  <h3>Simple File Explorer</h3>
  
  <!--- Create a simple form for navigating through folders --->
  <form action="SimpleFileExplorer.cfm" method="post">
  
    <input type="hidden" name="currentSubfolderPath" value="#subfolderPath#">
  
    <!--- Show the subfolder path, unless already at top level --->
    <cfif subfolderPath EQ "">
      You are at the top level.<br>
    <cfelse>
      Current Folder: #subfolderPath#

      <cfif directoryQuery.recordCount eq 0>
        <input type="submit" name="deleteFolder" value="Delete">
      </cfif><br>
    </cfif>
    
    <!--- Provide a drop-down list of subfolder names --->
    Select folder:&nbsp;
    <select name="subfolderPath" onchange="this.form.submit()">
    
      <!--- Provide an option to go up one level to the parent folder, --->
      <!--- unless already at the BaseFolder --->
      <cfif not isAtTopLevel>
        <cfset parentFolder = getFolderParent(subfolderPath)>
        <option value="#parentFolder#">[parent folder]
      </cfif>
      
      <!--- For each record in the query returned by <CFDIRECTORY> --->
      <cfloop query="directoryQuery">
        <!--- If the record represents a subfolder, list it as an option --->
        <cfif Type eq "Dir">
          <option value="#subfolderPath#/#Name#">#Name#
        </cfif>
      </cfloop>  
    </select>
    
    <!--- Submit button to navigate to the selected folder --->
    <input type="submit" value="Go"><br>
    
    Create folder:
    <input type="text" name="folderToCreate" value="">
    <input type="Submit" name="createFolder" value="OK"><br>

  </form>  
  
  
  <!--- Use Query of Queries (In Memory Query) to get a subset of --->
  <!--- the query returned by <CFDIRECTORY>. This new query object --->
  <!--- will hold only the file records, not any subfolder records --->
  <cfquery dbtype="query" name="filesQuery">
    SELECT * FROM directoryQuery
    WHERE TYPE = 'File'
  </cfquery>
    
  <!--- If there is at least one file to display... --->  
  <cfif filesQuery.recordCount gt 0>
    <!--- Display the files in a simple HTML table --->
    <table width="500" border="0" cellpadding="2" cellspacing="0">
      <tr bgcolor="cornflowerblue">
        <th>Filename</th>
        <th>Modified</th>
        <th>Size</th>
      </tr>
  
      <!--- For each file... --->
      <cfloop query="filesQuery">
        <!--- Use alternating colors for the table rows --->
        <!--- This is explained in the "Next N" examples from Chapter 21 --->
        <cfif filesQuery.currentRow mod 2 eq 0>
          <cfset rowcolor = "lightgrey">
        <cfelse>  
          <cfset rowcolor = "white">
        </cfif>

        <!--- Display the file details --->      
        <tr bgcolor="#rowColor#">
          <!--- File name --->
          <td width="250">
            #Name#
          </td>
          <!--- File modification date and time --->
          <td width="200">
            #dateFormat(DateLastModified, "m/d/yyyy")#
            at 
            #timeFormat(DateLastModified, "h:mm:ss tt")#
          </td>
          <!--- File size --->
          <td width="50" align="right">
            #ceiling(Size / 1024)# KB
          </td>
        </tr>
      </cfloop>  
    </table>
  </cfif>

  </body>
  </html>
</cfoutput>  