views:

138

answers:

6

I am often tasked with making specialty websites for the professors at my university. Recently a professor asked me to create a site with nothing except links to files. I told him that would be easy because as long as the site didn't include an index all the file links would display automagically (yeah I did). To my dismay the university servers do not do what I expected them to do, and although I know it is possible to implement this listing of files for the web site in question, I do not have the authority to do it.

I am in the process of making a simple PHP script that lists files and directories (and their associated download links) but I am wondering if something like this already exists that is perhaps already all polished up and ready to go. Does anyone know of such an application that I can just drop into place? Glitter is not required, but I would consider a simple one or a pretty one.

Oh yeah, it needs to be in PHP or ColdFusion

My server's is running ColdFusion 7,0,2,142559 and PHP 4.3.9

+4  A: 

I know you said that you don't have the authority to enable virtual directory listing for the professor's directory, but my advice is to speak with the admin who could make that call and ask them to enable it. If they refuse, chances are replicating that functionality would be denied for the same reason (whatever that happens to be).

It'll save you time either way, because either you can just let Apache (or whatever webserver) do what it's easily able to do, or you don't waste time building something that you will have to take down.

Daniel Vandersluis
It's generally possible to enable or disable directory listing on a *per directory* basis.
KatieK
@ Daniel Vandersluis I haven't even bothered asking because I am 99% sure I'll get shot down, not because of any real security issue, but just because they don't want to change anything. Still I will ask and see what happens. If I get shot down I'll probably just finish up the PHP script I started on, I don't think they will mind that (me doing the work).
typoknig
@typoknig If they don't mind you doing the work, then logically they shouldn't mind spending 5 seconds making a change to httpd.conf (or whatever file applies)... then again, people with authority in our industry often aren't logical ;)
Daniel Vandersluis
Why was this downvoted?
Daniel Vandersluis
@Daniel Vandersluis not sure, but I hate that (question was downvoted too with no explanation).
typoknig
+1  A: 

Hello,

You could put this in an index.php in the needed folders.

function outputRow($relPath, $isDir = false){
        // you could do something special for directories //
        echo '<a href="'.$relPath.'">'.$relPath.'</a>';
}

$dirPath = dirname(__FILE__);
$fileList = scandir( $dirPath );

foreach($fileList as $file){
    if($file == '.' || $file == 'index.php')
        continue 1;

    outputRow($file, is_dir($dirPath.'/'.$file));
}

Can't think of anything simpler than this.

Regards, Alin

Alin Purcaru
continue 1; is equivalent to continue;
Alin Purcaru
you can use preg_match('/\.([^\.]+)$/', $relPath, $extension); to detect the extension and show different icons for it and use $isDir to show dir icons for folders; you can use the icons from famfamfam for free if you like them
Alin Purcaru
@Alin Purcaru: Or use `pathinfo()` to get information. Or even better use the FileInfo object and `finfo_file()` to get the MIME type and display the icon based on that.
poke
anything simpler? here you go: `<? foreach (glob("*") as $file): ?><li><a href="<?=$file?>"><?=$file?></a><? endforeach ?>`
Col. Shrapnel
there is a difference between simple and short
Alin Purcaru
Oh really? You can tell that difference I presume?
Col. Shrapnel
Yes: the property of being easy to read, understand, modify. I can assume that you don't write all your code on the same line just to save some bytes and I hope you add some comments once in a while.
Alin Purcaru
this code has been formed in one line only because this comment won't let me any other form. Though you can write it in 10 and it still be simpler and at the same time more readable and more reliable.
Col. Shrapnel
+1  A: 

There are lots of examples on the web. Personally I wouldn't bother finding a library etc, as the code is pretty small to implement. Try this (an example I have searched for, but I have used in the past).

// open this directory 
$myDirectory = opendir(".");

// get each entry
while($entryName = readdir($myDirectory)) {
    $dirArray[] = $entryName;
}

// close directory
closedir($myDirectory);

//  count elements in array
$indexCount = count($dirArray);
Print ("$indexCount files<br>\n");

// sort 'em
sort($dirArray);

// print 'em
print("<TABLE border=1 cellpadding=5 cellspacing=0 class=whitelinks>\n");
print("<TR><TH>Filename</TH><th>Filetype</th><th>Filesize</th></TR>\n");
// loop through the array of files and print them all
for($index=0; $index < $indexCount; $index++) {
        if (substr("$dirArray[$index]", 0, 1) != "."){ // don't list hidden files
        print("<TR><TD><a href=\"$dirArray[$index]\">$dirArray[$index]</a></td>");
        print("<td>");
        print(filetype($dirArray[$index]));
        print("</td>");
        print("<td>");
        print(filesize($dirArray[$index]));
        print("</td>");
        print("</TR>\n");
    }
}
print("</TABLE>\n");
Codemwnci
yeah. There are lots of examples of such a dirty coding style
Col. Shrapnel
@Col. Shrapnel why is this "dirty"? I ask because the script I made for myself is very similar. It does work though.
typoknig
i didn't say it isn't working
Col. Shrapnel
@Col. Shrapnel yeah I know, I was just asking why you thought it was "dirty" and also saying at the same time that it does indeed work :)
typoknig
learn templates
Col. Shrapnel
+1  A: 

You haven't mentioned what is your web-server. In case of Apache you can put the .htaccess file with Options +Indexes and you're done.

Any way, very quick and very simple (previously I called it dirty, this is not true :) solution in CFML (let's say this is index.cfm file):

<!--- read all files recursively --->
<cfdirectory action="list" directory="#ExpandPath('.')#" name="qListDirectory" recurse="true" sort="directory ASC, name ASC" type="file" />

<!--- these paths used for building clean related-path links --->
<cfset baseURL = GetDirectoryFromPath(cgi.SCRIPT_NAME) />
<cfset basePath = GetDirectoryFromPath(cgi.PATH_TRANSLATED) />

<!--- list all files with directories except special and hidden --->
<cfoutput>
<ul>
<cfloop query="qListDirectory">
    <cfif NOT ListFind("index.cfm,Application.cfm,Application.cfc", qListDirectory.name) AND Left(qListDirectory.name,1) NEQ ".">
        <cfset thisPath = ReplaceNoCase(qListDirectory.directory, basePath, "") />
        <li><a href="#baseURL##thisPath#/#HTMLEditFormat(qListDirectory.name)#">#thisPath#/#HTMLEditFormat(qListDirectory.name)#</a></li>
    </cfif>
</cfloop>
</ul>
</cfoutput>

You can easily modify this to group files by directory (nested lists).

If you want true replication of web-server listing feature -- it may be possible to use Application.cfc to catch the requests in the nested folders without copying index.cfm

Please comment and I'll try this.

Sergii
The "Options +Indexes" in .htaccess thing will only work if Apache is set up to allow .htaccess files and to allow that particular option. Still, it's worth a try.
James
I said in my question I do not have the authority to make the changes myself, but we are using Apache. I do not have access to `htaccess`
typoknig
@typoknig you don't have to have access to this file. You have to create it.
Col. Shrapnel
@Col. Shrapnel what I meant was I do not have access to enable/disable directory listing, nor do I have the ability to use `htaccess`, their use has been disabled.
typoknig
@typoknig Sorry, that was not really obvious from your question. Any way, now you should stick to the CFML/PHP solution. Please update your posting to include the web-server details and ColdFusion version you have -- this will help to find better solution.
Sergii
@Sergii I have update the question listing the server's versions of PHP and ColdFusion.
typoknig
+2  A: 

see

<?
$dirArray = glob("*");
?>
<table border=1 cellpadding=5 cellspacing=0 class=whitelinks>
 <tr>
  <th>Filename</TH><th>Filetype</th><th>Filesize</th>
 </tr>
<? foreach ($dirArray as $file): ?>
 <tr>
  <td><a href="<?=$file?>"><?=$file?></a></td>
  <td><?=filetype($file)?></td>
  <td><?=filesize($file)?></td>
 </tr>
<? endforeach ?>
</table>
Col. Shrapnel
@Col. Shrapnel this does not work (error on line 11 it says) but I see what you are getting at with your templates suggestion.
typoknig
@typoknig it was a silly typo that was already corrected.
Col. Shrapnel
+1  A: 

Another ColdFusion version, this one lists size and date-modified (just like a directory index):

<!--- index.cfm, put into directory --->
<cffunction name="PrettySize" output="false">
    <cfargument name="size" type="Numeric">
    <cfif arguments.size GT 1048576>
        <cfreturn Fix(arguments.size/104857.6)/10 & ' MB'>
    <cfelseif arguments.size GT 1024>
        <cfreturn Fix(arguments.size/10.24)/100 & ' KB'>
    <cfelse>
        <cfreturn arguments.size & ' bytes'>
    </cfif>
</cffunction>
<cfdirectory action="list" directory="#GetDirectoryFromPath(ExpandPath("./"))#" name="Files">
<table>
    <thead>
        <tr>
        <td>Name</td>
        <td>Last Modified</td>
        <td>Size</td>
        </tr>
    </thead>
    <tbody>
        <cfoutput query="Files"><cfif Files.Name NEQ 'index.cfm'>
        <tr>
        <td><a href="./#Files.Name#">#Files.Name#</a></td>
        <td>#DateFormat(Files.DateLastModified)# #TimeFormat(Files.DateLastModified)#</td>
        <td>#PrettySize(Files.Size)#</td>
        </tr>
        </cfif></cfoutput>
    </tbody>
</table>

In theory, I think you could put this code into an Application.cfm file at the root of whatever directories you want to add. Then, just make sure that there's an empty index.cfm file in each directory where you want an index, and it should create it for you.

Jordan Reiter